diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 6cc5e3547ba..b5e46fb8107 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -13,3 +13,7 @@ # Whitespace trimming throughout codebase 9bb69e711a5da43aaf8c8ecb5601aeffd89dbe5a +f0bcb753fb7ebbb64bb0d6906d431d002f0f7d8f + +# imports cleanup +4b2be2999f2203493b49bf74c5b440d49e38b5e3 diff --git a/.github/helper/.flake8_strict b/.github/helper/.flake8_strict new file mode 100644 index 00000000000..4c7f5f82cfb --- /dev/null +++ b/.github/helper/.flake8_strict @@ -0,0 +1,70 @@ +[flake8] +ignore = + B007, + B950, + E101, + E111, + E114, + E116, + E117, + E121, + E122, + E123, + E124, + E125, + E126, + E127, + E128, + E131, + E201, + E202, + E203, + E211, + E221, + E222, + E223, + E224, + E225, + E226, + E228, + E231, + E241, + E242, + E251, + E261, + E262, + E265, + E266, + E271, + E272, + E273, + E274, + E301, + E302, + E303, + E305, + E306, + E402, + E501, + E502, + E701, + E702, + E703, + E741, + F403, + W191, + W291, + W292, + W293, + W391, + W503, + W504, + E711, + E129, + F841, + E713, + E712, + + +max-line-length = 200 +exclude=.github/helper/semgrep_rules,test_*.py diff --git a/.github/helper/documentation.py b/.github/helper/documentation.py index b4a4ba1bbdd..9150e08aaf9 100644 --- a/.github/helper/documentation.py +++ b/.github/helper/documentation.py @@ -1,7 +1,7 @@ import sys -import requests from urllib.parse import urlparse +import requests docs_repos = [ "frappe_docs", @@ -24,6 +24,8 @@ def docs_link_exists(body): parts = parsed_url.path.split('/') if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos: return True + elif parsed_url.netloc == "docs.erpnext.com": + return True if __name__ == "__main__": diff --git a/.github/helper/semgrep_rules/frappe_correctness.py b/.github/helper/semgrep_rules/frappe_correctness.py index 745e6463b8a..4373e88451c 100644 --- a/.github/helper/semgrep_rules/frappe_correctness.py +++ b/.github/helper/semgrep_rules/frappe_correctness.py @@ -1,6 +1,5 @@ import frappe -from frappe import _, flt - +from frappe import _ from frappe.model.document import Document diff --git a/.github/helper/semgrep_rules/report.py b/.github/helper/semgrep_rules/report.py new file mode 100644 index 00000000000..e3a265e407b --- /dev/null +++ b/.github/helper/semgrep_rules/report.py @@ -0,0 +1,14 @@ +from frappe import _ + +# ruleid: frappe-missing-translate-function-in-report-python +{"label": "Field Label"} + +# ruleid: frappe-missing-translate-function-in-report-python +dict(label="Field Label") + + +# ok: frappe-missing-translate-function-in-report-python +{"label": _("Field Label")} + +# ok: frappe-missing-translate-function-in-report-python +dict(label=_("Field Label")) diff --git a/.github/helper/semgrep_rules/report.yml b/.github/helper/semgrep_rules/report.yml new file mode 100644 index 00000000000..f2a9b167399 --- /dev/null +++ b/.github/helper/semgrep_rules/report.yml @@ -0,0 +1,34 @@ +rules: +- id: frappe-missing-translate-function-in-report-python + paths: + include: + - "**/report" + exclude: + - "**/regional" + pattern-either: + - patterns: + - pattern: | + {..., "label": "...", ...} + - pattern-not: | + {..., "label": _("..."), ...} + - patterns: + - pattern: dict(..., label="...", ...) + - pattern-not: dict(..., label=_("..."), ...) + message: | + All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations + languages: [python] + severity: ERROR + +- id: frappe-translated-values-in-business-logic + paths: + include: + - "**/report" + patterns: + - pattern-inside: | + {..., filters: [...], ...} + - pattern: | + {..., options: [..., __("..."), ...], ...} + message: | + Using translated values in options field will require you to translate the values while comparing in business logic. Instead of passing translated labels provide objects that contain both label and value. e.g. { label: __("Option value"), value: "Option value"} + languages: [javascript] + severity: ERROR diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py index a00d3cd8aef..fa97c1e9f08 100644 --- a/.github/helper/semgrep_rules/ux.py +++ b/.github/helper/semgrep_rules/ux.py @@ -1,6 +1,5 @@ import frappe -from frappe import msgprint, throw, _ - +from frappe import _, msgprint, throw # ruleid: frappe-missing-translate-function-python throw("Error Occured") diff --git a/.github/workflows/semgrep.yml b/.github/workflows/linters.yml similarity index 56% rename from .github/workflows/semgrep.yml rename to .github/workflows/linters.yml index e27b406df05..c2363397c47 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/linters.yml @@ -1,11 +1,12 @@ -name: Semgrep +name: Linters on: pull_request: { } jobs: - semgrep: - name: Frappe Linter + + linters: + name: linters runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -16,3 +17,11 @@ jobs: config: >- r/python.lang.correctness .github/helper/semgrep_rules + + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install and Run Pre-commit + uses: pre-commit/action@v2.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000000..2b3a471f774 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +exclude: 'node_modules|.git' +default_stages: [commit] +fail_fast: false + + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: trailing-whitespace + files: "erpnext.*" + exclude: ".*json$|.*txt$|.*csv|.*md" + - id: check-yaml + - id: no-commit-to-branch + args: ['--branch', 'develop'] + - id: check-merge-conflict + - id: check-ast + + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.9.2 + hooks: + - id: flake8 + args: ['--config', '.github/helper/.flake8_strict'] + exclude: ".*setup.py$" + + - repo: https://github.com/timothycrosley/isort + rev: 5.9.1 + hooks: + - id: isort + exclude: ".*setup.py$" + +ci: + autoupdate_schedule: weekly + skip: [] + submodules: false diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a988d7217db..2cdf1bf1829 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + import inspect + import frappe + from erpnext.hooks import regional_overrides -from frappe.utils import getdate __version__ = '13.2.0' diff --git a/erpnext/accounts/custom/address.py b/erpnext/accounts/custom/address.py index 834227bb586..a6d08d8ff61 100644 --- a/erpnext/accounts/custom/address.py +++ b/erpnext/accounts/custom/address.py @@ -1,7 +1,11 @@ import frappe from frappe import _ -from frappe.contacts.doctype.address.address import Address -from frappe.contacts.doctype.address.address import get_address_templates, get_address_display +from frappe.contacts.doctype.address.address import ( + Address, + get_address_display, + get_address_templates, +) + class ERPNextAddress(Address): def validate(self): @@ -31,7 +35,7 @@ class ERPNextAddress(Address): customers = frappe.db.get_all("Customer", filters=filters, as_list=True) for customer_name in customers: frappe.db.set_value("Customer", customer_name[0], "primary_address", address_display) - + @frappe.whitelist() def get_shipping_address(company, address = None): filters = [ diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py index 85f54f98ba8..5eb857719a9 100644 --- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py +++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py @@ -2,14 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json + +import frappe from frappe import _ -from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate, get_link_to_form -from erpnext.accounts.report.general_ledger.general_ledger import execute +from frappe.utils import add_to_date, formatdate, get_link_to_form, getdate, nowdate from frappe.utils.dashboard import cache_source from frappe.utils.dateutils import get_from_date_from_timespan, get_period_ending from frappe.utils.nestedset import get_descendants_of + @frappe.whitelist() @cache_source def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index 0c81d83ed8e..bcd07718a59 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -2,11 +2,26 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, get_first_day, cint, get_link_to_form, rounded -from erpnext.accounts.utils import get_account_currency from frappe.email import sendmail_to_system_managers -from frappe.utils.background_jobs import enqueue -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from frappe.utils import ( + add_days, + add_months, + cint, + date_diff, + flt, + get_first_day, + get_last_day, + get_link_to_form, + getdate, + rounded, + today, +) + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) +from erpnext.accounts.utils import get_account_currency + def validate_service_stop_date(doc): ''' Validates service_stop_date for Purchase Invoice and Sales Invoice ''' @@ -359,7 +374,7 @@ def make_gl_entries(doc, credit_account, debit_account, against, try: make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True) frappe.db.commit() - except: + except Exception: frappe.db.rollback() traceback = frappe.get_traceback() frappe.log_error(message=traceback) @@ -430,7 +445,7 @@ def book_revenue_via_journal_entry(doc, credit_account, debit_account, against, if submit: journal_entry.submit() - except: + except Exception: frappe.db.rollback() traceback = frappe.get_traceback() frappe.log_error(message=traceback) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index f763df0852b..f6198eb23ba 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _, throw from frappe.utils import cint, cstr -from frappe import throw, _ from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of + class RootNotEditable(frappe.ValidationError): pass class BalanceMismatchError(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index 927adc7086c..d6ccd169362 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals +import json +import os -import frappe, os, json +import frappe from frappe.utils import cstr -from unidecode import unidecode -from six import iteritems from frappe.utils.nestedset import rebuild_tree +from six import iteritems +from unidecode import unidecode + def create_charts(company, chart_template=None, existing_company=None, custom_chart=None): chart = custom_chart or get_chart(chart_template, existing_company) @@ -91,11 +94,14 @@ def get_chart(chart_template, existing_company=None): return get_account_tree_from_existing_company(existing_company) elif chart_template == "Standard": - from erpnext.accounts.doctype.account.chart_of_accounts.verified import standard_chart_of_accounts + from erpnext.accounts.doctype.account.chart_of_accounts.verified import ( + standard_chart_of_accounts, + ) return standard_chart_of_accounts.get() elif chart_template == "Standard with Numbers": - from erpnext.accounts.doctype.account.chart_of_accounts.verified \ - import standard_chart_of_accounts_with_account_number + from erpnext.accounts.doctype.account.chart_of_accounts.verified import ( + standard_chart_of_accounts_with_account_number, + ) return standard_chart_of_accounts_with_account_number.get() else: folders = ("verified",) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py index eb3e7ffd906..72223573a23 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py @@ -6,12 +6,13 @@ Import chart of accounts from OpenERP sources """ from __future__ import print_function, unicode_literals -import os, json import ast +import json +import os from xml.etree import ElementTree as ET -from frappe.utils.csvutils import read_csv_content -import frappe +import frappe +from frappe.utils.csvutils import read_csv_content from six import iteritems path = "/Users/nabinhait/projects/odoo/addons" diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py index 161e52a67d0..f058afba6a7 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get(): return { _("Application of Funds (Assets)"): { diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py index acb11e557a5..9f339520356 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get(): return { _("Application of Funds (Assets)"): { diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index 533eda31d58..0c3b33e0b9e 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -2,10 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest + import frappe -from erpnext.stock import get_warehouse_account, get_company_default_inventory_account -from erpnext.accounts.doctype.account.account import update_account_number, merge_account + +from erpnext.accounts.doctype.account.account import merge_account, update_account_number +from erpnext.stock import get_company_default_inventory_account, get_warehouse_account + class TestAccount(unittest.TestCase): def test_rename_account(self): diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index fac28c92397..af8255f9448 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -3,15 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import _ + import json -from frappe.model.document import Document + +import frappe +from frappe import _, scrub from frappe.custom.doctype.custom_field.custom_field import create_custom_field -from frappe import scrub -from frappe.utils import cstr -from frappe.utils.background_jobs import enqueue from frappe.model import core_doctypes_list +from frappe.model.document import Document +from frappe.utils import cstr + class AccountingDimension(Document): def before_insert(self): @@ -47,9 +48,9 @@ class AccountingDimension(Document): def on_trash(self): if frappe.flags.in_test: - delete_accounting_dimension(doc=self, queue='long') + delete_accounting_dimension(doc=self) else: - frappe.enqueue(delete_accounting_dimension, doc=self) + frappe.enqueue(delete_accounting_dimension, doc=self, queue='long') def set_fieldname_and_label(self): if not self.label: diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index 4f3ee7643ab..3769fc12707 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -3,10 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + +import frappe + from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice test_dependencies = ['Cost Center', 'Location', 'Warehouse', 'Department'] diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py index 17cf549fc45..c116f164536 100644 --- a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py @@ -3,8 +3,10 @@ # 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/accounting_dimension_filter/accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py index 6aef9caa747..cb8c7d1c984 100644 --- a/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py +++ b/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _, scrub from frappe.model.document import Document + class AccountingDimensionFilter(Document): def validate(self): self.validate_applicable_accounts() diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py index 7f6254f99f5..9968f689916 100644 --- a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py +++ b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py @@ -3,10 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + +from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import ( + create_dimension, + disable_dimension, +) from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import create_dimension, disable_dimension from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError test_dependencies = ['Location', 'Cost Center', 'Department'] diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index 739d8f6bc63..67d1a8a09bd 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class OverlapError(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py index dc472c7695d..5885b58e481 100644 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py @@ -3,12 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, add_months -from erpnext.accounts.general_ledger import ClosedAccountingPeriod + +import frappe +from frappe.utils import add_months, nowdate + from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.general_ledger import ClosedAccountingPeriod test_dependencies = ['Item'] diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 62c97f24d5f..f54473351a2 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -4,11 +4,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cint -from frappe.model.document import Document from frappe.custom.doctype.property_setter.property_setter import make_property_setter +from frappe.model.document import Document +from frappe.utils import cint class AccountsSettings(Document): diff --git a/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.py index 014cf45e518..c1c156fa65e 100644 --- a/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import unittest import frappe diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py index 597d2ccc625..0c98f248746 100644 --- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py +++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AdvanceTaxesandCharges(Document): pass diff --git a/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py b/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py index c2afc1a2621..b5e7ad3fbe2 100644 --- a/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py +++ b/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AllowedDimension(Document): pass diff --git a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py index a3e4bbcd094..3e84c3071b0 100644 --- a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py +++ b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class AllowedToTransactWith(Document): pass diff --git a/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py b/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py index 0fccaf302fb..91331fadd51 100644 --- a/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py +++ b/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ApplicableOnAccount(Document): pass diff --git a/erpnext/accounts/doctype/bank/bank.py b/erpnext/accounts/doctype/bank/bank.py index 99fa21c8f9a..e1eb984f5f5 100644 --- a/erpnext/accounts/doctype/bank/bank.py +++ b/erpnext/accounts/doctype/bank/bank.py @@ -3,9 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) from frappe.model.document import Document -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address + class Bank(Document): def onload(self): diff --git a/erpnext/accounts/doctype/bank/test_bank.py b/erpnext/accounts/doctype/bank/test_bank.py index d8741f24c54..62d14d6fc63 100644 --- a/erpnext/accounts/doctype/bank/test_bank.py +++ b/erpnext/accounts/doctype/bank/test_bank.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestBank(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index 3e08c2812ef..703f55de807 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -3,10 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) from frappe.model.document import Document -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address + class BankAccount(Document): def onload(self): diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.py b/erpnext/accounts/doctype/bank_account/test_bank_account.py index ed34d17ee74..dc970f3d99e 100644 --- a/erpnext/accounts/doctype/bank_account/test_bank_account.py +++ b/erpnext/accounts/doctype/bank_account/test_bank_account.py @@ -3,11 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe -from frappe import _ -from frappe import ValidationError import unittest +import frappe +from frappe import ValidationError + # test_records = frappe.get_test_records('Bank Account') class TestBankAccount(unittest.TestCase): diff --git a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py index ab52c4af77c..84fa0c92b80 100644 --- a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py +++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class BankAccountSubtype(Document): pass diff --git a/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py index ca3addc979d..d4eb88b3656 100644 --- a/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py +++ b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestBankAccountSubtype(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.py b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py index b7dc0e0dc37..bba43dc486c 100644 --- a/erpnext/accounts/doctype/bank_account_type/bank_account_type.py +++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class BankAccountType(Document): pass diff --git a/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py index f04725a2e55..00fd4338d22 100644 --- a/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py +++ b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBankAccountType(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index 79f5596384c..340b4481785 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt, getdate, nowdate, fmt_money -from frappe import msgprint, _ +from frappe import _, msgprint from frappe.model.document import Document +from frappe.utils import flt, fmt_money, getdate, nowdate form_grid_templates = { "journal_entries": "templates/form_grid/bank_reconciliation_grid.html" diff --git a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py index 833abde5ce3..bdf3c7f48ae 100644 --- a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBankClearance(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py index 59299f81e50..1b23400cd37 100644 --- a/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py +++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class BankClearanceDetail(Document): pass diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py index a0aac6ab170..8043c5f04e5 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py @@ -3,10 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe.model.document import Document + +import json + +import frappe from frappe import _ from frappe.desk.search import sanitize_searchfield +from frappe.model.document import Document + class BankGuarantee(Document): def validate(self): diff --git a/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.py b/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.py index 816743a9b03..5cd455fd6c6 100644 --- a/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.py +++ b/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestBankGuarantee(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 8a17233cf74..ce64ee4f5a2 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -3,17 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals + import json import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document from frappe.utils import flt from erpnext import get_company_currency -from erpnext.accounts.utils import get_balance_on -from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import get_entries, get_amounts_not_reflected_in_system from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_paid_amount +from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import ( + get_amounts_not_reflected_in_system, + get_entries, +) +from erpnext.accounts.utils import get_balance_on class BankReconciliationTool(Document): diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py index d96950abbce..55b83b6bdfe 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBankReconciliationTool(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py index ffc9d1c4658..25d1023c270 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py @@ -3,22 +3,22 @@ # For license information, please see license.txt from __future__ import unicode_literals + import csv import json import re +import frappe import openpyxl +from frappe import _ +from frappe.core.doctype.data_import.data_import import DataImport +from frappe.core.doctype.data_import.importer import Importer, ImportFile +from frappe.utils.background_jobs import enqueue +from frappe.utils.xlsxutils import ILLEGAL_CHARACTERS_RE, handle_html from openpyxl.styles import Font from openpyxl.utils import get_column_letter from six import string_types -import frappe -from frappe.core.doctype.data_import.importer import Importer, ImportFile -from frappe.utils.background_jobs import enqueue -from frappe.utils.xlsxutils import handle_html, ILLEGAL_CHARACTERS_RE -from frappe import _ - -from frappe.core.doctype.data_import.data_import import DataImport class BankStatementImport(DataImport): def __init__(self, *args, **kwargs): diff --git a/erpnext/accounts/doctype/bank_statement_import/test_bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/test_bank_statement_import.py index cd5831412d9..5b45fa204bf 100644 --- a/erpnext/accounts/doctype/bank_statement_import/test_bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/test_bank_statement_import.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBankStatementImport(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 7ea71fc103a..c4cf37e0c82 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from erpnext.controllers.status_updater import StatusUpdater from frappe.utils import flt from six.moves import reduce -from frappe import _ + +from erpnext.controllers.status_updater import StatusUpdater + class BankTransaction(StatusUpdater): def after_insert(self): @@ -21,7 +23,7 @@ class BankTransaction(StatusUpdater): self.update_allocations() self.clear_linked_payment_entries() self.set_status(update=True) - + def on_cancel(self): self.clear_linked_payment_entries(for_cancel=True) self.set_status(update=True) @@ -45,7 +47,7 @@ class BankTransaction(StatusUpdater): frappe.db.set_value(self.doctype, self.name, "status", "Reconciled") self.reload() - + def clear_linked_payment_entries(self, for_cancel=False): for payment_entry in self.payment_entries: if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]: @@ -77,7 +79,7 @@ class BankTransaction(StatusUpdater): def get_reconciled_bank_transactions(payment_entry): reconciled_bank_transactions = frappe.get_all( - 'Bank Transaction Payments', + 'Bank Transaction Payments', filters = { 'payment_entry': payment_entry.payment_entry }, diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py index dc3b8674700..e8d032be360 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe.utils import getdate from frappe.utils.dateutils import parse_date from six import iteritems + @frappe.whitelist() def upload_bank_statement(): if getattr(frappe, "uploaded_file", None): diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py index 439d4891194..35d08bd8033 100644 --- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py @@ -3,14 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest import json -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +import unittest + +import frappe + +from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import ( + get_linked_payments, + reconcile_vouchers, +) from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry -from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import reconcile_vouchers, get_linked_payments from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice test_dependencies = ["Item", "Cost Center"] diff --git a/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py b/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py index 95a5bc33883..8b809fe705d 100644 --- a/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py +++ b/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class BankTransactionMapping(Document): pass diff --git a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py index d6d7c109cf5..2546f27a46e 100644 --- a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py +++ b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class BankTransactionPayments(Document): pass diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index d93b6ffbaf9..9c20e82f169 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -1,15 +1,20 @@ - # -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, getdate, add_months, get_last_day, fmt_money, nowdate -from frappe.model.naming import make_autoname -from erpnext.accounts.utils import get_fiscal_year from frappe.model.document import Document -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from frappe.model.naming import make_autoname +from frappe.utils import add_months, flt, fmt_money, get_last_day, getdate + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) +from erpnext.accounts.utils import get_fiscal_year + class BudgetError(frappe.ValidationError): pass class DuplicateBudgetError(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py index 6c25f0024d5..cc8220920e3 100644 --- a/erpnext/accounts/doctype/budget/test_budget.py +++ b/erpnext/accounts/doctype/budget/test_budget.py @@ -3,13 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, now_datetime + +import frappe +from frappe.utils import now_datetime, nowdate + +from erpnext.accounts.doctype.budget.budget import BudgetError, get_actual_expense +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry from erpnext.accounts.utils import get_fiscal_year from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order -from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError -from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry test_dependencies = ['Monthly Distribution'] diff --git a/erpnext/accounts/doctype/budget_account/budget_account.py b/erpnext/accounts/doctype/budget_account/budget_account.py index 81b2709ba8b..454e47d7a1a 100644 --- a/erpnext/accounts/doctype/budget_account/budget_account.py +++ b/erpnext/accounts/doctype/budget_account/budget_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class BudgetAccount(Document): pass diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py index cfe28f3ff9f..b1ab6481597 100644 --- a/erpnext/accounts/doctype/c_form/c_form.py +++ b/erpnext/accounts/doctype/c_form/c_form.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt from frappe import _ from frappe.model.document import Document +from frappe.utils import flt + class CForm(Document): def validate(self): diff --git a/erpnext/accounts/doctype/c_form/test_c_form.py b/erpnext/accounts/doctype/c_form/test_c_form.py index c4c95db0f24..e5c56157318 100644 --- a/erpnext/accounts/doctype/c_form/test_c_form.py +++ b/erpnext/accounts/doctype/c_form/test_c_form.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('C-Form') diff --git a/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.py b/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.py index 20e423a610e..1316227df91 100644 --- a/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.py +++ b/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CFormInvoiceDetail(Document): pass diff --git a/erpnext/accounts/doctype/campaign_item/campaign_item.py b/erpnext/accounts/doctype/campaign_item/campaign_item.py index 4f5fd7f7d78..d78fdf52858 100644 --- a/erpnext/accounts/doctype/campaign_item/campaign_item.py +++ b/erpnext/accounts/doctype/campaign_item/campaign_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class CampaignItem(Document): pass diff --git a/erpnext/accounts/doctype/cash_flow_mapper/cash_flow_mapper.py b/erpnext/accounts/doctype/cash_flow_mapper/cash_flow_mapper.py index 72515338378..96920b329e7 100644 --- a/erpnext/accounts/doctype/cash_flow_mapper/cash_flow_mapper.py +++ b/erpnext/accounts/doctype/cash_flow_mapper/cash_flow_mapper.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py b/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py index b1ad2972beb..9ec466a7a6d 100644 --- a/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py +++ b/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.py b/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.py index 499c820479e..5e44c61379b 100644 --- a/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.py +++ b/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + class TestCashFlowMapping(unittest.TestCase): def setUp(self): diff --git a/erpnext/accounts/doctype/cash_flow_mapping_accounts/cash_flow_mapping_accounts.py b/erpnext/accounts/doctype/cash_flow_mapping_accounts/cash_flow_mapping_accounts.py index fc63b8f9af6..51740353192 100644 --- a/erpnext/accounts/doctype/cash_flow_mapping_accounts/cash_flow_mapping_accounts.py +++ b/erpnext/accounts/doctype/cash_flow_mapping_accounts/cash_flow_mapping_accounts.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/cash_flow_mapping_template/cash_flow_mapping_template.py b/erpnext/accounts/doctype/cash_flow_mapping_template/cash_flow_mapping_template.py index 6f77a39bab9..fabf5796bcf 100644 --- a/erpnext/accounts/doctype/cash_flow_mapping_template/cash_flow_mapping_template.py +++ b/erpnext/accounts/doctype/cash_flow_mapping_template/cash_flow_mapping_template.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/cash_flow_mapping_template_details/cash_flow_mapping_template_details.py b/erpnext/accounts/doctype/cash_flow_mapping_template_details/cash_flow_mapping_template_details.py index e10b63829fd..f0ff33fb38f 100644 --- a/erpnext/accounts/doctype/cash_flow_mapping_template_details/cash_flow_mapping_template_details.py +++ b/erpnext/accounts/doctype/cash_flow_mapping_template_details/cash_flow_mapping_template_details.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py index 081c6fa4718..cab7d407b54 100644 --- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py +++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py @@ -3,10 +3,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _ from frappe.model.document import Document -from frappe.utils import cint, flt, cstr -from frappe import _, msgprint, throw +from frappe.utils import flt + class CashierClosing(Document): def validate(self): diff --git a/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.py b/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.py index 3c489a78727..981093f3d04 100644 --- a/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.py +++ b/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCashierClosing(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py b/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py index f73703158d8..a2a8b9437e4 100644 --- a/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py +++ b/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py @@ -3,8 +3,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CashierClosingPayments(Document): pass diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py index 8456b49c8ee..61968cf627d 100644 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py +++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py @@ -3,14 +3,26 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import csv +import os from functools import reduce -import frappe, csv, os + +import frappe from frappe import _ -from frappe.utils import cstr, cint from frappe.model.document import Document +from frappe.utils import cint, cstr from frappe.utils.csvutils import UnicodeWriter -from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts, build_tree_from_json -from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file, read_xls_file_from_attached_file +from frappe.utils.xlsxutils import ( + read_xls_file_from_attached_file, + read_xlsx_file_from_attached_file, +) + +from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import ( + build_tree_from_json, + create_charts, +) + class ChartofAccountsImporter(Document): def validate(self): diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.py index 6ab19b771bf..ca9cf699aa7 100644 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.py +++ b/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestChartofAccountsImporter(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py index d62ee9deeb5..0f595ba933a 100644 --- a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py +++ b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class ChequePrintTemplate(Document): pass diff --git a/erpnext/accounts/doctype/cheque_print_template/test_cheque_print_template.py b/erpnext/accounts/doctype/cheque_print_template/test_cheque_print_template.py index fa9c5b5eb09..8ce8794cfcf 100644 --- a/erpnext/accounts/doctype/cheque_print_template/test_cheque_print_template.py +++ b/erpnext/accounts/doctype/cheque_print_template/test_cheque_print_template.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Cheque Print Template') diff --git a/erpnext/accounts/doctype/closed_document/closed_document.py b/erpnext/accounts/doctype/closed_document/closed_document.py index 048ceeecbf5..50469bc19c6 100644 --- a/erpnext/accounts/doctype/closed_document/closed_document.py +++ b/erpnext/accounts/doctype/closed_document/closed_document.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ClosedDocument(Document): pass diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py index 981fec308cc..166ebb83ac2 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center.py +++ b/erpnext/accounts/doctype/cost_center/cost_center.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cint, cstr +from frappe.utils import cint from frappe.utils.nestedset import NestedSet + from erpnext.accounts.utils import validate_field_number diff --git a/erpnext/accounts/doctype/cost_center/test_cost_center.py b/erpnext/accounts/doctype/cost_center/test_cost_center.py index 7779ccefc20..142b925c2ea 100644 --- a/erpnext/accounts/doctype/cost_center/test_cost_center.py +++ b/erpnext/accounts/doctype/cost_center/test_cost_center.py @@ -1,7 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest + import frappe test_records = frappe.get_test_records('Cost Center') diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.py b/erpnext/accounts/doctype/coupon_code/coupon_code.py index 92a816d25e9..bb2615b3610 100644 --- a/erpnext/accounts/doctype/coupon_code/coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/coupon_code.py @@ -3,10 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import (strip) +from frappe.utils import strip + + class CouponCode(Document): def autoname(self): self.coupon_name = strip(self.coupon_name) diff --git a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py index 06987a8a4a5..9d34cc2fbb9 100644 --- a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py @@ -3,11 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order -from erpnext.stock.get_item_details import get_item_details -from frappe.test_runner import make_test_objects test_dependencies = ['Item'] @@ -41,9 +41,6 @@ def test_create_test_data(): "selling_cost_center": "Main - _TC", "income_account": "Sales - _TC" }], - "show_in_website": 1, - "route":"-test-tesla-car", - "website_warehouse": "Stores - _TC" }) item.insert() # create test item price diff --git a/erpnext/accounts/doctype/customer_group_item/customer_group_item.py b/erpnext/accounts/doctype/customer_group_item/customer_group_item.py index df782ac9e0c..100bfd5e665 100644 --- a/erpnext/accounts/doctype/customer_group_item/customer_group_item.py +++ b/erpnext/accounts/doctype/customer_group_item/customer_group_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class CustomerGroupItem(Document): pass diff --git a/erpnext/accounts/doctype/customer_item/customer_item.py b/erpnext/accounts/doctype/customer_item/customer_item.py index a577145e4ee..da3533fcc68 100644 --- a/erpnext/accounts/doctype/customer_item/customer_item.py +++ b/erpnext/accounts/doctype/customer_item/customer_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class CustomerItem(Document): pass diff --git a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py index 93dfcc14bda..11faa773c65 100644 --- a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py +++ b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DiscountedInvoice(Document): pass diff --git a/erpnext/accounts/doctype/distributed_cost_center/distributed_cost_center.py b/erpnext/accounts/doctype/distributed_cost_center/distributed_cost_center.py index 48c589f0c0f..436704008ea 100644 --- a/erpnext/accounts/doctype/distributed_cost_center/distributed_cost_center.py +++ b/erpnext/accounts/doctype/distributed_cost_center/distributed_cost_center.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DistributedCostCenter(Document): pass diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py index 1ef512a4894..65ada530df5 100644 --- a/erpnext/accounts/doctype/dunning/dunning.py +++ b/erpnext/accounts/doctype/dunning/dunning.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe +from frappe.utils import cint, flt, getdate from six import string_types -from frappe.utils import getdate, get_datetime, rounded, flt, cint -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions from erpnext.controllers.accounts_controller import AccountsController diff --git a/erpnext/accounts/doctype/dunning/dunning_dashboard.py b/erpnext/accounts/doctype/dunning/dunning_dashboard.py index 33c6ab080c9..fa3330f7cfd 100644 --- a/erpnext/accounts/doctype/dunning/dunning_dashboard.py +++ b/erpnext/accounts/doctype/dunning/dunning_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'dunning', diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py index 39ee74658ce..5e380de5bc5 100644 --- a/erpnext/accounts/doctype/dunning/test_dunning.py +++ b/erpnext/accounts/doctype/dunning/test_dunning.py @@ -3,13 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import add_days, today, nowdate -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice_against_cost_center + +import frappe +from frappe.utils import add_days, nowdate, today + from erpnext.accounts.doctype.dunning.dunning import calculate_interest_and_amount from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + unlink_payment_on_cancel_of_invoice, +) +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import ( + create_sales_invoice_against_cost_center, +) class TestDunning(unittest.TestCase): diff --git a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py index 426497b6072..b14fdc11f2a 100644 --- a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py +++ b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DunningLetterText(Document): pass diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.py b/erpnext/accounts/doctype/dunning_type/dunning_type.py index 87087484289..64e7cf420fe 100644 --- a/erpnext/accounts/doctype/dunning_type/dunning_type.py +++ b/erpnext/accounts/doctype/dunning_type/dunning_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DunningType(Document): pass diff --git a/erpnext/accounts/doctype/dunning_type/test_dunning_type.py b/erpnext/accounts/doctype/dunning_type/test_dunning_type.py index b2fb26f34a5..ae08907273e 100644 --- a/erpnext/accounts/doctype/dunning_type/test_dunning_type.py +++ b/erpnext/accounts/doctype/dunning_type/test_dunning_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestDunningType(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index dbbcedcadfa..9c173d0c517 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt from frappe.model.document import Document from frappe.model.meta import get_field_precision -from erpnext.setup.utils import get_exchange_rate +from frappe.utils import flt + +import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_balance_on +from erpnext.setup.utils import get_exchange_rate + class ExchangeRateRevaluation(Document): def validate(self): diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py index b5cfa04ed67..7358f561ed4 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'reference_name', diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py index 3b037d1dc47..e725ce4da45 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestExchangeRateRevaluation(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py index 87d7b673465..58375dd4ef9 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ExchangeRateRevaluationAccount(Document): pass diff --git a/erpnext/accounts/doctype/finance_book/finance_book.py b/erpnext/accounts/doctype/finance_book/finance_book.py index bc9fce2ce86..527b8e67886 100644 --- a/erpnext/accounts/doctype/finance_book/finance_book.py +++ b/erpnext/accounts/doctype/finance_book/finance_book.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class FinanceBook(Document): pass diff --git a/erpnext/accounts/doctype/finance_book/test_finance_book.py b/erpnext/accounts/doctype/finance_book/test_finance_book.py index 2ba21397ad0..1f25e5a9d27 100644 --- a/erpnext/accounts/doctype/finance_book/test_finance_book.py +++ b/erpnext/accounts/doctype/finance_book/test_finance_book.py @@ -2,11 +2,13 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry +import unittest import frappe -import unittest + +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry + class TestFinanceBook(unittest.TestCase): def test_finance_book(self): diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 42556269fdd..6854ac910d2 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -2,12 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe import msgprint, _ -from frappe.utils import getdate, add_days, add_years, cstr -from dateutil.relativedelta import relativedelta +import frappe +from dateutil.relativedelta import relativedelta +from frappe import _, msgprint from frappe.model.document import Document +from frappe.utils import add_days, add_years, cstr, getdate + class FiscalYearIncorrectDate(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py index cec4f4492d6..b0365afa827 100644 --- a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py @@ -3,7 +3,9 @@ from __future__ import unicode_literals -import frappe, unittest +import unittest + +import frappe from erpnext.accounts.doctype.fiscal_year.fiscal_year import FiscalYearIncorrectDate diff --git a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py index 8dfc2fa7e29..b9c57f67b0e 100644 --- a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py +++ b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class FiscalYearCompany(Document): pass diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 0844995f296..1e983b1d429 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -2,20 +2,30 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt, fmt_money, getdate, formatdate, cint from frappe.model.document import Document -from frappe.model.naming import set_name_from_naming_options from frappe.model.meta import get_field_precision -from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled -from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.utils import get_fiscal_year -from erpnext.exceptions import InvalidAccountCurrency, InvalidAccountDimensionError, MandatoryAccountDimensionError -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts -from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import get_dimension_filter_map +from frappe.model.naming import set_name_from_naming_options +from frappe.utils import flt, fmt_money from six import iteritems +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_checks_for_pl_and_bs_accounts, +) +from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import ( + get_dimension_filter_map, +) +from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency +from erpnext.accounts.utils import get_account_currency, get_fiscal_year +from erpnext.exceptions import ( + InvalidAccountCurrency, + InvalidAccountDimensionError, + MandatoryAccountDimensionError, +) + exclude_from_linked_with = True class GLEntry(Document): def autoname(self): diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py index 4167ca70df2..14959520767 100644 --- a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py @@ -2,10 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, unittest + +import unittest + +import frappe from frappe.model.naming import parse_naming_series -from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry + from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry + class TestGLEntry(unittest.TestCase): def test_round_off_entry(self): diff --git a/erpnext/accounts/doctype/gst_account/gst_account.py b/erpnext/accounts/doctype/gst_account/gst_account.py index d7848495a69..9ca3f9ac51d 100644 --- a/erpnext/accounts/doctype/gst_account/gst_account.py +++ b/erpnext/accounts/doctype/gst_account/gst_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class GSTAccount(Document): pass diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index b73d8bfbb11..8867f1cd9bf 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -3,12 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json, erpnext + +import json + +import frappe from frappe import _ -from frappe.utils import flt, getdate, nowdate, add_days -from erpnext.controllers.accounts_controller import AccountsController +from frappe.utils import add_days, flt, getdate, nowdate + +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) from erpnext.accounts.general_ledger import make_gl_entries -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from erpnext.controllers.accounts_controller import AccountsController + class InvoiceDiscounting(AccountsController): def validate(self): diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting_dashboard.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting_dashboard.py index 6d35ca24397..bab8e46c31e 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting_dashboard.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'reference_name', diff --git a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py index 919dd0cba77..58aea92e817 100644 --- a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py @@ -3,13 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import nowdate, add_days, flt import unittest -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries + +import frappe +from frappe.utils import add_days, flt, nowdate + from erpnext.accounts.doctype.account.test_account import create_account from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries + + class TestInvoiceDiscounting(unittest.TestCase): def setUp(self): self.ar_credit = create_account(account_name="_Test Accounts Receivable Credit", parent_account = "Accounts Receivable - _TC", company="_Test Company") diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py index d9155cbab4a..1e26afe0253 100644 --- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class ItemTaxTemplate(Document): def validate(self): diff --git a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py index acf1e446e74..46bb300e37d 100644 --- a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py +++ b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestItemTaxTemplate(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py index d51bed0520a..aa3b5420d60 100644 --- a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py +++ b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ItemTaxTemplateDetail(Document): pass diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 72648753a7a..5b3d1c5c4cb 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -2,19 +2,30 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext, json -from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate, cint, get_link_to_form -from frappe import msgprint, _, scrub -from erpnext.controllers.accounts_controller import AccountsController -from erpnext.accounts.utils import get_balance_on, get_stock_accounts, get_stock_and_account_balance, \ - get_account_currency, check_if_stock_and_account_balance_synced -from erpnext.accounts.party import get_party_account -from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount -from erpnext.accounts.doctype.invoice_discounting.invoice_discounting \ - import get_party_account_based_on_invoice_discounting -from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts -from six import string_types, iteritems +import json + +import frappe +from frappe import _, msgprint, scrub +from frappe.utils import cint, cstr, flt, fmt_money, formatdate, get_link_to_form, nowdate +from six import iteritems, string_types + +import erpnext +from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts +from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import ( + get_party_account_based_on_invoice_discounting, +) +from erpnext.accounts.party import get_party_account +from erpnext.accounts.utils import ( + check_if_stock_and_account_balance_synced, + get_account_currency, + get_balance_on, + get_stock_accounts, + get_stock_and_account_balance, +) +from erpnext.controllers.accounts_controller import AccountsController +from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount + class StockAccountInvalidTransaction(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index 5835d462ae9..d03a08851a6 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -2,11 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest, frappe + +import unittest + +import frappe from frappe.utils import flt, nowdate + from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.exceptions import InvalidAccountCurrency from erpnext.accounts.doctype.journal_entry.journal_entry import StockAccountInvalidTransaction +from erpnext.exceptions import InvalidAccountCurrency + class TestJournalEntry(unittest.TestCase): def test_journal_entry_with_against_jv(self): diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py index 2e77cf2b44e..86d3df4dc22 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class JournalEntryAccount(Document): pass diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py index e0b9cbc9193..f0813f5e275 100644 --- a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py +++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class JournalEntryTemplate(Document): pass diff --git a/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py index 5f74a2042fd..61fea94e823 100644 --- a/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py +++ b/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestJournalEntryTemplate(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py index 48e6abbc284..d0408ca2fcd 100644 --- a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py +++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class JournalEntryTemplateAccount(Document): pass diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py index 3579a1a9604..0813926f5f2 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py +++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.utils import today diff --git a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py index b6e2d57b9fb..07856cfd5d6 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py +++ b/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestLoyaltyPointEntry(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py b/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py index e4382b6c789..506e2ce8398 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py +++ b/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LoyaltyPointEntryRedemption(Document): pass diff --git a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py index cb753a3723d..89ed461fd5d 100644 --- a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py @@ -3,11 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import today, flt +from frappe.utils import flt, today + class LoyaltyProgram(Document): pass diff --git a/erpnext/accounts/doctype/loyalty_program/loyalty_program_dashboard.py b/erpnext/accounts/doctype/loyalty_program/loyalty_program_dashboard.py index 189004f5ec8..267bbbf00b2 100644 --- a/erpnext/accounts/doctype/loyalty_program/loyalty_program_dashboard.py +++ b/erpnext/accounts/doctype/loyalty_program/loyalty_program_dashboard.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from frappe import _ - def get_data(): return { diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py index 31994885aa6..a039e32b8b9 100644 --- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py @@ -3,12 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import today, cint, flt, getdate -from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points + +import frappe +from frappe.utils import cint, flt, getdate, today + +from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( + get_loyalty_program_details_with_points, +) from erpnext.accounts.party import get_dashboard_info + class TestLoyaltyProgram(unittest.TestCase): @classmethod def setUpClass(self): diff --git a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py index 42cc38cb4c2..4bbcf3ae9f0 100644 --- a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py +++ b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LoyaltyProgramCollection(Document): pass diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py index cea921e999e..dfe42df226a 100644 --- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py +++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document +import frappe from frappe import _ +from frappe.model.document import Document + class ModeofPayment(Document): def validate(self): diff --git a/erpnext/accounts/doctype/mode_of_payment/test_mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/test_mode_of_payment.py index ad6cd4795f3..299687b067e 100644 --- a/erpnext/accounts/doctype/mode_of_payment/test_mode_of_payment.py +++ b/erpnext/accounts/doctype/mode_of_payment/test_mode_of_payment.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Mode of Payment') diff --git a/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py b/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py index 5cb195a3ba4..40b5f302f2c 100644 --- a/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py +++ b/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ModeofPaymentAccount(Document): pass diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py index ad8623fb4ee..c0e00d62099 100644 --- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import (flt, add_months) from frappe.model.document import Document +from frappe.utils import add_months, flt + class MonthlyDistribution(Document): @frappe.whitelist() diff --git a/erpnext/accounts/doctype/monthly_distribution/test_monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/test_monthly_distribution.py index efbf4eb105f..63faa158f15 100644 --- a/erpnext/accounts/doctype/monthly_distribution/test_monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/test_monthly_distribution.py @@ -2,9 +2,11 @@ # See license.txt from __future__ import unicode_literals -import frappe + import unittest +import frappe + test_records = frappe.get_test_records('Monthly Distribution') class TestMonthlyDistribution(unittest.TestCase): diff --git a/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py b/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py index d9e8bf9c778..8ec30c79af7 100644 --- a/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py +++ b/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MonthlyDistributionPercentage(Document): pass 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 3586e683d4d..646bc4cceb9 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 @@ -3,14 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import traceback from json import dumps + +import frappe from frappe import _, scrub -from frappe.utils import flt, nowdate from frappe.model.document import Document +from frappe.utils import flt, nowdate from frappe.utils.background_jobs import enqueue -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) class OpeningInvoiceCreationTool(Document): diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py index 8d6de2d562f..ed3c6a9da0a 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py @@ -3,12 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe from frappe.cache_manager import clear_doctype_cache from frappe.custom.doctype.property_setter.property_setter import make_property_setter -from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import get_temporary_opening_account + +from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import ( + get_temporary_opening_account, +) test_dependencies = ["Customer", "Supplier"] diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py index d47c3e94ecc..4008022a26b 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class OpeningInvoiceCreationToolItem(Document): pass diff --git a/erpnext/accounts/doctype/party_account/party_account.py b/erpnext/accounts/doctype/party_account/party_account.py index 21cfb96dba4..08d67c7a7be 100644 --- a/erpnext/accounts/doctype/party_account/party_account.py +++ b/erpnext/accounts/doctype/party_account/party_account.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PartyAccount(Document): pass diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py index 7d58506ce74..daf667caf0c 100644 --- a/erpnext/accounts/doctype/party_link/party_link.py +++ b/erpnext/accounts/doctype/party_link/party_link.py @@ -5,19 +5,20 @@ import frappe from frappe import _ from frappe.model.document import Document + class PartyLink(Document): def validate(self): if self.primary_role not in ['Customer', 'Supplier']: frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."), title=_("Invalid Primary Role")) - + existing_party_link = frappe.get_all('Party Link', { 'primary_party': self.secondary_party }, pluck="primary_role") if existing_party_link: frappe.throw(_('{} {} is already linked with another {}') .format(self.secondary_role, self.secondary_party, existing_party_link[0])) - + existing_party_link = frappe.get_all('Party Link', { 'secondary_party': self.primary_party }, pluck="primary_role") diff --git a/erpnext/accounts/doctype/party_link/test_party_link.py b/erpnext/accounts/doctype/party_link/test_party_link.py index a3ea3959ba4..2ae338133e0 100644 --- a/erpnext/accounts/doctype/party_link/test_party_link.py +++ b/erpnext/accounts/doctype/party_link/test_party_link.py @@ -4,5 +4,6 @@ # import frappe import unittest + class TestPartyLink(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index cc8ab453fd9..727ef55b3c7 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -872,7 +872,7 @@ frappe.ui.form.on('Payment Entry', { && frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions && frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) { unallocated_amount = (frm.doc.base_received_amount + total_deductions + frm.doc.base_total_taxes_and_charges - + frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate; + - frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate; } else if (frm.doc.payment_type == "Pay" && frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions && frm.doc.total_allocated_amount < frm.doc.received_amount + (total_deductions / frm.doc.target_exchange_rate)) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index e34d651f0c4..607f85c87bd 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -3,22 +3,37 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext, json -from frappe import _, scrub, ValidationError, throw -from frappe.utils import flt, comma_or, nowdate, getdate, cint -from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on -from erpnext.accounts.party import get_party_account -from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account -from erpnext.setup.utils import get_exchange_rate -from erpnext.accounts.general_ledger import make_gl_entries -from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount -from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_account, get_bank_account_details -from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status -from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details -from six import string_types, iteritems -from erpnext.controllers.accounts_controller import validate_taxes_and_charges +import json + +import frappe +from frappe import ValidationError, _, scrub, throw +from frappe.utils import cint, comma_or, flt, getdate, nowdate +from six import iteritems, string_types + +import erpnext +from erpnext.accounts.doctype.bank_account.bank_account import ( + get_bank_account_details, + get_party_bank_account, +) +from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import ( + get_party_account_based_on_invoice_discounting, +) +from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account +from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( + get_party_tax_withholding_details, +) +from erpnext.accounts.general_ledger import make_gl_entries +from erpnext.accounts.party import get_party_account +from erpnext.accounts.utils import get_account_currency, get_balance_on, get_outstanding_invoices +from erpnext.controllers.accounts_controller import ( + AccountsController, + get_supplier_block_status, + validate_taxes_and_charges, +) +from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount +from erpnext.setup.utils import get_exchange_rate + class InvalidPaymentEntry(ValidationError): pass @@ -484,7 +499,7 @@ class PaymentEntry(AccountsController): def validate_amounts(self): self.validate_received_amount() - + def validate_received_amount(self): if self.paid_from_account_currency == self.paid_to_account_currency: if self.paid_amount != self.received_amount: @@ -1390,7 +1405,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre }) def get_amounts_based_on_reference_doctype(reference_doctype, ref_doc, party_account_currency, company_currency, reference_name): - total_amount, outstanding_amount, exchange_rate = None + total_amount = outstanding_amount = exchange_rate = None if reference_doctype == "Fees": total_amount = ref_doc.get("grand_total") exchange_rate = 1 @@ -1410,7 +1425,7 @@ def get_amounts_based_on_reference_doctype(reference_doctype, ref_doc, party_acc return total_amount, outstanding_amount, exchange_rate def get_amounts_based_on_ref_doc(reference_doctype, ref_doc, party_account_currency, company_currency): - total_amount, outstanding_amount, exchange_rate = None + total_amount = outstanding_amount = exchange_rate = None if ref_doc.doctype == "Expense Claim": total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges) elif ref_doc.doctype == "Employee Advance": @@ -1450,7 +1465,7 @@ def get_total_amount_exchange_rate_base_on_currency(party_account_currency, comp return total_amount, exchange_rate def get_bill_no_and_update_amounts(reference_doctype, ref_doc, total_amount, exchange_rate, party_account_currency, company_currency): - outstanding_amount, bill_no = None + outstanding_amount = bill_no = None if reference_doctype in ("Sales Invoice", "Purchase Invoice"): outstanding_amount = ref_doc.get("outstanding_amount") bill_no = ref_doc.get("bill_no") diff --git a/erpnext/accounts/doctype/payment_entry/regional/india.js b/erpnext/accounts/doctype/payment_entry/regional/india.js new file mode 100644 index 00000000000..abb344581ce --- /dev/null +++ b/erpnext/accounts/doctype/payment_entry/regional/india.js @@ -0,0 +1,29 @@ +frappe.ui.form.on("Payment Entry", { + company: function(frm) { + frappe.call({ + 'method': 'frappe.contacts.doctype.address.address.get_default_address', + 'args': { + 'doctype': 'Company', + 'name': frm.doc.company + }, + 'callback': function(r) { + frm.set_value('company_address', r.message); + } + }); + }, + + party: function(frm) { + if (frm.doc.party_type == "Customer" && frm.doc.party) { + frappe.call({ + 'method': 'frappe.contacts.doctype.address.address.get_default_address', + 'args': { + 'doctype': 'Customer', + 'name': frm.doc.party + }, + 'callback': function(r) { + frm.set_value('customer_address', r.message); + } + }); + } + } +}); \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index dac927b2cef..c90a3c503c2 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -3,14 +3,25 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import flt, nowdate -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order -from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, InvalidPaymentEntry -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice, create_sales_invoice_against_cost_center -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice, make_purchase_invoice_against_cost_center + +from erpnext.accounts.doctype.payment_entry.payment_entry import ( + InvalidPaymentEntry, + get_payment_entry, +) +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + make_purchase_invoice, + make_purchase_invoice_against_cost_center, +) +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import ( + create_sales_invoice, + create_sales_invoice_against_cost_center, +) from erpnext.hr.doctype.expense_claim.test_expense_claim import make_expense_claim +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order test_dependencies = ["Item"] @@ -324,7 +335,10 @@ class TestPaymentEntry(unittest.TestCase): self.assertEqual(flt(pe.unallocated_amount, 2), 0.0) def test_payment_entry_retrieves_last_exchange_rate(self): - from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records + from erpnext.setup.doctype.currency_exchange.test_currency_exchange import ( + save_new_records, + test_records, + ) save_new_records(test_records) diff --git a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py index d6686bbe422..9cfed7b56d3 100644 --- a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py +++ b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PaymentEntryDeduction(Document): pass diff --git a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py index 51f8c06165a..a686f495cda 100644 --- a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py +++ b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PaymentEntryReference(Document): pass diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py index 3529c16a1c2..1d8a8ac5e19 100644 --- a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py +++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class PaymentGatewayAccount(Document): def autoname(self): self.name = self.payment_gateway + " - " + self.currency diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account_dashboard.py b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account_dashboard.py index 08982296f3d..2edc1a1590b 100644 --- a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account_dashboard.py +++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account_dashboard.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from frappe import _ - def get_data(): return { diff --git a/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py b/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py index 84c3bc4a600..f76aa4a80f8 100644 --- a/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py +++ b/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Payment Gateway Account') diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index 8d29ae70ae7..e9b5ad9dc4d 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import nowdate -from erpnext.accounts.party import get_party_account from frappe.model.document import Document +from frappe.utils import nowdate + +from erpnext.accounts.party import get_party_account + class PaymentOrder(Document): def on_submit(self): diff --git a/erpnext/accounts/doctype/payment_order/payment_order_dashboard.py b/erpnext/accounts/doctype/payment_order/payment_order_dashboard.py index a4f335833ee..d9262be9b86 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order_dashboard.py +++ b/erpnext/accounts/doctype/payment_order/payment_order_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/accounts/doctype/payment_order/test_payment_order.py b/erpnext/accounts/doctype/payment_order/test_payment_order.py index 9ba57aef300..6414473346b 100644 --- a/erpnext/accounts/doctype/payment_order/test_payment_order.py +++ b/erpnext/accounts/doctype/payment_order/test_payment_order.py @@ -3,13 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import getdate + from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account -from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, make_payment_order +from erpnext.accounts.doctype.payment_entry.payment_entry import ( + get_payment_entry, + make_payment_order, +) from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice + class TestPaymentOrder(unittest.TestCase): def setUp(self): create_bank_account() diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py index b3a92940e27..4bb98a3b61a 100644 --- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py +++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PaymentOrderReference(Document): pass diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js index d1523cd7aca..bcba13eb288 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js @@ -2,46 +2,10 @@ // For license information, please see license.txt frappe.provide("erpnext.accounts"); - -frappe.ui.form.on("Payment Reconciliation Payment", { - invoice_number: function(frm, cdt, cdn) { - var row = locals[cdt][cdn]; - if(row.invoice_number) { - var parts = row.invoice_number.split(' | '); - var invoice_type = parts[0]; - var invoice_number = parts[1]; - - var invoice_amount = frm.doc.invoices.filter(function(d) { - return d.invoice_type === invoice_type && d.invoice_number === invoice_number; - })[0].outstanding_amount; - - frappe.model.set_value(cdt, cdn, "allocated_amount", Math.min(invoice_amount, row.amount)); - - frm.call({ - doc: frm.doc, - method: 'get_difference_amount', - args: { - child_row: row - }, - callback: function(r, rt) { - if(r.message) { - frappe.model.set_value(cdt, cdn, - "difference_amount", r.message); - } - } - }); - } - } -}); - erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.extend({ onload: function() { var me = this; - this.frm.set_query("party", function() { - check_mandatory(me.frm); - }); - this.frm.set_query("party_type", function() { return { "filters": { @@ -88,15 +52,36 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext refresh: function() { this.frm.disable_save(); - this.toggle_primary_action(); + + if (this.frm.doc.receivable_payable_account) { + this.frm.add_custom_button(__('Get Unreconciled Entries'), () => + this.frm.trigger("get_unreconciled_entries") + ); + } + if (this.frm.doc.invoices.length && this.frm.doc.payments.length) { + this.frm.add_custom_button(__('Allocate'), () => + this.frm.trigger("allocate") + ); + } + if (this.frm.doc.allocation.length) { + this.frm.add_custom_button(__('Reconcile'), () => + this.frm.trigger("reconcile") + ); + } }, - onload_post_render: function() { - this.toggle_primary_action(); + company: function() { + var me = this; + this.frm.set_value('receivable_payable_account', ''); + me.frm.clear_table("allocation"); + me.frm.clear_table("invoices"); + me.frm.clear_table("payments"); + me.frm.refresh_fields(); + me.frm.trigger('party'); }, party: function() { - var me = this + var me = this; if (!me.frm.doc.receivable_payable_account && me.frm.doc.party_type && me.frm.doc.party) { return frappe.call({ method: "erpnext.accounts.party.get_party_account", @@ -109,6 +94,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext if (!r.exc && r.message) { me.frm.set_value("receivable_payable_account", r.message); } + me.frm.refresh(); } }); } @@ -120,16 +106,41 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext doc: me.frm.doc, method: 'get_unreconciled_entries', callback: function(r, rt) { - me.set_invoice_options(); - me.toggle_primary_action(); + if (!(me.frm.doc.payments.length || me.frm.doc.invoices.length)) { + frappe.throw({message: __("No invoice and payment records found for this party")}); + } + me.frm.refresh(); } }); }, + allocate: function() { + var me = this; + let payments = me.frm.fields_dict.payments.grid.get_selected_children(); + if (!(payments.length)) { + payments = me.frm.doc.payments; + } + let invoices = me.frm.fields_dict.invoices.grid.get_selected_children(); + if (!(invoices.length)) { + invoices = me.frm.doc.invoices; + } + return me.frm.call({ + doc: me.frm.doc, + method: 'allocate_entries', + args: { + payments: payments, + invoices: invoices + }, + callback: function() { + me.frm.refresh(); + } + }); + }, + reconcile: function() { var me = this; - var show_dialog = me.frm.doc.payments.filter(d => d.difference_amount && !d.difference_account); + var show_dialog = me.frm.doc.allocation.filter(d => d.difference_amount && !d.difference_account); if (show_dialog && show_dialog.length) { @@ -138,7 +149,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext title: __("Select Difference Account"), fields: [ { - fieldname: "payments", fieldtype: "Table", label: __("Payments"), + fieldname: "allocation", fieldtype: "Table", label: __("Allocation"), data: this.data, in_place_edit: true, get_data: () => { return this.data; @@ -179,10 +190,10 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext }, ], primary_action: function() { - const args = dialog.get_values()["payments"]; + const args = dialog.get_values()["allocation"]; args.forEach(d => { - frappe.model.set_value("Payment Reconciliation Payment", d.docname, + frappe.model.set_value("Payment Reconciliation Allocation", d.docname, "difference_account", d.difference_account); }); @@ -192,9 +203,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext primary_action_label: __('Reconcile Entries') }); - this.frm.doc.payments.forEach(d => { + this.frm.doc.allocation.forEach(d => { if (d.difference_amount && !d.difference_account) { - dialog.fields_dict.payments.df.data.push({ + dialog.fields_dict.allocation.df.data.push({ 'docname': d.name, 'reference_name': d.reference_name, 'difference_amount': d.difference_amount, @@ -203,8 +214,8 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext } }); - this.data = dialog.fields_dict.payments.df.data; - dialog.fields_dict.payments.grid.refresh(); + this.data = dialog.fields_dict.allocation.df.data; + dialog.fields_dict.allocation.grid.refresh(); dialog.show(); } else { this.reconcile_payment_entries(); @@ -218,48 +229,12 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext doc: me.frm.doc, method: 'reconcile', callback: function(r, rt) { - me.set_invoice_options(); - me.toggle_primary_action(); + me.frm.clear_table("allocation"); + me.frm.refresh_fields(); + me.frm.refresh(); } }); - }, - - set_invoice_options: function() { - var me = this; - var invoices = []; - - $.each(me.frm.doc.invoices || [], function(i, row) { - if (row.invoice_number && !in_list(invoices, row.invoice_number)) - invoices.push(row.invoice_type + " | " + row.invoice_number); - }); - - if (invoices) { - this.frm.fields_dict.payments.grid.update_docfield_property( - 'invoice_number', 'options', "\n" + invoices.join("\n") - ); - - $.each(me.frm.doc.payments || [], function(i, p) { - if(!in_list(invoices, cstr(p.invoice_number))) p.invoice_number = null; - }); - } - - refresh_field("payments"); - }, - - toggle_primary_action: function() { - if ((this.frm.doc.payments || []).length) { - this.frm.fields_dict.reconcile.$input - && this.frm.fields_dict.reconcile.$input.addClass("btn-primary"); - this.frm.fields_dict.get_unreconciled_entries.$input - && this.frm.fields_dict.get_unreconciled_entries.$input.removeClass("btn-primary"); - } else { - this.frm.fields_dict.reconcile.$input - && this.frm.fields_dict.reconcile.$input.removeClass("btn-primary"); - this.frm.fields_dict.get_unreconciled_entries.$input - && this.frm.fields_dict.get_unreconciled_entries.$input.addClass("btn-primary"); - } } - }); $.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm})); diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json index cfb24c3954c..9023b3646f2 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json @@ -1,622 +1,206 @@ { - "allow_copy": 1, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2014-07-09 12:04:51.681583", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, - "engine": "InnoDB", + "actions": [], + "allow_copy": 1, + "creation": "2014-07-09 12:04:51.681583", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "company", + "party_type", + "column_break_4", + "party", + "receivable_payable_account", + "col_break1", + "from_invoice_date", + "to_invoice_date", + "minimum_invoice_amount", + "maximum_invoice_amount", + "invoice_limit", + "column_break_13", + "from_payment_date", + "to_payment_date", + "minimum_payment_amount", + "maximum_payment_amount", + "payment_limit", + "bank_cash_account", + "sec_break1", + "invoices", + "column_break_15", + "payments", + "sec_break2", + "allocation" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party_type", - "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": "Party Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "party_type", + "fieldtype": "Link", + "label": "Party Type", + "options": "DocType", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "party", - "fieldtype": "Dynamic 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": "Party", - "length": 0, - "no_copy": 0, - "options": "party_type", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.party_type", + "fieldname": "party", + "fieldtype": "Dynamic Link", + "label": "Party", + "options": "party_type", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "receivable_payable_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Receivable / Payable Account", - "length": 0, - "no_copy": 0, - "options": "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.company && doc.party", + "fieldname": "receivable_payable_account", + "fieldtype": "Link", + "label": "Receivable / Payable Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_cash_account", - "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": "Bank / Cash Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "This filter will be applied to Journal Entry.", + "fieldname": "bank_cash_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Bank / Cash Account", + "options": "Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "collapsible_depends_on": "eval: doc.invoices.length == 0", + "depends_on": "eval:doc.receivable_payable_account", + "fieldname": "col_break1", + "fieldtype": "Section Break", + "label": "Filters" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "from_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "From Invoice Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:(doc.payments).length || (doc.invoices).length", + "fieldname": "sec_break1", + "fieldtype": "Section Break", + "label": "Unreconciled Entries" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "to_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "To Invoice Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payments", + "fieldtype": "Table", + "label": "Payments", + "options": "Payment Reconciliation Payment" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "minimum_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": "Minimum Invoice Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "allocation", + "fieldname": "sec_break2", + "fieldtype": "Section Break", + "label": "Allocated Entries" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "maximum_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": "Maximum Invoice Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "invoices", + "fieldtype": "Table", + "label": "Invoices", + "options": "Payment Reconciliation Invoice" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "System will fetch all the entries if limit value is zero.", - "fieldname": "limit", - "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": "Limit", - "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_15", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "get_unreconciled_entries", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Get Unreconciled Entries", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "allocation", + "fieldtype": "Table", + "label": "Allocation", + "options": "Payment Reconciliation Allocation" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sec_break1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Unreconciled Payment Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payments", - "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": "Payments", - "length": 0, - "no_copy": 0, - "options": "Payment Reconciliation Payment", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "from_invoice_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "From Invoice Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reconcile", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reconcile", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "to_invoice_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "To Invoice Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sec_break2", - "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": "Invoice/Journal Entry Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "minimum_invoice_amount", + "fieldtype": "Currency", + "label": "Minimum Invoice Amount" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "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": "Payment Reconciliation Invoice", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "description": "System will fetch all the entries if limit value is zero.", + "fieldname": "invoice_limit", + "fieldtype": "Int", + "label": "Invoice Limit" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "from_payment_date", + "fieldtype": "Date", + "label": "From Payment Date" + }, + { + "fieldname": "to_payment_date", + "fieldtype": "Date", + "label": "To Payment Date" + }, + { + "fieldname": "minimum_payment_amount", + "fieldtype": "Currency", + "label": "Minimum Payment Amount" + }, + { + "fieldname": "maximum_payment_amount", + "fieldtype": "Currency", + "label": "Maximum Payment Amount" + }, + { + "fieldname": "payment_limit", + "fieldtype": "Int", + "label": "Payment Limit" + }, + { + "fieldname": "maximum_invoice_amount", + "fieldtype": "Currency", + "label": "Maximum Invoice Amount" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 1, - "icon": "icon-resize-horizontal", - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "menu_index": 0, - "modified": "2019-01-15 17:42:21.135214", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Reconciliation", - "name_case": "", - "owner": "Administrator", + ], + "hide_toolbar": 1, + "icon": "icon-resize-horizontal", + "issingle": 1, + "links": [], + "modified": "2021-08-30 13:05:51.977861", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Reconciliation", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "read": 1, + "role": "Accounts Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "read": 1, + "role": "Accounts User", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "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/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index acfe1fef2ee..9de79aee58a 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -2,14 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import flt, today -from frappe import msgprint, _ + +import frappe +from frappe import _, msgprint from frappe.model.document import Document -from erpnext.accounts.utils import (get_outstanding_invoices, - update_reference_in_payment_entry, reconcile_against_document) +from frappe.utils import flt, getdate, nowdate, today + +import erpnext +from erpnext.accounts.utils import get_outstanding_invoices, reconcile_against_document from erpnext.controllers.accounts_controller import get_advance_payment_entries + class PaymentReconciliation(Document): @frappe.whitelist() def get_unreconciled_entries(self): @@ -27,24 +30,32 @@ class PaymentReconciliation(Document): else: dr_or_cr_notes = [] - self.add_payment_entries(payment_entries + journal_entries + dr_or_cr_notes) + non_reconciled_payments = payment_entries + journal_entries + dr_or_cr_notes + + if self.payment_limit: + non_reconciled_payments = non_reconciled_payments[:self.payment_limit] + + non_reconciled_payments = sorted(non_reconciled_payments, key=lambda k: k['posting_date'] or getdate(nowdate())) + + self.add_payment_entries(non_reconciled_payments) def get_payment_entries(self): order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order" + condition = self.get_conditions(get_payments=True) payment_entries = get_advance_payment_entries(self.party_type, self.party, - self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.limit) + self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.payment_limit, + condition=condition) return payment_entries def get_jv_entries(self): + condition = self.get_conditions() dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") bank_account_condition = "t2.against_account like %(bank_cash_account)s" \ if self.bank_cash_account else "1=1" - limit_cond = "limit %s" % self.limit if self.limit else "" - journal_entries = frappe.db.sql(""" select "Journal Entry" as reference_type, t1.name as reference_name, @@ -56,7 +67,7 @@ class PaymentReconciliation(Document): where t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1 and t2.party_type = %(party_type)s and t2.party = %(party)s - and t2.account = %(account)s and {dr_or_cr} > 0 + and t2.account = %(account)s and {dr_or_cr} > 0 {condition} and (t2.reference_type is null or t2.reference_type = '' or (t2.reference_type in ('Sales Order', 'Purchase Order') and t2.reference_name is not null and t2.reference_name != '')) @@ -65,11 +76,11 @@ class PaymentReconciliation(Document): THEN 1=1 ELSE {bank_account_condition} END) - order by t1.posting_date {limit_cond} + order by t1.posting_date """.format(**{ "dr_or_cr": dr_or_cr, "bank_account_condition": bank_account_condition, - "limit_cond": limit_cond + "condition": condition }), { "party_type": self.party_type, "party": self.party, @@ -80,6 +91,7 @@ class PaymentReconciliation(Document): return list(journal_entries) def get_dr_or_cr_notes(self): + condition = self.get_conditions(get_return_invoices=True) dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") @@ -90,7 +102,7 @@ class PaymentReconciliation(Document): if self.party_type == 'Customer' else "Purchase Invoice") return frappe.db.sql(""" SELECT doc.name as reference_name, %(voucher_type)s as reference_type, - (sum(gl.{dr_or_cr}) - sum(gl.{reconciled_dr_or_cr})) as amount, + (sum(gl.{dr_or_cr}) - sum(gl.{reconciled_dr_or_cr})) as amount, doc.posting_date, account_currency as currency FROM `tab{doc}` doc, `tabGL Entry` gl WHERE @@ -100,15 +112,17 @@ class PaymentReconciliation(Document): and gl.against_voucher_type = %(voucher_type)s and doc.docstatus = 1 and gl.party = %(party)s and gl.party_type = %(party_type)s and gl.account = %(account)s - and gl.is_cancelled = 0 + and gl.is_cancelled = 0 {condition} GROUP BY doc.name Having amount > 0 + ORDER BY doc.posting_date """.format( doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr, - party_type_field=frappe.scrub(self.party_type)), + party_type_field=frappe.scrub(self.party_type), + condition=condition or ""), { 'party': self.party, 'party_type': self.party_type, @@ -116,22 +130,23 @@ class PaymentReconciliation(Document): 'account': self.receivable_payable_account }, as_dict=1) - def add_payment_entries(self, entries): + def add_payment_entries(self, non_reconciled_payments): self.set('payments', []) - for e in entries: + + for payment in non_reconciled_payments: row = self.append('payments', {}) - row.update(e) + row.update(payment) def get_invoice_entries(self): #Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against - condition = self.check_condition() + condition = self.get_conditions(get_invoices=True) non_reconciled_invoices = get_outstanding_invoices(self.party_type, self.party, self.receivable_payable_account, condition=condition) - if self.limit: - non_reconciled_invoices = non_reconciled_invoices[:self.limit] + if self.invoice_limit: + non_reconciled_invoices = non_reconciled_invoices[:self.invoice_limit] self.add_invoice_entries(non_reconciled_invoices) @@ -139,41 +154,78 @@ class PaymentReconciliation(Document): #Populate 'invoices' with JVs and Invoices to reconcile against self.set('invoices', []) - for e in non_reconciled_invoices: - ent = self.append('invoices', {}) - ent.invoice_type = e.get('voucher_type') - ent.invoice_number = e.get('voucher_no') - ent.invoice_date = e.get('posting_date') - ent.amount = flt(e.get('invoice_amount')) - ent.currency = e.get('currency') - ent.outstanding_amount = e.get('outstanding_amount') + for entry in non_reconciled_invoices: + inv = self.append('invoices', {}) + inv.invoice_type = entry.get('voucher_type') + inv.invoice_number = entry.get('voucher_no') + inv.invoice_date = entry.get('posting_date') + inv.amount = flt(entry.get('invoice_amount')) + inv.currency = entry.get('currency') + inv.outstanding_amount = flt(entry.get('outstanding_amount')) @frappe.whitelist() - def reconcile(self, args): - for e in self.get('payments'): - e.invoice_type = None - if e.invoice_number and " | " in e.invoice_number: - e.invoice_type, e.invoice_number = e.invoice_number.split(" | ") + def allocate_entries(self, args): + self.validate_entries() + entries = [] + for pay in args.get('payments'): + pay.update({'unreconciled_amount': pay.get('amount')}) + for inv in args.get('invoices'): + if pay.get('amount') >= inv.get('outstanding_amount'): + res = self.get_allocated_entry(pay, inv, inv['outstanding_amount']) + pay['amount'] = flt(pay.get('amount')) - flt(inv.get('outstanding_amount')) + inv['outstanding_amount'] = 0 + else: + res = self.get_allocated_entry(pay, inv, pay['amount']) + inv['outstanding_amount'] = flt(inv.get('outstanding_amount')) - flt(pay.get('amount')) + pay['amount'] = 0 + if pay.get('amount') == 0: + entries.append(res) + break + elif inv.get('outstanding_amount') == 0: + entries.append(res) + continue + else: + break - self.get_invoice_entries() - self.validate_invoice() + self.set('allocation', []) + for entry in entries: + if entry['allocated_amount'] != 0: + row = self.append('allocation', {}) + row.update(entry) + + def get_allocated_entry(self, pay, inv, allocated_amount): + return frappe._dict({ + 'reference_type': pay.get('reference_type'), + 'reference_name': pay.get('reference_name'), + 'reference_row': pay.get('reference_row'), + 'invoice_type': inv.get('invoice_type'), + 'invoice_number': inv.get('invoice_number'), + 'unreconciled_amount': pay.get('unreconciled_amount'), + 'amount': pay.get('amount'), + 'allocated_amount': allocated_amount, + 'difference_amount': pay.get('difference_amount') + }) + + @frappe.whitelist() + def reconcile(self): + self.validate_allocation() dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") - lst = [] + entry_list = [] dr_or_cr_notes = [] - for e in self.get('payments'): + for row in self.get('allocation'): reconciled_entry = [] - if e.invoice_number and e.allocated_amount: - if e.reference_type in ['Sales Invoice', 'Purchase Invoice']: + if row.invoice_number and row.allocated_amount: + if row.reference_type in ['Sales Invoice', 'Purchase Invoice']: reconciled_entry = dr_or_cr_notes else: - reconciled_entry = lst + reconciled_entry = entry_list - reconciled_entry.append(self.get_payment_details(e, dr_or_cr)) + reconciled_entry.append(self.get_payment_details(row, dr_or_cr)) - if lst: - reconcile_against_document(lst) + if entry_list: + reconcile_against_document(entry_list) if dr_or_cr_notes: reconcile_dr_cr_note(dr_or_cr_notes, self.company) @@ -183,98 +235,104 @@ class PaymentReconciliation(Document): def get_payment_details(self, row, dr_or_cr): return frappe._dict({ - 'voucher_type': row.reference_type, - 'voucher_no' : row.reference_name, - 'voucher_detail_no' : row.reference_row, - 'against_voucher_type' : row.invoice_type, - 'against_voucher' : row.invoice_number, + 'voucher_type': row.get('reference_type'), + 'voucher_no' : row.get('reference_name'), + 'voucher_detail_no' : row.get('reference_row'), + 'against_voucher_type' : row.get('invoice_type'), + 'against_voucher' : row.get('invoice_number'), 'account' : self.receivable_payable_account, 'party_type': self.party_type, 'party': self.party, - 'is_advance' : row.is_advance, + 'is_advance' : row.get('is_advance'), 'dr_or_cr' : dr_or_cr, - 'unadjusted_amount' : flt(row.amount), - 'allocated_amount' : flt(row.allocated_amount), - 'difference_amount': row.difference_amount, - 'difference_account': row.difference_account + 'unreconciled_amount': flt(row.get('unreconciled_amount')), + 'unadjusted_amount' : flt(row.get('amount')), + 'allocated_amount' : flt(row.get('allocated_amount')), + 'difference_amount': flt(row.get('difference_amount')), + 'difference_account': row.get('difference_account') }) - @frappe.whitelist() - def get_difference_amount(self, child_row): - if child_row.get("reference_type") != 'Payment Entry': return - - child_row = frappe._dict(child_row) - - if child_row.invoice_number and " | " in child_row.invoice_number: - child_row.invoice_type, child_row.invoice_number = child_row.invoice_number.split(" | ") - - dr_or_cr = ("credit_in_account_currency" - if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") - - row = self.get_payment_details(child_row, dr_or_cr) - - doc = frappe.get_doc(row.voucher_type, row.voucher_no) - update_reference_in_payment_entry(row, doc, do_not_save=True) - - return doc.difference_amount - def check_mandatory_to_fetch(self): for fieldname in ["company", "party_type", "party", "receivable_payable_account"]: if not self.get(fieldname): frappe.throw(_("Please select {0} first").format(self.meta.get_label(fieldname))) - def validate_invoice(self): + def validate_entries(self): if not self.get("invoices"): - frappe.throw(_("No records found in the Invoice table")) + frappe.throw(_("No records found in the Invoices table")) if not self.get("payments"): - frappe.throw(_("No records found in the Payment table")) + frappe.throw(_("No records found in the Payments table")) + def validate_allocation(self): unreconciled_invoices = frappe._dict() - for d in self.get("invoices"): - unreconciled_invoices.setdefault(d.invoice_type, {}).setdefault(d.invoice_number, d.outstanding_amount) + + for inv in self.get("invoices"): + unreconciled_invoices.setdefault(inv.invoice_type, {}).setdefault(inv.invoice_number, inv.outstanding_amount) invoices_to_reconcile = [] - for p in self.get("payments"): - if p.invoice_type and p.invoice_number and p.allocated_amount: - invoices_to_reconcile.append(p.invoice_number) + for row in self.get("allocation"): + if row.invoice_type and row.invoice_number and row.allocated_amount: + invoices_to_reconcile.append(row.invoice_number) - if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}): - frappe.throw(_("{0}: {1} not found in Invoice Details table") - .format(p.invoice_type, p.invoice_number)) + if flt(row.amount) - flt(row.allocated_amount) < 0: + frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equal to remaining payment amount {2}") + .format(row.idx, row.allocated_amount, row.amount)) - if flt(p.allocated_amount) > flt(p.amount): - frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to Payment Entry amount {2}") - .format(p.idx, p.allocated_amount, p.amount)) - - invoice_outstanding = unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number) - if flt(p.allocated_amount) - invoice_outstanding > 0.009: - frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}") - .format(p.idx, p.allocated_amount, invoice_outstanding)) + invoice_outstanding = unreconciled_invoices.get(row.invoice_type, {}).get(row.invoice_number) + if flt(row.allocated_amount) - invoice_outstanding > 0.009: + frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equal to invoice outstanding amount {2}") + .format(row.idx, row.allocated_amount, invoice_outstanding)) if not invoices_to_reconcile: - frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row")) + frappe.throw(_("No records found in Allocation table")) - def check_condition(self): - cond = " and posting_date >= {0}".format(frappe.db.escape(self.from_date)) if self.from_date else "" - cond += " and posting_date <= {0}".format(frappe.db.escape(self.to_date)) if self.to_date else "" - dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' - else "credit_in_account_currency") + def get_conditions(self, get_invoices=False, get_payments=False, get_return_invoices=False): + condition = " and company = '{0}' ".format(self.company) - if self.minimum_amount: - cond += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_amount)) - if self.maximum_amount: - cond += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_amount)) + if get_invoices: + condition += " and posting_date >= {0}".format(frappe.db.escape(self.from_invoice_date)) if self.from_invoice_date else "" + condition += " and posting_date <= {0}".format(frappe.db.escape(self.to_invoice_date)) if self.to_invoice_date else "" + dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' + else "credit_in_account_currency") - return cond + if self.minimum_invoice_amount: + condition += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_invoice_amount)) + if self.maximum_invoice_amount: + condition += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_invoice_amount)) + + elif get_return_invoices: + condition = " and doc.company = '{0}' ".format(self.company) + condition += " and doc.posting_date >= {0}".format(frappe.db.escape(self.from_payment_date)) if self.from_payment_date else "" + condition += " and doc.posting_date <= {0}".format(frappe.db.escape(self.to_payment_date)) if self.to_payment_date else "" + dr_or_cr = ("gl.debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' + else "gl.credit_in_account_currency") + + if self.minimum_invoice_amount: + condition += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_payment_amount)) + if self.maximum_invoice_amount: + condition += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_payment_amount)) + + else: + condition += " and posting_date >= {0}".format(frappe.db.escape(self.from_payment_date)) if self.from_payment_date else "" + condition += " and posting_date <= {0}".format(frappe.db.escape(self.to_payment_date)) if self.to_payment_date else "" + + if self.minimum_payment_amount: + condition += " and unallocated_amount >= {0}".format(flt(self.minimum_payment_amount)) if get_payments \ + else " and total_debit >= {0}".format(flt(self.minimum_payment_amount)) + if self.maximum_payment_amount: + condition += " and unallocated_amount <= {0}".format(flt(self.maximum_payment_amount)) if get_payments \ + else " and total_debit <= {0}".format(flt(self.maximum_payment_amount)) + + return condition def reconcile_dr_cr_note(dr_cr_notes, company): - for d in dr_cr_notes: + for inv in dr_cr_notes: voucher_type = ('Credit Note' - if d.voucher_type == 'Sales Invoice' else 'Debit Note') + if inv.voucher_type == 'Sales Invoice' else 'Debit Note') reconcile_dr_or_cr = ('debit_in_account_currency' - if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency') + if inv.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency') company_currency = erpnext.get_company_currency(company) @@ -283,25 +341,25 @@ def reconcile_dr_cr_note(dr_cr_notes, company): "voucher_type": voucher_type, "posting_date": today(), "company": company, - "multi_currency": 1 if d.currency != company_currency else 0, + "multi_currency": 1 if inv.currency != company_currency else 0, "accounts": [ { - 'account': d.account, - 'party': d.party, - 'party_type': d.party_type, - d.dr_or_cr: abs(d.allocated_amount), - 'reference_type': d.against_voucher_type, - 'reference_name': d.against_voucher, + 'account': inv.account, + 'party': inv.party, + 'party_type': inv.party_type, + inv.dr_or_cr: abs(inv.allocated_amount), + 'reference_type': inv.against_voucher_type, + 'reference_name': inv.against_voucher, 'cost_center': erpnext.get_default_cost_center(company) }, { - 'account': d.account, - 'party': d.party, - 'party_type': d.party_type, - reconcile_dr_or_cr: (abs(d.allocated_amount) - if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)), - 'reference_type': d.voucher_type, - 'reference_name': d.voucher_no, + 'account': inv.account, + 'party': inv.party, + 'party_type': inv.party_type, + reconcile_dr_or_cr: (abs(inv.allocated_amount) + if abs(inv.unadjusted_amount) > abs(inv.allocated_amount) else abs(inv.unadjusted_amount)), + 'reference_type': inv.voucher_type, + 'reference_name': inv.voucher_no, 'cost_center': erpnext.get_default_cost_center(company) } ] diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py new file mode 100644 index 00000000000..2271f48a2b9 --- /dev/null +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -0,0 +1,9 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +import unittest + + +class TestPaymentReconciliation(unittest.TestCase): + pass diff --git a/erpnext/portal/doctype/products_settings/__init__.py b/erpnext/accounts/doctype/payment_reconciliation_allocation/__init__.py similarity index 100% rename from erpnext/portal/doctype/products_settings/__init__.py rename to erpnext/accounts/doctype/payment_reconciliation_allocation/__init__.py diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json new file mode 100644 index 00000000000..36535014320 --- /dev/null +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json @@ -0,0 +1,137 @@ +{ + "actions": [], + "creation": "2021-08-16 17:04:40.185167", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "reference_type", + "reference_name", + "column_break_3", + "invoice_type", + "invoice_number", + "section_break_6", + "allocated_amount", + "unreconciled_amount", + "amount", + "column_break_8", + "is_advance", + "section_break_5", + "difference_amount", + "column_break_7", + "difference_account" + ], + "fields": [ + { + "fieldname": "invoice_number", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Invoice Number", + "options": "invoice_type", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "allocated_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Allocated Amount", + "options": "Currency", + "reqd": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, + { + "fieldname": "difference_account", + "fieldtype": "Link", + "label": "Difference Account", + "options": "Account", + "read_only": 1 + }, + { + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, + { + "fieldname": "difference_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Difference Amount", + "options": "Currency", + "read_only": 1 + }, + { + "fieldname": "reference_name", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Reference Name", + "options": "reference_type", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "is_advance", + "fieldtype": "Data", + "hidden": 1, + "label": "Is Advance", + "read_only": 1 + }, + { + "fieldname": "reference_type", + "fieldtype": "Link", + "label": "Reference Type", + "options": "DocType", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "invoice_type", + "fieldtype": "Link", + "label": "Invoice Type", + "options": "DocType", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "fieldname": "unreconciled_amount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Unreconciled Amount", + "options": "Currency", + "read_only": 1 + }, + { + "fieldname": "amount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Amount", + "options": "Currency", + "read_only": 1 + } + ], + "istable": 1, + "links": [], + "modified": "2021-08-30 10:58:42.665107", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Reconciliation Allocation", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py new file mode 100644 index 00000000000..9db8e62af08 --- /dev/null +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py @@ -0,0 +1,9 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class PaymentReconciliationAllocation(Document): + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json index 6a79a85c348..00c9e1240c5 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json +++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json @@ -44,7 +44,6 @@ { "fieldname": "amount", "fieldtype": "Currency", - "in_list_view": 1, "label": "Amount", "options": "currency", "read_only": 1 @@ -67,7 +66,7 @@ ], "istable": 1, "links": [], - "modified": "2020-07-19 18:12:27.964073", + "modified": "2021-08-24 22:42:40.923179", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Invoice", diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py index 800d8009754..5ac1855c030 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py +++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PaymentReconciliationInvoice(Document): pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json index 925a6f10a5e..add07e870d8 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json @@ -11,11 +11,7 @@ "is_advance", "reference_row", "col_break1", - "invoice_number", "amount", - "allocated_amount", - "section_break_10", - "difference_account", "difference_amount", "sec_break1", "remark", @@ -41,6 +37,7 @@ { "fieldname": "posting_date", "fieldtype": "Date", + "in_list_view": 1, "label": "Posting Date", "read_only": 1 }, @@ -62,14 +59,6 @@ "fieldname": "col_break1", "fieldtype": "Column Break" }, - { - "columns": 2, - "fieldname": "invoice_number", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Invoice Number", - "reqd": 1 - }, { "columns": 2, "fieldname": "amount", @@ -79,15 +68,6 @@ "options": "currency", "read_only": 1 }, - { - "columns": 2, - "fieldname": "allocated_amount", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Allocated amount", - "options": "currency", - "reqd": 1 - }, { "fieldname": "sec_break1", "fieldtype": "Section Break" @@ -95,41 +75,27 @@ { "fieldname": "remark", "fieldtype": "Small Text", - "in_list_view": 1, "label": "Remark", "read_only": 1 }, - { - "columns": 2, - "fieldname": "difference_account", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Difference Account", - "options": "Account" - }, - { - "fieldname": "difference_amount", - "fieldtype": "Currency", - "label": "Difference Amount", - "options": "currency", - "print_hide": 1, - "read_only": 1 - }, - { - "fieldname": "section_break_10", - "fieldtype": "Section Break" - }, { "fieldname": "currency", "fieldtype": "Link", "hidden": 1, "label": "Currency", "options": "Currency" + }, + { + "fieldname": "difference_amount", + "fieldtype": "Currency", + "label": "Difference Amount", + "options": "currency", + "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2020-07-19 18:12:41.682347", + "modified": "2021-08-30 10:51:48.140062", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Payment", diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py index c76f7852c8c..78c84ff5a6a 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PaymentReconciliationPayment(Document): pass diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index f83cb375fcf..c5b8b548cc0 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -3,18 +3,25 @@ # For license information, please see license.txt from __future__ import unicode_literals + import json + import frappe from frappe import _ +from frappe.integrations.utils import get_payment_gateway_controller from frappe.model.document import Document -from frappe.utils import flt, nowdate, get_url +from frappe.utils import flt, get_url, nowdate +from frappe.utils.background_jobs import enqueue + +from erpnext.accounts.doctype.payment_entry.payment_entry import ( + get_company_defaults, + get_payment_entry, +) +from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate from erpnext.accounts.party import get_party_account, get_party_bank_account from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, get_company_defaults -from frappe.integrations.utils import get_payment_gateway_controller -from frappe.utils.background_jobs import enqueue from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription -from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate + class PaymentRequest(Document): def validate(self): @@ -286,7 +293,7 @@ class PaymentRequest(Document): if not status: return - shopping_cart_settings = frappe.get_doc("Shopping Cart Settings") + shopping_cart_settings = frappe.get_doc("E Commerce Settings") if status in ["Authorized", "Completed"]: redirect_to = None @@ -436,7 +443,7 @@ def get_gateway_details(args): return get_payment_gateway_account(args.get("payment_gateway_account")) if args.order_type == "Shopping Cart": - payment_gateway_account = frappe.get_doc("Shopping Cart Settings").payment_gateway_account + payment_gateway_account = frappe.get_doc("E Commerce Settings").payment_gateway_account return get_payment_gateway_account(payment_gateway_account) gateway_account = get_payment_gateway_account({"is_default": 1}) @@ -542,3 +549,11 @@ def make_payment_order(source_name, target_doc=None): }, target_doc, set_missing_values) return doclist + +def validate_payment(doc, method=""): + if not frappe.db.has_column(doc.reference_doctype, 'status'): + return + + status = frappe.db.get_value(doc.reference_doctype, doc.reference_docname, 'status') + if status == 'Paid': + frappe.throw(_("The Payment Request {0} is already paid, cannot process payment twice").format(doc.reference_docname)) \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index ad6ff6f5553..c97c873fc4e 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -3,11 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + +import frappe + from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.setup.utils import get_exchange_rate test_dependencies = ["Currency Exchange", "Journal Entry", "Contact", "Address"] diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py index 41740170f03..33d5efa10e3 100644 --- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py +++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/payment_term/payment_term.py b/erpnext/accounts/doctype/payment_term/payment_term.py index 5d4df053fb2..a04c183bedc 100644 --- a/erpnext/accounts/doctype/payment_term/payment_term.py +++ b/erpnext/accounts/doctype/payment_term/payment_term.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/payment_term/test_payment_term.py b/erpnext/accounts/doctype/payment_term/test_payment_term.py index d9baa5907b9..bc0645f9a62 100644 --- a/erpnext/accounts/doctype/payment_term/test_payment_term.py +++ b/erpnext/accounts/doctype/payment_term/test_payment_term.py @@ -2,6 +2,7 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py index 39627eb376a..35685911324 100644 --- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py @@ -5,9 +5,9 @@ from __future__ import unicode_literals import frappe -from frappe.model.document import Document -from frappe.utils import flt, cint from frappe import _ +from frappe.model.document import Document +from frappe.utils import flt class PaymentTermsTemplate(Document): diff --git a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py index 6daaf1ed74e..2052a5093d2 100644 --- a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py @@ -2,6 +2,7 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest import frappe diff --git a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py index 54c0fda0119..c857a88b9f5 100644 --- a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py +++ b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index 16fc98b38c2..9f30dc00c1e 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -2,13 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt from frappe import _ +from frappe.utils import flt + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimensions, +) from erpnext.accounts.utils import get_account_currency from erpnext.controllers.accounts_controller import AccountsController -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (get_accounting_dimensions, - get_dimensions) + class PeriodClosingVoucher(AccountsController): def validate(self): @@ -54,7 +59,7 @@ class PeriodClosingVoucher(AccountsController): if gl_entries: from erpnext.accounts.general_ledger import make_gl_entries make_gl_entries(gl_entries) - + def get_gl_entries(self): gl_entries = [] pl_accounts = self.get_pl_balances() @@ -77,7 +82,7 @@ class PeriodClosingVoucher(AccountsController): gl_entries += gle_for_net_pl_bal return gl_entries - + def get_pnl_gl_entry(self, pl_accounts): company_cost_center = frappe.db.get_value("Company", self.company, "cost_center") gl_entries = [] diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 2a636bb3381..2d417a4cfba 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -3,13 +3,17 @@ from __future__ import unicode_literals + import unittest + import frappe -from frappe.utils import flt, today -from erpnext.accounts.utils import get_fiscal_year, now -from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry +from frappe.utils import today + from erpnext.accounts.doctype.finance_book.test_finance_book import create_finance_book +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.utils import get_fiscal_year, now + class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py index 82528728ddc..896ebdfd5e6 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import json from frappe import _ -from frappe.utils import get_datetime, flt +from frappe.utils import flt, get_datetime + +from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + unconsolidate_pos_invoices, +) from erpnext.controllers.status_updater import StatusUpdater -from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data -from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import consolidate_pos_invoices, unconsolidate_pos_invoices + class POSClosingEntry(StatusUpdater): def validate(self): diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index b596c0cf25a..256ade4f47b 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -2,14 +2,19 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe + import unittest -from frappe.utils import nowdate -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + +import frappe + +from erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry import ( + make_closing_entry_from_opening, +) from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice -from erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry import make_closing_entry_from_opening from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + class TestPOSClosingEntry(unittest.TestCase): def setUp(self): diff --git a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py index 46b6c773bc3..4293abdfdc1 100644 --- a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py +++ b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class POSClosingEntryDetail(Document): pass diff --git a/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py index f72d9a61e10..74cf7540311 100644 --- a/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py +++ b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class POSClosingEntryTaxes(Document): pass diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py index 85c1c9f8ddf..570eb9ea177 100644 --- a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py +++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class POSCustomerGroup(Document): pass diff --git a/erpnext/accounts/doctype/pos_field/pos_field.py b/erpnext/accounts/doctype/pos_field/pos_field.py index b4720b309bd..00faebb7abb 100644 --- a/erpnext/accounts/doctype/pos_field/pos_field.py +++ b/erpnext/accounts/doctype/pos_field/pos_field.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSField(Document): pass diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index 19c6c8f3472..bff85872781 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -622,6 +622,7 @@ "read_only": 1 }, { + "depends_on": "packed_items", "fieldname": "packing_list", "fieldtype": "Section Break", "label": "Packing List", @@ -629,6 +630,7 @@ "print_hide": 1 }, { + "depends_on": "packed_items", "fieldname": "packed_items", "fieldtype": "Table", "label": "Packed Items", @@ -1564,7 +1566,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2021-08-24 18:19:20.728433", + "modified": "2021-08-27 20:12:57.306772", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 034a217a26d..d6e41e6f90d 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -3,19 +3,24 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document -from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.party import get_party_account, get_due_date -from frappe.utils import cint, flt, getdate, nowdate, get_link_to_form -from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request -from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points -from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos -from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice, get_bank_cash_account, update_multi_mode_option, get_mode_of_payment_info - +from frappe.utils import cint, flt, get_link_to_form, getdate, nowdate from six import iteritems +from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points +from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request +from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + SalesInvoice, + get_bank_cash_account, + get_mode_of_payment_info, + update_multi_mode_option, +) +from erpnext.accounts.party import get_due_date, get_party_account +from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos + + class POSInvoice(SalesInvoice): def __init__(self, *args, **kwargs): super(POSInvoice, self).__init__(*args, **kwargs) @@ -309,7 +314,7 @@ class POSInvoice(SalesInvoice): def set_pos_fields(self, for_validate=False): """Set retail related fields from POS Profiles""" - from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile + from erpnext.stock.get_item_details import get_pos_profile, get_pos_profile_item_details if not self.pos_profile: pos_profile = get_pos_profile(self.company) or {} if not pos_profile: @@ -519,6 +524,7 @@ def make_sales_return(source_name, target_doc=None): @frappe.whitelist() def make_merge_log(invoices): import json + from six import string_types if isinstance(invoices, string_types): diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index d2527fb2e50..e6e0dd238f0 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -3,14 +3,18 @@ # See license.txt from __future__ import unicode_literals +import copy +import unittest + import frappe -import unittest, copy, time -from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile + from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt -from erpnext.stock.doctype.item.test_item import make_item +from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + class TestPOSInvoice(unittest.TestCase): @classmethod @@ -213,8 +217,8 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(pos_return.get('payments')[1].amount, -500) def test_pos_return_for_serialized_item(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item(company='_Test Company', target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC') @@ -239,8 +243,8 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(pos_return.get('items')[0].serial_no, serial_nos[0]) def test_partial_pos_returns(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item(company='_Test Company', target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC') @@ -293,8 +297,8 @@ class TestPOSInvoice(unittest.TestCase): self.assertRaises(frappe.ValidationError, inv.insert) def test_serialized_item_transaction(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item(company='_Test Company', target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC') @@ -324,8 +328,8 @@ class TestPOSInvoice(unittest.TestCase): self.assertRaises(frappe.ValidationError, pos2.submit) def test_delivered_serialized_item_transaction(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item(company='_Test Company', target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC') @@ -353,8 +357,10 @@ class TestPOSInvoice(unittest.TestCase): self.assertRaises(frappe.ValidationError, pos2.submit) def test_loyalty_points(self): + from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( + get_loyalty_program_details_with_points, + ) from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records - from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points create_records() frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty") @@ -374,7 +380,10 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(after_cancel_lp_details.loyalty_points, before_lp_details.loyalty_points) def test_loyalty_points_redeemption(self): - from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points + from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( + get_loyalty_program_details_with_points, + ) + # add 10 loyalty points create_pos_invoice(customer="Test Loyalty Customer", rate=10000) @@ -392,8 +401,12 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(after_redeem_lp_details.loyalty_points, 9) def test_merging_into_sales_invoice_with_discount(self): - from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile - from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import consolidate_pos_invoices + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + ) frappe.db.sql("delete from `tabPOS Invoice`") test_user, pos_profile = init_user_and_profile() @@ -416,8 +429,12 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(rounded_total, 3470) def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self): - from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile - from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import consolidate_pos_invoices + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + ) frappe.db.sql("delete from `tabPOS Invoice`") test_user, pos_profile = init_user_and_profile() @@ -457,8 +474,12 @@ class TestPOSInvoice(unittest.TestCase): self.assertEqual(rounded_total, 840) def test_merging_with_validate_selling_price(self): - from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile - from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import consolidate_pos_invoices + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + ) if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"): frappe.db.set_value("Selling Settings", "Selling Settings", "validate_selling_price", 1) diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py index 92ce61be529..99e471991c3 100644 --- a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py +++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSInvoiceItem(Document): pass diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index e50d437ba6a..0be8ca7ee69 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -3,17 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import json + import frappe +import six from frappe import _ -from frappe.model import default_fields +from frappe.core.page.background_jobs.background_jobs import get_info from frappe.model.document import Document +from frappe.model.mapper import map_child_doc, map_doc from frappe.utils import flt, getdate, nowdate from frappe.utils.background_jobs import enqueue -from frappe.model.mapper import map_doc, map_child_doc from frappe.utils.scheduler import is_scheduler_inactive -from frappe.core.page.background_jobs.background_jobs import get_info -import json -import six + class POSInvoiceMergeLog(Document): def validate(self): diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py index 1b9659409c0..c531bb9f079 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py @@ -3,13 +3,18 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest import json -from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice -from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return -from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import consolidate_pos_invoices +import unittest + +import frappe + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile +from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return +from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice +from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, +) + class TestPOSInvoiceMergeLog(unittest.TestCase): def test_consolidated_invoice_creation(self): diff --git a/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py index 4c45265f608..9bce082c958 100644 --- a/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py +++ b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSInvoiceReference(Document): pass diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py index ceaa57ba60c..b5ff794ccc3 100644 --- a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py +++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class POSItemGroup(Document): pass diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py index 3318fefab14..979479ffb58 100644 --- a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py +++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cint, get_link_to_form + from erpnext.controllers.status_updater import StatusUpdater + class POSOpeningEntry(StatusUpdater): def validate(self): self.validate_pos_profile_and_cashier() diff --git a/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py index c115be5ae94..35a2b5835fd 100644 --- a/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py +++ b/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestPOSOpeningEntry(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py index 555706227fc..be5d876a164 100644 --- a/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py +++ b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSOpeningEntryDetail(Document): pass diff --git a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py index 8a46d84bfe2..851d8efde1d 100644 --- a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py +++ b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSPaymentMethod(Document): pass diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index cf7ed26d277..b64e2eda2db 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ -from frappe.utils import cint, now, get_link_to_form -from six import iteritems +from frappe import _, msgprint from frappe.model.document import Document +from frappe.utils import get_link_to_form, now +from six import iteritems + class POSProfile(Document): def validate(self): diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index 0033965700e..83ecfb47bb5 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -3,10 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.stock.get_item_details import get_pos_profile + +import frappe + from erpnext.accounts.doctype.pos_profile.pos_profile import get_child_nodes +from erpnext.stock.get_item_details import get_pos_profile test_dependencies = ['Item'] diff --git a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py index d77cddea614..404c4ab6296 100644 --- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py +++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class POSProfileUser(Document): pass diff --git a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py index 5c69ab1fb8f..dca35564082 100644 --- a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py +++ b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestPOSProfileUser(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py b/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py index 720ea77745f..32f9f9298b1 100644 --- a/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py +++ b/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class POSSearchFields(Document): pass diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.py b/erpnext/accounts/doctype/pos_settings/pos_settings.py index d925dd9d86e..5c5aaa04ed3 100644 --- a/erpnext/accounts/doctype/pos_settings/pos_settings.py +++ b/erpnext/accounts/doctype/pos_settings/pos_settings.py @@ -3,9 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class POSSettings(Document): def validate(self): pass diff --git a/erpnext/accounts/doctype/pos_settings/test_pos_settings.py b/erpnext/accounts/doctype/pos_settings/test_pos_settings.py index a3df10803c0..949fed775bf 100644 --- a/erpnext/accounts/doctype/pos_settings/test_pos_settings.py +++ b/erpnext/accounts/doctype/pos_settings/test_pos_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestPOSSettings(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 4903c50e17b..e5bf3b80641 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -3,15 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -import json + import copy +import json import re -from frappe import throw, _ -from frappe.utils import flt, cint, getdate +import frappe +from frappe import _, throw from frappe.model.document import Document - +from frappe.utils import cint, flt, getdate from six import string_types apply_on_dict = {"Item Code": "items", @@ -203,13 +203,13 @@ def apply_pricing_rule(args, doc=None): serialized_items = dict() for item_code, val in query_items: serialized_items.setdefault(item_code, val) - + for item in item_list: args_copy = copy.deepcopy(args) args_copy.update(item) data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc) out.append(data) - + if serialized_items.get(item.get('item_code')) and not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'): out[0].update(get_serial_no_for_item(args_copy)) @@ -228,8 +228,12 @@ def get_serial_no_for_item(args): return item_details def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False): - from erpnext.accounts.doctype.pricing_rule.utils import (get_pricing_rules, - get_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule) + from erpnext.accounts.doctype.pricing_rule.utils import ( + get_applied_pricing_rules, + get_pricing_rule_items, + get_pricing_rules, + get_product_discount_rule, + ) if isinstance(doc, string_types): doc = json.loads(doc) @@ -315,9 +319,8 @@ def update_args_for_pricing_rule(args): if not (args.item_group and args.brand): try: args.item_group, args.brand = frappe.get_cached_value("Item", args.item_code, ["item_group", "brand"]) - except TypeError: - # invalid item_code - return item_details + except frappe.DoesNotExistError: + return if not args.item_group: frappe.throw(_("Item Group not mentioned in item master for item {0}").format(args.item_code)) @@ -390,8 +393,10 @@ def apply_price_discount_rule(pricing_rule, item_details, args): if pricing_rule else args.get(field, 0)) def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): - from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules, - get_pricing_rule_items) + from erpnext.accounts.doctype.pricing_rule.utils import ( + get_applied_pricing_rules, + get_pricing_rule_items, + ) for d in get_applied_pricing_rules(pricing_rules): if not d or not frappe.db.exists("Pricing Rule", d): continue pricing_rule = frappe.get_cached_doc('Pricing Rule', d) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 662d7704a55..e2b23704c88 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -3,14 +3,18 @@ from __future__ import unicode_literals + import unittest + import frappe -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError -from erpnext.stock.doctype.item.test_item import make_item + +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.healthcare.doctype.lab_test_template.lab_test_template import make_item_price +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.get_item_details import get_item_details + class TestPricingRule(unittest.TestCase): def setUp(self): @@ -20,9 +24,10 @@ class TestPricingRule(unittest.TestCase): delete_existing_pricing_rules() def test_pricing_rule_for_discount(self): - from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError + from erpnext.stock.get_item_details import get_item_details + test_record = { "doctype": "Pricing Rule", "title": "_Test Pricing Rule", @@ -102,9 +107,10 @@ class TestPricingRule(unittest.TestCase): self.assertEqual(details.get("discount_percentage"), 15) def test_pricing_rule_for_margin(self): - from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError + from erpnext.stock.get_item_details import get_item_details + test_record = { "doctype": "Pricing Rule", "title": "_Test Pricing Rule", @@ -195,9 +201,10 @@ class TestPricingRule(unittest.TestCase): self.assertEqual(details.get("discount_percentage"), 10) def test_pricing_rule_for_variants(self): - from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError + from erpnext.stock.get_item_details import get_item_details + if not frappe.db.exists("Item", "Test Variant PRT"): frappe.get_doc({ "doctype": "Item", diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 5467cb0bc5b..12b486e45eb 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -8,14 +8,14 @@ from __future__ import unicode_literals import copy import json -from six import string_types - import frappe +from frappe import _, bold +from frappe.utils import cint, flt, fmt_money, get_link_to_form, getdate, today + from erpnext.setup.doctype.item_group.item_group import get_child_item_groups from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses from erpnext.stock.get_item_details import get_conversion_factor -from frappe import _, bold -from frappe.utils import cint, flt, get_link_to_form, getdate, today, fmt_money + class MultiplePricingRuleConflict(frappe.ValidationError): pass @@ -81,7 +81,7 @@ def filter_pricing_rule_based_on_condition(pricing_rules, doc=None): try: if frappe.safe_eval(pricing_rule.condition, None, doc.as_dict()): filtered_pricing_rules.append(pricing_rule) - except: + except Exception: pass else: filtered_pricing_rules.append(pricing_rule) diff --git a/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py b/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py index e2f70af4a12..5e10b8411a4 100644 --- a/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py +++ b/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PricingRuleBrand(Document): pass diff --git a/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py b/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py index 3cb7da91584..a90ecbb6f7f 100644 --- a/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py +++ b/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PricingRuleDetail(Document): pass diff --git a/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py b/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py index 4468620314c..4746b39e175 100644 --- a/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py +++ b/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PricingRuleItemCode(Document): pass diff --git a/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py b/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py index d3c36197c77..ff1ba75a60f 100644 --- a/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py +++ b/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PricingRuleItemGroup(Document): pass diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py index 5e7583a9745..72b7b23e149 100644 --- a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py +++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py @@ -3,13 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _ from frappe.model.document import Document + +from erpnext.accounts.deferred_revenue import ( + build_conditions, + convert_deferred_expense_to_expense, + convert_deferred_revenue_to_income, +) from erpnext.accounts.general_ledger import make_reverse_gl_entries -from erpnext.accounts.deferred_revenue import convert_deferred_expense_to_expense, \ - convert_deferred_revenue_to_income, build_conditions + class ProcessDeferredAccounting(Document): def validate(self): diff --git a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py index 03c269ac766..69e2caa8e82 100644 --- a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py +++ b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py @@ -3,11 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.accounts.doctype.account.test_account import create_account +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import ( + check_gl_entries, + create_sales_invoice, +) from erpnext.stock.doctype.item.test_item import create_item -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice, check_gl_entries + class TestProcessDeferredAccounting(unittest.TestCase): def test_creation_of_ledger_entry_on_submit(self): diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index a12ea4033df..73f30385120 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -3,22 +3,24 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import copy + import frappe from frappe import _ from frappe.model.document import Document -from erpnext.accounts.report.general_ledger.general_ledger import execute as get_soa -from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import execute as get_ageing +from frappe.utils import add_days, add_months, format_date, getdate, today +from frappe.utils.jinja import validate_template +from frappe.utils.pdf import get_pdf +from frappe.www.printview import get_print_style + from erpnext import get_company_currency from erpnext.accounts.party import get_party_account_currency +from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import ( + execute as get_ageing, +) +from erpnext.accounts.report.general_ledger.general_ledger import execute as get_soa -from frappe.utils.print_format import report_to_pdf -from frappe.utils.pdf import get_pdf -from frappe.utils import today, add_days, add_months, getdate, format_date -from frappe.utils.jinja import validate_template - -import copy -from datetime import timedelta -from frappe.www.printview import get_print_style class ProcessStatementOfAccounts(Document): def validate(self): @@ -158,7 +160,7 @@ def get_recipients_and_cc(customer, doc): if doc.cc_to != '': try: cc=[frappe.get_value('User', doc.cc_to, 'email')] - except: + except Exception: pass return recipients, cc diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py index 30efbb36833..7ddcd105af9 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestProcessStatementOfAccounts(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py index 1a760101dba..fe940094071 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProcessStatementOfAccountsCustomer(Document): pass diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py index 3d7a891f333..d09f7dc2da2 100644 --- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py @@ -3,10 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cstr -from frappe.model.naming import make_autoname from frappe.model.document import Document pricing_rule_fields = ['apply_on', 'mixed_conditions', 'is_cumulative', 'other_item_code', 'other_item_group', diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme_dashboard.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme_dashboard.py index 54fedb77387..6d079242682 100644 --- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme_dashboard.py +++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme_dashboard.py @@ -1,5 +1,6 @@ from frappe import _ + def get_data(): return { 'fieldname': 'promotional_scheme', diff --git a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py index 286f7cf6edd..190b734cc17 100644 --- a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestPromotionalScheme(unittest.TestCase): def test_promotional_scheme(self): ps = make_promotional_scheme() diff --git a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py index 380ae32f9a5..ab8efc33141 100644 --- a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py +++ b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PromotionalSchemePriceDiscount(Document): pass diff --git a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py index 2931106f768..85019b4e455 100644 --- a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py +++ b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PromotionalSchemeProductDiscount(Document): pass diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py index 0aeef3ed3a8..cb5aaa9c5e0 100644 --- a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py +++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PSOACostCenter(Document): pass diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.py b/erpnext/accounts/doctype/psoa_project/psoa_project.py index f4a5dee9752..1cd995179d5 100644 --- a/erpnext/accounts/doctype/psoa_project/psoa_project.py +++ b/erpnext/accounts/doctype/psoa_project/psoa_project.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PSOAProject(Document): pass diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index fdd8765b411..81c391e5582 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -3,29 +3,42 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate, get_link_to_form -from frappe import _, throw -import frappe.defaults -from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account -from erpnext.controllers.buying_controller import BuyingController -from erpnext.accounts.party import get_party_account, get_due_date -from erpnext.accounts.utils import get_account_currency, get_fiscal_year -from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po -from erpnext.stock import get_warehouse_account_map -from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, make_reverse_gl_entries -from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt -from erpnext.buying.utils import check_on_hold_or_closed_status -from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center -from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled +import frappe +from frappe import _, throw from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate from six import iteritems -from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\ - unlink_inter_company_doc, check_if_return_invoice_linked_with_payment_entry -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details + +import erpnext from erpnext.accounts.deferred_revenue import validate_service_stop_date -from erpnext.stock.doctype.purchase_receipt.purchase_receipt import get_item_account_wise_additional_cost +from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt +from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + check_if_return_invoice_linked_with_payment_entry, + unlink_inter_company_doc, + update_linked_doc, + validate_inter_company_party, +) +from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( + get_party_tax_withholding_details, +) +from erpnext.accounts.general_ledger import ( + get_round_off_account_and_cost_center, + make_gl_entries, + make_reverse_gl_entries, + merge_similar_entries, +) +from erpnext.accounts.party import get_due_date, get_party_account +from erpnext.accounts.utils import get_account_currency, get_fiscal_year +from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled +from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account +from erpnext.buying.utils import check_on_hold_or_closed_status +from erpnext.controllers.buying_controller import BuyingController +from erpnext.stock import get_warehouse_account_map +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + get_item_account_wise_additional_cost, + update_billed_amount_based_on_po, +) form_grid_templates = { "items": "templates/form_grid/item_grid.html" diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py index b6467a3d5ca..4cc319d594f 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'purchase_invoice', diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index bfe34bb4a73..e77b60bb1cd 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -3,20 +3,25 @@ from __future__ import unicode_literals + import unittest -import frappe, erpnext -import frappe.model + +import frappe +from frappe.utils import add_days, cint, flt, getdate, nowdate, today + +import erpnext +from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry -from frappe.utils import cint, flt, today, nowdate, add_days, getdate -import frappe.defaults -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt, get_taxes +from erpnext.buying.doctype.supplier.test_supplier import create_supplier from erpnext.controllers.accounts_controller import get_payment_terms from erpnext.exceptions import InvalidCurrency -from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction from erpnext.projects.doctype.project.test_project import make_project -from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.stock.doctype.item.test_item import create_item -from erpnext.buying.doctype.supplier.test_supplier import create_supplier +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import ( + get_taxes, + make_purchase_receipt, +) +from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"] test_ignore = ["Serial No"] @@ -380,8 +385,9 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(tax.total, expected_values[i][2]) def test_purchase_invoice_with_advance(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.copy_doc(jv_test_records[1]) jv.insert() @@ -420,8 +426,9 @@ class TestPurchaseInvoice(unittest.TestCase): where reference_type='Purchase Invoice' and reference_name=%s""", pi.name)) def test_invoice_with_advance_and_multi_payment_terms(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.copy_doc(jv_test_records[1]) jv.insert() @@ -693,8 +700,9 @@ class TestPurchaseInvoice(unittest.TestCase): "warehouse"), pi.get("items")[0].rejected_warehouse) def test_outstanding_amount_after_advance_jv_cancelation(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.copy_doc(jv_test_records[1]) jv.accounts[0].is_advance = 'Yes' @@ -773,8 +781,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance)) def test_purchase_invoice_with_shipping_rule(self): - from erpnext.accounts.doctype.shipping_rule.test_shipping_rule \ - import create_shipping_rule + from erpnext.accounts.doctype.shipping_rule.test_shipping_rule import create_shipping_rule shipping_rule = create_shipping_rule(shipping_rule_type = "Buying", shipping_rule_name = "Shipping Rule - Purchase Invoice Test") @@ -1112,9 +1119,9 @@ class TestPurchaseInvoice(unittest.TestCase): frappe.db.set_value("Company", "_Test Company", "exchange_gain_loss_account", original_account) def test_purchase_invoice_advance_taxes(self): - from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice + from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order # create a new supplier to test supplier = create_supplier(supplier_name = '_Test TDS Advance Supplier', diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py index d157837a7a5..ec2ce65168d 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseInvoiceAdvance(Document): pass diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 51e5c1a6a9a..eab98a7e3fd 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -8,6 +8,7 @@ "engine": "InnoDB", "field_order": [ "item_code", + "product_bundle", "col_break1", "item_name", "description_section", @@ -857,12 +858,19 @@ "fieldtype": "Link", "label": "Discount Account", "options": "Account" + }, + { + "fieldname": "product_bundle", + "fieldtype": "Link", + "label": "Product Bundle", + "options": "Product Bundle", + "read_only": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-08-12 20:14:45.506639", + "modified": "2021-09-01 16:04:03.538643", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", @@ -870,4 +878,4 @@ "permissions": [], "sort_field": "modified", "sort_order": "DESC" -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py index 50ec7d8b4d8..ad2a24c0e2f 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseInvoiceItem(Document): pass diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py index 5854ddee940..34ac25753b3 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseTaxesandCharges(Document): pass diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py index efcef469bde..53b549f6829 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py @@ -3,10 +3,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document -from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_charges_template \ - import valdiate_taxes_and_charges_template + +from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_charges_template import ( + valdiate_taxes_and_charges_template, +) + class PurchaseTaxesandChargesTemplate(Document): def validate(self): diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.py b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.py index 97fbca31b6b..c60c81b7239 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Purchase Taxes and Charges Template') diff --git a/erpnext/accounts/doctype/salary_component_account/salary_component_account.py b/erpnext/accounts/doctype/salary_component_account/salary_component_account.py index 983d0156a58..d96ef62c293 100644 --- a/erpnext/accounts/doctype/salary_component_account/salary_component_account.py +++ b/erpnext/accounts/doctype/salary_component_account/salary_component_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SalaryComponentAccount(Document): pass diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 7427f381aba..f59f5748f35 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -566,6 +566,9 @@ frappe.ui.form.on('Sales Invoice', { frm.add_fetch('payment_term', 'invoice_portion', 'invoice_portion'); frm.add_fetch('payment_term', 'description', 'description'); + frm.set_df_property('packed_items', 'cannot_add_rows', true); + frm.set_df_property('packed_items', 'cannot_delete_rows', true); + frm.set_query("account_for_change_amount", function() { return { filters: { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 2f8de068840..314d83f2ac0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -696,7 +696,6 @@ "hide_days": 1, "hide_seconds": 1, "label": "Scan Barcode", - "length": 1, "options": "Barcode" }, { @@ -728,6 +727,7 @@ "read_only": 1 }, { + "depends_on": "packed_items", "fieldname": "packing_list", "fieldtype": "Section Break", "hide_days": 1, @@ -737,6 +737,7 @@ "print_hide": 1 }, { + "depends_on": "packed_items", "fieldname": "packed_items", "fieldtype": "Table", "hide_days": 1, @@ -2031,7 +2032,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-08-25 15:46:05.279588", + "modified": "2021-09-08 15:24:25.486499", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0a7042fa47c..458a17c43a0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -2,34 +2,51 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -import frappe.defaults -from frappe.utils import cint, flt, getdate, add_days, add_months, cstr, nowdate, get_link_to_form, formatdate + +import frappe from frappe import _, msgprint, throw -from erpnext.accounts.party import get_party_account, get_due_date, get_party_details -from frappe.model.mapper import get_mapped_doc -from erpnext.controllers.selling_controller import SellingController -from erpnext.accounts.utils import get_account_currency -from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so -from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data -from erpnext.assets.doctype.asset.depreciation \ - import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain, post_depreciation_entries -from erpnext.stock.doctype.batch.batch import set_batch_nos -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, get_delivery_note_serial_no -from erpnext.setup.doctype.company.company import update_company_current_month_sales -from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center -from erpnext.accounts.doctype.loyalty_program.loyalty_program import \ - get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points -from erpnext.accounts.deferred_revenue import validate_service_stop_date -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details -from frappe.model.utils import get_fetch_values from frappe.contacts.doctype.address.address import get_address_display -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details - -from erpnext.healthcare.utils import manage_invoice_submit_cancel - +from frappe.model.mapper import get_mapped_doc +from frappe.model.utils import get_fetch_values +from frappe.utils import ( + add_days, + add_months, + cint, + cstr, + flt, + formatdate, + get_link_to_form, + getdate, + nowdate, +) from six import iteritems +import erpnext +from erpnext.accounts.deferred_revenue import validate_service_stop_date +from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( + get_loyalty_program_details_with_points, + validate_loyalty_points, +) +from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( + get_party_tax_withholding_details, +) +from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center +from erpnext.accounts.party import get_due_date, get_party_account, get_party_details +from erpnext.accounts.utils import get_account_currency +from erpnext.assets.doctype.asset.depreciation import ( + get_disposal_account_and_cost_center, + get_gl_entries_on_asset_disposal, + get_gl_entries_on_asset_regain, + post_depreciation_entries, +) +from erpnext.controllers.selling_controller import SellingController +from erpnext.healthcare.utils import manage_invoice_submit_cancel +from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data +from erpnext.setup.doctype.company.company import update_company_current_month_sales +from erpnext.stock.doctype.batch.batch import set_batch_nos +from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so +from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos + form_grid_templates = { "items": "templates/form_grid/item_grid.html" } @@ -483,7 +500,7 @@ class SalesInvoice(SellingController): if not self.account_for_change_amount: self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account') - from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile + from erpnext.stock.get_item_details import get_pos_profile, get_pos_profile_item_details if not self.pos_profile: pos_profile = get_pos_profile(self.company) or {} if not pos_profile: @@ -933,7 +950,7 @@ class SalesInvoice(SellingController): if asset.calculate_depreciation: self.reset_depreciation_schedule(asset) - + else: fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount, item.finance_book) @@ -947,7 +964,7 @@ class SalesInvoice(SellingController): gl_entries.append(self.get_gl_dict(gle, item=item)) self.set_asset_status(asset) - + else: # Do not book income for transfer within same company if not self.is_internal_transfer(): @@ -980,7 +997,7 @@ class SalesInvoice(SellingController): asset = frappe.get_doc("Asset", item.asset) else: frappe.throw(_( - "Row #{0}: You must select an Asset for Item {1}.").format(item.idx, item.item_name), + "Row #{0}: You must select an Asset for Item {1}.").format(item.idx, item.item_name), title=_("Missing Asset") ) @@ -997,7 +1014,7 @@ class SalesInvoice(SellingController): asset.flags.ignore_validate_update_after_submit = True asset.prepare_depreciation_data(self.posting_date) asset.save() - + post_depreciation_entries(self.posting_date) def reset_depreciation_schedule(self, asset): @@ -1037,7 +1054,7 @@ class SalesInvoice(SellingController): finance_book = schedule.finance_book else: row += 1 - + if schedule.schedule_date == posting_date_of_original_invoice: if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice): reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) @@ -1047,13 +1064,13 @@ class SalesInvoice(SellingController): def get_posting_date_of_sales_invoice(self): return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date') - # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone + # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone def sale_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_invoice): for finance_book in asset.get('finance_books'): if schedule.finance_book == finance_book.finance_book: orginal_schedule_date = add_months(finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation)) - + if orginal_schedule_date == posting_date_of_original_invoice: return True return False @@ -1372,8 +1389,10 @@ class SalesInvoice(SellingController): # redeem the loyalty points. def apply_loyalty_points(self): - from erpnext.accounts.doctype.loyalty_point_entry.loyalty_point_entry \ - import get_loyalty_point_entries, get_redemption_details + from erpnext.accounts.doctype.loyalty_point_entry.loyalty_point_entry import ( + get_loyalty_point_entries, + get_redemption_details, + ) loyalty_point_entries = get_loyalty_point_entries(self.customer, self.loyalty_program, self.company, self.posting_date) redemption_details = get_redemption_details(self.customer, self.loyalty_program, self.company) @@ -2006,7 +2025,11 @@ def get_mode_of_payment_info(mode_of_payment, company): @frappe.whitelist() def create_dunning(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc - from erpnext.accounts.doctype.dunning.dunning import get_dunning_letter_text, calculate_interest_and_amount + + from erpnext.accounts.doctype.dunning.dunning import ( + calculate_interest_and_amount, + get_dunning_letter_text, + ) def set_missing_values(source, target): target.sales_invoice = source_name target.outstanding_amount = source.outstanding_amount diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py index 3238ead4316..64b35b2987e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'sales_invoice', diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 8fa36509d21..f339b7f064b 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2,30 +2,37 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import copy +import unittest -import unittest, copy, time -from frappe.utils import nowdate, flt, getdate, cint, add_days, add_months +import frappe from frappe.model.dynamic_links import get_dynamic_link_map -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice -from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile -from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data -from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries -from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency -from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError from frappe.model.naming import make_autoname -from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account -from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data -from erpnext.stock.doctype.item.test_item import create_item +from frappe.utils import add_days, flt, getdate, nowdate from six import iteritems + +from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account +from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + unlink_payment_on_cancel_of_invoice, +) from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction -from erpnext.regional.india.utils import get_ewb_data -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt -from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice -from erpnext.stock.utils import get_incoming_rate from erpnext.accounts.utils import PaymentEntryUnlinkError +from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries +from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data +from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data +from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency +from erpnext.regional.india.utils import get_ewb_data +from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice +from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError +from erpnext.stock.doctype.stock_entry.test_stock_entry import ( + get_qty_after_transaction, + make_stock_entry, +) +from erpnext.stock.utils import get_incoming_rate + class TestSalesInvoice(unittest.TestCase): def make(self): @@ -676,8 +683,9 @@ class TestSalesInvoice(unittest.TestCase): def test_payment(self): w = self.make() - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.get_doc(frappe.copy_doc(jv_test_records[0])) jv.get("accounts")[0].reference_type = w.doctype @@ -943,16 +951,18 @@ class TestSalesInvoice(unittest.TestCase): def _insert_purchase_receipt(self): - from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import test_records \ - as pr_test_records + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import ( + test_records as pr_test_records, + ) pr = frappe.copy_doc(pr_test_records[0]) pr.naming_series = "_T-Purchase Receipt-" pr.insert() pr.submit() def _insert_delivery_note(self): - from erpnext.stock.doctype.delivery_note.test_delivery_note import test_records \ - as dn_test_records + from erpnext.stock.doctype.delivery_note.test_delivery_note import ( + test_records as dn_test_records, + ) dn = frappe.copy_doc(dn_test_records[0]) dn.naming_series = "_T-Delivery Note-" dn.insert() @@ -960,8 +970,9 @@ class TestSalesInvoice(unittest.TestCase): return dn def test_sales_invoice_with_advance(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.copy_doc(jv_test_records[0]) jv.insert() @@ -993,8 +1004,8 @@ class TestSalesInvoice(unittest.TestCase): si.cancel() def test_serialized(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() serial_nos = get_serial_nos(se.get("items")[0].serial_no) @@ -1047,9 +1058,9 @@ class TestSalesInvoice(unittest.TestCase): check if the sales invoice item serial numbers and the delivery note items serial numbers are same """ - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() serial_nos = get_serial_nos(se.get("items")[0].serial_no) @@ -1118,9 +1129,9 @@ class TestSalesInvoice(unittest.TestCase): 'qty': 1 }) pi.set_missing_values() - + asset = create_asset(item_code="Macbook Pro") - + si = create_sales_invoice(item_code="Macbook Pro", asset=asset.name, qty=1, rate=90000) return_si = create_sales_invoice(is_return=1, return_against=si.name, item_code="Macbook Pro", asset=asset.name, qty=-1, rate=90000) @@ -1128,7 +1139,7 @@ class TestSalesInvoice(unittest.TestCase): # Asset value is 100,000 but it was sold for 90,000, so there should be a loss of 10,000 loss_for_si = frappe.get_all( - "GL Entry", + "GL Entry", filters = { "voucher_no": si.name, "account": disposal_account @@ -1137,7 +1148,7 @@ class TestSalesInvoice(unittest.TestCase): )[0] loss_for_return_si = frappe.get_all( - "GL Entry", + "GL Entry", filters = { "voucher_no": return_si.name, "account": disposal_account @@ -1298,8 +1309,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(si.get("items")[0].rate, flt((price_list_rate*25)/100 + price_list_rate)) def test_outstanding_amount_after_advance_jv_cancelation(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records + from erpnext.accounts.doctype.journal_entry.test_journal_entry import ( + test_records as jv_test_records, + ) jv = frappe.copy_doc(jv_test_records[0]) jv.accounts[0].is_advance = 'Yes' @@ -1585,8 +1597,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(expected_values[gle.account][2], gle.credit) def test_sales_invoice_with_shipping_rule(self): - from erpnext.accounts.doctype.shipping_rule.test_shipping_rule \ - import create_shipping_rule + from erpnext.accounts.doctype.shipping_rule.test_shipping_rule import create_shipping_rule shipping_rule = create_shipping_rule(shipping_rule_type = "Selling", shipping_rule_name = "Shipping Rule - Sales Invoice Test") @@ -2102,7 +2113,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") def test_sales_invoice_with_discount_accounting_enabled(self): - from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import enable_discount_accounting + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + enable_discount_accounting, + ) enable_discount_accounting() @@ -2120,7 +2133,9 @@ class TestSalesInvoice(unittest.TestCase): enable_discount_accounting(enable=0) def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled(self): - from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import enable_discount_accounting + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + enable_discount_accounting, + ) enable_discount_accounting() additional_discount_account = create_account(account_name="Discount Account", @@ -2174,7 +2189,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(schedule.journal_entry) def test_sales_invoice_against_supplier(self): - from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import make_customer + from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import ( + make_customer, + ) from erpnext.buying.doctype.supplier.test_supplier import create_supplier # create a customer diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py index 28aeef4d5e1..ae69598a66a 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class SalesInvoiceAdvance(Document): pass diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py index a73b03acc84..063c591f768 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class SalesInvoiceItem(Document): pass diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py index cc0b7a620db..a980ece580b 100644 --- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py +++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SalesInvoicePayment(Document): pass diff --git a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py index afc05ab7ede..e8d4b114fef 100644 --- a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py +++ b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SalesInvoiceTimesheet(Document): pass diff --git a/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py b/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py index 9796c7b0ccf..97489d155fc 100644 --- a/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py +++ b/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class SalesPartnerItem(Document): pass diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py index b1de9d85fdb..39872f33770 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class SalesTaxesandCharges(Document): pass diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py index 8f9eb6577b8..0a0bb3e00b9 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py @@ -2,11 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt from frappe.model.document import Document -from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax, validate_cost_center, validate_account_head +from frappe.utils import flt + +from erpnext.controllers.accounts_controller import ( + validate_account_head, + validate_cost_center, + validate_inclusive_tax, + validate_taxes_and_charges, +) + class SalesTaxesandChargesTemplate(Document): def validate(self): diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.py index 1c0c0c77e75..1cad4129f83 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_records = frappe.get_test_records('Sales Taxes and Charges Template') class TestSalesTaxesandChargesTemplate(unittest.TestCase): diff --git a/erpnext/accounts/doctype/share_balance/share_balance.py b/erpnext/accounts/doctype/share_balance/share_balance.py index bd165cd38a4..0353e998237 100644 --- a/erpnext/accounts/doctype/share_balance/share_balance.py +++ b/erpnext/accounts/doctype/share_balance/share_balance.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ShareBalance(Document): pass diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.py b/erpnext/accounts/doctype/share_transfer/share_transfer.py index 3d4543fb051..5117ef8b5b5 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.py @@ -3,13 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document -from frappe.model.naming import make_autoname from frappe.exceptions import ValidationError +from frappe.model.document import Document +from frappe.model.naming import make_autoname from frappe.utils import nowdate + class ShareDontExists(ValidationError): pass class ShareTransfer(Document): diff --git a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py index 2ff9b02129f..b40e5fbbf8e 100644 --- a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py @@ -3,8 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.accounts.doctype.share_transfer.share_transfer import ShareDontExists test_dependencies = ["Share Type", "Shareholder"] diff --git a/erpnext/accounts/doctype/share_type/share_type.py b/erpnext/accounts/doctype/share_type/share_type.py index ab4b8bc1ef2..5b133aa34ab 100644 --- a/erpnext/accounts/doctype/share_type/share_type.py +++ b/erpnext/accounts/doctype/share_type/share_type.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ShareType(Document): pass diff --git a/erpnext/accounts/doctype/share_type/test_share_type.py b/erpnext/accounts/doctype/share_type/test_share_type.py index 1c1f0516588..a6f8d611c1b 100644 --- a/erpnext/accounts/doctype/share_type/test_share_type.py +++ b/erpnext/accounts/doctype/share_type/test_share_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestShareType(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/shareholder/shareholder.py b/erpnext/accounts/doctype/shareholder/shareholder.py index c507fcfaa9d..12c50c8283b 100644 --- a/erpnext/accounts/doctype/shareholder/shareholder.py +++ b/erpnext/accounts/doctype/shareholder/shareholder.py @@ -3,9 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) from frappe.model.document import Document -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address + class Shareholder(Document): def onload(self): diff --git a/erpnext/accounts/doctype/shareholder/shareholder_dashboard.py b/erpnext/accounts/doctype/shareholder/shareholder_dashboard.py index 3b77fd51b5e..0084f2567ab 100644 --- a/erpnext/accounts/doctype/shareholder/shareholder_dashboard.py +++ b/erpnext/accounts/doctype/shareholder/shareholder_dashboard.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from frappe import _ - def get_data(): return { diff --git a/erpnext/accounts/doctype/shareholder/test_shareholder.py b/erpnext/accounts/doctype/shareholder/test_shareholder.py index 9ce00932fad..6790fdd2ff7 100644 --- a/erpnext/accounts/doctype/shareholder/test_shareholder.py +++ b/erpnext/accounts/doctype/shareholder/test_shareholder.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestShareholder(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py index d32a348741e..28521014720 100644 --- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py @@ -4,10 +4,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _, msgprint, throw -from frappe.utils import flt, fmt_money from frappe.model.document import Document +from frappe.utils import flt, fmt_money + +import erpnext + class OverlappingConditionError(frappe.ValidationError): pass class FromGreaterThanToError(frappe.ValidationError): pass diff --git a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py index abc6ab82d3d..bdd9be3beda 100644 --- a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py @@ -2,9 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.accounts.doctype.shipping_rule.shipping_rule import FromGreaterThanToError, ManyBlankToValuesError, OverlappingConditionError + +import frappe + +from erpnext.accounts.doctype.shipping_rule.shipping_rule import ( + FromGreaterThanToError, + ManyBlankToValuesError, + OverlappingConditionError, +) test_records = frappe.get_test_records('Shipping Rule') diff --git a/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py b/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py index db6ef117c22..66cd269e51b 100644 --- a/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py +++ b/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ShippingRuleCondition(Document): pass diff --git a/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py b/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py index b9646cfc293..9576acd0aba 100644 --- a/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py +++ b/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ShippingRuleCountry(Document): pass diff --git a/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py b/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py index 4bd8c65a046..d9a3bcc0df4 100644 --- a/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py +++ b/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class SouthAfricaVATAccount(Document): pass diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 7c4ff73d908..68f4e984165 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -6,13 +6,27 @@ from __future__ import unicode_literals import frappe -import erpnext from frappe import _ from frappe.model.document import Document -from frappe.utils.data import nowdate, getdate, cstr, 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 +from frappe.utils.data import ( + add_days, + add_to_date, + cint, + cstr, + date_diff, + flt, + get_last_day, + getdate, + nowdate, +) + +import erpnext from erpnext import get_default_company +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) +from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate + class Subscription(Document): def before_insert(self): diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 4f2cf487a4f..e2cf4d5a442 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -6,9 +6,18 @@ from __future__ import unicode_literals import unittest import frappe +from frappe.utils.data import ( + add_days, + add_months, + add_to_date, + date_diff, + flt, + get_date_str, + nowdate, +) + from erpnext.accounts.doctype.subscription.subscription import get_prorata_factor -from frappe.utils.data import (nowdate, add_days, add_to_date, add_months, date_diff, flt, get_date_str, - get_first_day, get_last_day) + def create_plan(): if not frappe.db.exists('Subscription Plan', '_Test Plan Name'): diff --git a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py index 6f459b4790d..687c94cce2c 100644 --- a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py +++ b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SubscriptionInvoice(Document): pass diff --git a/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.py b/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.py index e60a4eeca99..2cc3038d913 100644 --- a/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.py +++ b/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSubscriptionInvoice(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index a341c2af6ac..c7bb58cb26d 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import get_first_day, get_last_day, date_diff, flt, getdate from frappe.model.document import Document +from frappe.utils import date_diff, flt, get_first_day, get_last_day, getdate + from erpnext.utilities.product import get_price + class SubscriptionPlan(Document): def validate(self): self.validate_interval_count() diff --git a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py index 73afbf620ec..ba997632479 100644 --- a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSubscriptionPlan(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py index 1d9606ff78c..a63a27700cc 100644 --- a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py +++ b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SubscriptionPlanDetail(Document): pass diff --git a/erpnext/accounts/doctype/subscription_settings/subscription_settings.py b/erpnext/accounts/doctype/subscription_settings/subscription_settings.py index cc378e4d9fd..54735834baa 100644 --- a/erpnext/accounts/doctype/subscription_settings/subscription_settings.py +++ b/erpnext/accounts/doctype/subscription_settings/subscription_settings.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SubscriptionSettings(Document): pass diff --git a/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.py b/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.py index 82c7e1d269e..5875ee069ec 100644 --- a/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.py +++ b/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSubscriptionSettings(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py b/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py index de0444ee193..61c16fe0ff1 100644 --- a/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py +++ b/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class SupplierGroupItem(Document): pass diff --git a/erpnext/accounts/doctype/supplier_item/supplier_item.py b/erpnext/accounts/doctype/supplier_item/supplier_item.py index ad66e230c80..2105b1d3327 100644 --- a/erpnext/accounts/doctype/supplier_item/supplier_item.py +++ b/erpnext/accounts/doctype/supplier_item/supplier_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class SupplierItem(Document): pass diff --git a/erpnext/accounts/doctype/tax_category/tax_category.py b/erpnext/accounts/doctype/tax_category/tax_category.py index 2870e3200f8..df31a5e45f9 100644 --- a/erpnext/accounts/doctype/tax_category/tax_category.py +++ b/erpnext/accounts/doctype/tax_category/tax_category.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TaxCategory(Document): pass diff --git a/erpnext/accounts/doctype/tax_category/test_tax_category.py b/erpnext/accounts/doctype/tax_category/test_tax_category.py index 548d00852aa..90931058f07 100644 --- a/erpnext/accounts/doctype/tax_category/test_tax_category.py +++ b/erpnext/accounts/doctype/tax_category/test_tax_category.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestTaxCategory(unittest.TestCase): pass diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 58142318177..9a63dfedbee 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -3,19 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals -from past.builtins import cmp -import frappe -from frappe import _ -from frappe.model.document import Document -from frappe.utils import cstr, cint -from frappe.contacts.doctype.address.address import get_default_address -from frappe.utils.nestedset import get_root_of -from erpnext.setup.doctype.customer_group.customer_group import get_parent_customer_groups import functools +import frappe +from frappe import _ +from frappe.contacts.doctype.address.address import get_default_address +from frappe.model.document import Document +from frappe.utils import cint, cstr +from frappe.utils.nestedset import get_root_of +from past.builtins import cmp from six import iteritems +from erpnext.setup.doctype.customer_group.customer_group import get_parent_customer_groups + + class IncorrectCustomerGroup(frappe.ValidationError): pass class IncorrectSupplierType(frappe.ValidationError): pass class ConflictingTaxRule(frappe.ValidationError): pass @@ -100,7 +102,7 @@ class TaxRule(Document): def validate_use_for_shopping_cart(self): '''If shopping cart is enabled and no tax rule exists for shopping cart, enable this one''' if (not self.use_for_shopping_cart - and cint(frappe.db.get_single_value('Shopping Cart Settings', 'enabled')) + and cint(frappe.db.get_single_value('E Commerce Settings', 'enabled')) and not frappe.db.get_value('Tax Rule', {'use_for_shopping_cart': 1, 'name': ['!=', self.name]})): self.use_for_shopping_cart = 1 diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index cf7226822ed..f937274edf5 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -3,16 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template -from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity + +import frappe + +from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule, get_tax_template from erpnext.crm.doctype.opportunity.opportunity import make_quotation +from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity test_records = frappe.get_test_records('Tax Rule') from six import iteritems + class TestTaxRule(unittest.TestCase): @classmethod def setUpClass(cls): diff --git a/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py b/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py index 76e3fa32b0c..fd194829e56 100644 --- a/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py +++ b/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TaxWithholdingAccount(Document): pass diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 0cb872c4b81..b4bdd73c492 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt, getdate, cint +from frappe.utils import cint, getdate + from erpnext.accounts.utils import get_fiscal_year + class TaxWithholdingCategory(Document): pass @@ -240,7 +243,7 @@ def get_deducted_tax(taxable_vouchers, fiscal_year, tax_details): def get_tds_amount(ldc, parties, inv, tax_details, fiscal_year_details, tax_deducted, vouchers): tds_amount = 0 invoice_filters = { - 'name': ('in', vouchers), + 'name': ('in', vouchers), 'docstatus': 1, 'apply_tds': 1 } diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category_dashboard.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category_dashboard.py index d51ba65b13b..152ee460814 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category_dashboard.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category_dashboard.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from frappe import _ - def get_data(): return { diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index 0f921db678d..c4a5ba52fea 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -3,11 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import today + from erpnext.accounts.utils import get_fiscal_year -from erpnext.buying.doctype.supplier.test_supplier import create_supplier test_dependencies = ["Supplier Group", "Customer Group"] diff --git a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py index 6e32abec390..6556277509a 100644 --- a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py +++ b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TaxWithholdingRate(Document): pass diff --git a/erpnext/accounts/doctype/territory_item/territory_item.py b/erpnext/accounts/doctype/territory_item/territory_item.py index d46edc9dca8..bcc02be2dd3 100644 --- a/erpnext/accounts/doctype/territory_item/territory_item.py +++ b/erpnext/accounts/doctype/territory_item/territory_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class TerritoryItem(Document): pass diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 31261384080..4bf2b828edd 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -2,12 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import flt, cstr, cint, comma_and, today, getdate, formatdate, now + +import frappe from frappe import _ from frappe.model.meta import get_field_precision +from frappe.utils import cint, cstr, flt, formatdate, getdate, now + +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions + class ClosedAccountingPeriod(frappe.ValidationError): pass diff --git a/erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.py b/erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.py index 1bc4d1874c8..f57de916dd1 100644 --- a/erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.py +++ b/erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_context(context): # do your magic here pass diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index de7dde9dd1f..7ea6ccee5b4 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -3,20 +3,37 @@ from __future__ import unicode_literals -import frappe, erpnext +import frappe from frappe import _, msgprint, scrub +from frappe.contacts.doctype.address.address import ( + get_address_display, + get_company_address, + get_default_address, +) +from frappe.contacts.doctype.contact.contact import get_contact_details from frappe.core.doctype.user_permission.user_permission import get_permitted_documents from frappe.model.utils import get_fetch_values -from frappe.utils import (add_days, getdate, formatdate, date_diff, - add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day, cint) -from frappe.contacts.doctype.address.address import (get_address_display, - get_default_address, get_company_address) -from frappe.contacts.doctype.contact.contact import get_contact_details -from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency -from erpnext.accounts.utils import get_fiscal_year -from erpnext import get_company_currency +from frappe.utils import ( + add_days, + add_months, + add_years, + cint, + cstr, + date_diff, + flt, + formatdate, + get_last_day, + get_timestamp, + getdate, + nowdate, +) +from six import iteritems + +import erpnext +from erpnext import get_company_currency +from erpnext.accounts.utils import get_fiscal_year +from erpnext.exceptions import InvalidAccountCurrency, PartyDisabled, PartyFrozen -from six import iteritems, string_types class DuplicatePartyAccountError(frappe.ValidationError): pass @@ -386,7 +403,7 @@ def get_address_tax_category(tax_category=None, billing_address=None, shipping_a @frappe.whitelist() def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_group=None, tax_category=None, billing_address=None, shipping_address=None, use_for_shopping_cart=None): - from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details + from erpnext.accounts.doctype.tax_rule.tax_rule import get_party_details, get_tax_template args = { party_type.lower(): party, "company": company @@ -648,7 +665,7 @@ def get_default_contact(doctype, name): if out: try: return out[0][0] - except: + except Exception: return None else: return None diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py index be64c327fdf..9ae61ddcfd2 100644 --- a/erpnext/accounts/report/account_balance/account_balance.py +++ b/erpnext/accounts/report/account_balance/account_balance.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + from erpnext.accounts.utils import get_balance_on + def execute(filters=None): filters = frappe._dict(filters or {}) columns = get_columns(filters) diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py index f5c9449e85d..94c73f5264b 100644 --- a/erpnext/accounts/report/account_balance/test_account_balance.py +++ b/erpnext/accounts/report/account_balance/test_account_balance.py @@ -1,10 +1,13 @@ from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import getdate -from erpnext.accounts.report.account_balance.account_balance import execute + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.report.account_balance.account_balance import execute + class TestAccountBalance(unittest.TestCase): def test_account_balance(self): diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.py b/erpnext/accounts/report/accounts_payable/accounts_payable.py index 246ead6016e..0de573e4541 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.py +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.py @@ -2,9 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport + def execute(filters=None): args = { "party_type": "Supplier", diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.py b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.py index c08582b564c..6034ec0d83b 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.py +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary \ - import AccountsReceivableSummary + +from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import ( + AccountsReceivableSummary, +) + def execute(filters=None): args = { diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index cedfc0f58b8..e91fdf27cdd 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -2,12 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe import _, scrub -from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr, now, time_diff_in_seconds + from collections import OrderedDict + +import frappe +from frappe import _, scrub +from frappe.utils import cint, cstr, flt, getdate, nowdate + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) from erpnext.accounts.utils import get_currency_precision -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children # This report gives a summary of all Outstanding Invoices considering the following diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index cca67608238..1d24561bb3f 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -1,11 +1,14 @@ from __future__ import unicode_literals -import frappe -import frappe.defaults + import unittest -from frappe.utils import today, getdate, add_days -from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + +import frappe +from frappe.utils import add_days, getdate, today + from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute + class TestAccountsReceivable(unittest.TestCase): def test_accounts_receivable(self): diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 4bfb022c4ee..106f224a740 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _, scrub -from frappe.utils import flt, cint +from frappe.utils import cint +from six import iteritems + from erpnext.accounts.party import get_partywise_advanced_payment_amount from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport -from six import iteritems + def execute(filters=None): args = { diff --git a/erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py b/erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py index 2162a02eff9..0fd4ca0f24a 100644 --- a/erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py +++ b/erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import flt + +import frappe from frappe import _ +from frappe.utils import flt + def execute(filters=None): columns, data = get_columns(), get_data(filters) diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index 5001ad9f12f..d34bc854bba 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -2,9 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import formatdate, flt, add_days +from frappe.utils import add_days, flt, formatdate def execute(filters=None): diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 7838385dc56..78ee7cab9af 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -2,11 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, cint -from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data, - get_filtered_list_for_consolidated_report) +from frappe.utils import cint, flt + +from erpnext.accounts.report.financial_statements import ( + get_columns, + get_data, + get_filtered_list_for_consolidated_report, + get_period_list, +) + def execute(filters=None): period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, diff --git a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py index 95f724cc580..1a1fa964fe0 100644 --- a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py +++ b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import nowdate, getdate +from frappe.utils import getdate, nowdate + def execute(filters=None): if not filters: filters = {} 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 63317c52d80..b9843068a18 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt, getdate, nowdate from frappe import _ +from frappe.utils import flt, getdate, nowdate + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py index 2dcea22f7e6..6c4cd671b24 100644 --- a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py +++ b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): data = get_data(filters) or [] columns = get_columns() diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py index 443126e4655..c204250377f 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py @@ -2,12 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import datetime -from six import iteritems import frappe from frappe import _ from frappe.utils import flt, formatdate +from six import iteritems from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 3577457c980..d5271885b7e 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -2,14 +2,23 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cint, cstr -from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data, get_filtered_list_for_consolidated_report) -from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss -from erpnext.accounts.utils import get_fiscal_year from six import iteritems +from erpnext.accounts.report.financial_statements import ( + get_columns, + get_data, + get_filtered_list_for_consolidated_report, + get_period_list, +) +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import ( + get_net_profit_loss, +) +from erpnext.accounts.utils import get_fiscal_year + def execute(filters=None): if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')): diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py index c11c15390b3..bbc020e591f 100644 --- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py +++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py @@ -2,11 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import add_to_date -from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data) -from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss + +from erpnext.accounts.report.financial_statements import get_columns, get_data, get_period_list +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import ( + get_net_profit_loss, +) def get_mapper_for(mappers, position): diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index fc4212733a3..e419727c2d1 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -2,17 +2,37 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt, cint, getdate -from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency +from frappe.utils import cint, flt, getdate + +from erpnext.accounts.report.balance_sheet.balance_sheet import ( + check_opening_balance, + get_chart_data, + get_provisional_profit_loss, +) +from erpnext.accounts.report.balance_sheet.balance_sheet import ( + get_report_summary as get_bs_summary, +) +from erpnext.accounts.report.cash_flow.cash_flow import ( + add_total_row_account, + get_account_type_based_gl_data, + get_cash_flow_accounts, +) +from erpnext.accounts.report.cash_flow.cash_flow import get_report_summary as get_cash_flow_summary from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts -from erpnext.accounts.report.balance_sheet.balance_sheet import (get_provisional_profit_loss, - check_opening_balance, get_chart_data, get_report_summary as get_bs_summary) -from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import (get_net_profit_loss, - get_chart_data as get_pl_chart_data, get_report_summary as get_pl_summary) -from erpnext.accounts.report.cash_flow.cash_flow import (get_cash_flow_accounts, get_account_type_based_gl_data, - add_total_row_account, get_report_summary as get_cash_flow_summary) +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import ( + get_chart_data as get_pl_chart_data, +) +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import ( + get_net_profit_loss, +) +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import ( + get_report_summary as get_pl_summary, +) +from erpnext.accounts.report.utils import convert_to_presentation_currency + def execute(filters=None): columns, data, message, chart = [], [], [], [] diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index c79d7401e6a..603fbac5aa9 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -2,12 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _, scrub from frappe.utils import getdate, nowdate from six import iteritems, itervalues + class PartyLedgerSummaryReport(object): def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) diff --git a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py index 9953d8fcaf5..f096094296c 100644 --- a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py +++ b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe import _ + from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data + def execute(filters=None): columns = get_column() args = get_args() diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py index de7ed4926e1..4212137d7a6 100644 --- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py @@ -2,14 +2,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe import _ -from frappe.utils import (flt, cstr) -from erpnext.accounts.report.financial_statements import filter_accounts, filter_out_zero_value_rows +import frappe +from frappe import _ +from frappe.utils import cstr, flt +from six import itervalues + +import erpnext +from erpnext.accounts.report.financial_statements import ( + filter_accounts, + filter_out_zero_value_rows, +) from erpnext.accounts.report.trial_balance.trial_balance import validate_filters -from six import itervalues def execute(filters=None): validate_filters(filters) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 39ff8045181..2cb8a6802a7 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -5,19 +5,23 @@ from __future__ import unicode_literals -import re -from past.builtins import cmp import functools import math +import re -import frappe, erpnext -from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency -from erpnext.accounts.utils import get_fiscal_year +import frappe from frappe import _ -from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr, cint) - +from frappe.utils import add_days, add_months, cint, cstr, flt, formatdate, get_first_day, getdate +from past.builtins import cmp from six import itervalues -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) +from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency +from erpnext.accounts.utils import get_fiscal_year + def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_end_date, filter_based_on, periodicity, accumulated_values=False, company=None, reset_period_on_fy_change=True, ignore_fiscal_year=False): @@ -339,7 +343,7 @@ def sort_accounts(accounts, is_root=False, key="name"): """Sort root types as Asset, Liability, Equity, Income, Expense""" def compare_accounts(a, b): - if re.split('\W+', a[key])[0].isdigit(): + if re.split(r'\W+', a[key])[0].isdigit(): # if chart of accounts is numbered, then sort by number return cmp(a[key], b[key]) elif is_root: diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 095f5eda66a..b2968761c63 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -110,9 +110,26 @@ frappe.query_reports["General Ledger"] = { "fieldname":"group_by", "label": __("Group by"), "fieldtype": "Select", - "options": ["", __("Group by Voucher"), __("Group by Voucher (Consolidated)"), - __("Group by Account"), __("Group by Party")], - "default": __("Group by Voucher (Consolidated)") + "options": [ + "", + { + label: __("Group by Voucher"), + value: "Group by Voucher", + }, + { + label: __("Group by Voucher (Consolidated)"), + value: "Group by Voucher (Consolidated)", + }, + { + label: __("Group by Account"), + value: "Group by Account", + }, + { + label: __("Group by Party"), + value: "Group by Party", + }, + ], + "default": "Group by Voucher (Consolidated)" }, { "fieldname":"tax_id", diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 3723c8e0d23..5bd6e583dbb 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -2,17 +2,24 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from erpnext import get_company_currency, get_default_company -from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency -from frappe.utils import getdate, cstr, flt, fmt_money -from frappe import _, _dict -from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.report.financial_statements import get_cost_centers_with_children -from six import iteritems -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children + from collections import OrderedDict +import frappe +from frappe import _, _dict +from frappe.utils import cstr, flt, getdate +from six import iteritems + +from erpnext import get_company_currency, get_default_company +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) +from erpnext.accounts.report.financial_statements import get_cost_centers_with_children +from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency +from erpnext.accounts.utils import get_account_currency + + def execute(filters=None): if not filters: return [], [] @@ -55,14 +62,14 @@ def validate_filters(filters, account_details): if not account_details.get(account): frappe.throw(_("Account {0} does not exists").format(account)) - if (filters.get("account") and filters.get("group_by") == _('Group by Account')): + if (filters.get("account") and filters.get("group_by") == 'Group by Account'): filters.account = frappe.parse_json(filters.get('account')) for account in filters.account: if account_details[account].is_group == 0: frappe.throw(_("Can not filter based on Child Account, if grouped by Account")) if (filters.get("voucher_no") - and filters.get("group_by") in [_('Group by Voucher')]): + and filters.get("group_by") in ['Group by Voucher']): frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) if filters.from_date > filters.to_date: @@ -146,7 +153,7 @@ def get_gl_entries(filters, accounting_dimensions): if filters.get("include_dimensions"): order_by_statement = "order by posting_date, creation" - if filters.get("group_by") == _("Group by Voucher"): + if filters.get("group_by") == "Group by Voucher": order_by_statement = "order by posting_date, voucher_type, voucher_no" if filters.get("include_default_book_entries"): @@ -305,13 +312,13 @@ def get_data_with_opening_closing(filters, account_details, accounting_dimension # Opening for filtered account data.append(totals.opening) - if filters.get("group_by") != _('Group by Voucher (Consolidated)'): + if filters.get("group_by") != 'Group by Voucher (Consolidated)': for acc, acc_dict in iteritems(gle_map): # acc if acc_dict.entries: # opening data.append({}) - if filters.get("group_by") != _("Group by Voucher"): + if filters.get("group_by") != "Group by Voucher": data.append(acc_dict.totals.opening) data += acc_dict.entries @@ -320,7 +327,7 @@ def get_data_with_opening_closing(filters, account_details, accounting_dimension data.append(acc_dict.totals.total) # closing - if filters.get("group_by") != _("Group by Voucher"): + if filters.get("group_by") != "Group by Voucher": data.append(acc_dict.totals.closing) data.append({}) else: @@ -350,9 +357,9 @@ def get_totals_dict(): ) def group_by_field(group_by): - if group_by == _('Group by Party'): + if group_by == 'Group by Party': return 'party' - elif group_by in [_('Group by Voucher (Consolidated)'), _('Group by Account')]: + elif group_by in ['Group by Voucher (Consolidated)', 'Group by Account']: return 'account' else: return 'voucher_no' @@ -416,9 +423,9 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): elif gle.posting_date <= to_date: update_value_in_dict(gle_map[gle.get(group_by)].totals, 'total', gle) update_value_in_dict(totals, 'total', gle) - if filters.get("group_by") != _('Group by Voucher (Consolidated)'): + if filters.get("group_by") != 'Group by Voucher (Consolidated)': gle_map[gle.get(group_by)].entries.append(gle) - elif filters.get("group_by") == _('Group by Voucher (Consolidated)'): + elif filters.get("group_by") == 'Group by Voucher (Consolidated)': keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")] for dim in accounting_dimensions: keylist.append(gle.get(dim)) diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py index 8e33af7ee8e..49522d9c873 100644 --- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py @@ -2,11 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import copy + import frappe from frappe import _ from frappe.utils import flt -from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data) -import copy + +from erpnext.accounts.report.financial_statements import get_columns, get_data, get_period_list + def execute(filters=None): period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, filters.period_start_date, diff --git a/erpnext/accounts/report/gross_profit/gross_profit.js b/erpnext/accounts/report/gross_profit/gross_profit.js index ba17a94e8d3..856b97d1645 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.js +++ b/erpnext/accounts/report/gross_profit/gross_profit.js @@ -36,5 +36,20 @@ frappe.query_reports["Gross Profit"] = { "options": "Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject", "default": "Invoice" }, - ] + ], + "tree": true, + "name_field": "parent", + "parent_field": "parent_invoice", + "initial_depth": 3, + "formatter": function(value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (data && data.indent == 0.0) { + value = $(`${value}`); + var $value = $(value).css("font-weight", "bold"); + value = $value.wrap("

").parent().html(); + } + + return value; + }, } diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index c949d9b74e5..3d5e7c50e77 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _, scrub -from erpnext.stock.utils import get_incoming_rate +from frappe.utils import cint, flt + from erpnext.controllers.queries import get_match_cond -from frappe.utils import flt, cint +from erpnext.stock.utils import get_incoming_rate def execute(filters=None): @@ -41,6 +43,34 @@ def execute(filters=None): columns = get_columns(group_wise_columns, filters) + if filters.group_by == 'Invoice': + get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_wise_columns, data) + + else: + get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data) + + return columns, data + +def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_wise_columns, data): + column_names = get_column_names() + + # to display item as Item Code: Item Name + columns[0] = 'Sales Invoice:Link/Item:300' + # removing Item Code and Item Name columns + del columns[4:6] + + for src in gross_profit_data.si_list: + row = frappe._dict() + row.indent = src.indent + row.parent_invoice = src.parent_invoice + row.currency = filters.currency + + for col in group_wise_columns.get(scrub(filters.group_by)): + row[column_names[col]] = src.get(col) + + data.append(row) + +def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data): for idx, src in enumerate(gross_profit_data.grouped_data): row = [] for col in group_wise_columns.get(scrub(filters.group_by)): @@ -51,8 +81,6 @@ def execute(filters=None): row[0] = frappe.bold("Total") data.append(row) - return columns, data - def get_columns(group_wise_columns, filters): columns = [] column_map = frappe._dict({ @@ -93,12 +121,38 @@ def get_columns(group_wise_columns, filters): return columns +def get_column_names(): + return frappe._dict({ + 'parent': 'sales_invoice', + 'customer': 'customer', + 'customer_group': 'customer_group', + 'posting_date': 'posting_date', + 'item_code': 'item_code', + 'item_name': 'item_name', + 'item_group': 'item_group', + 'brand': 'brand', + 'description': 'description', + 'warehouse': 'warehouse', + 'qty': 'qty', + 'base_rate': 'avg._selling_rate', + 'buying_rate': 'valuation_rate', + 'base_amount': 'selling_amount', + 'buying_amount': 'buying_amount', + 'gross_profit': 'gross_profit', + 'gross_profit_percent': 'gross_profit_%', + 'project': 'project' + }) + class GrossProfitGenerator(object): def __init__(self, filters=None): self.data = [] self.average_buying_rate = {} self.filters = frappe._dict(filters) self.load_invoice_items() + + if filters.group_by == 'Invoice': + self.group_items_by_invoice() + self.load_stock_ledger_entries() self.load_product_bundle() self.load_non_stock_items() @@ -112,7 +166,12 @@ class GrossProfitGenerator(object): self.currency_precision = cint(frappe.db.get_default("currency_precision")) or 3 self.float_precision = cint(frappe.db.get_default("float_precision")) or 2 - for row in self.si_list: + grouped_by_invoice = True if self.filters.get("group_by") == "Invoice" else False + + if grouped_by_invoice: + buying_amount = 0 + + for row in reversed(self.si_list): if self.skip_row(row, self.product_bundles): continue @@ -134,12 +193,20 @@ class GrossProfitGenerator(object): row.buying_amount = flt(self.get_buying_amount(row, row.item_code), self.currency_precision) + if grouped_by_invoice: + if row.indent == 1.0: + buying_amount += row.buying_amount + elif row.indent == 0.0: + row.buying_amount = buying_amount + buying_amount = 0 + # get buying rate - if row.qty: - row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision) - row.base_rate = flt(row.base_amount / row.qty, self.float_precision) + if flt(row.qty): + row.buying_rate = flt(row.buying_amount / flt(row.qty), self.float_precision) + row.base_rate = flt(row.base_amount / flt(row.qty), self.float_precision) else: - row.buying_rate, row.base_rate = 0.0, 0.0 + if self.is_not_invoice_row(row): + row.buying_rate, row.base_rate = 0.0, 0.0 # calculate gross profit row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision) @@ -171,7 +238,7 @@ class GrossProfitGenerator(object): if i==0: new_row = row else: - new_row.qty += row.qty + new_row.qty += flt(row.qty) new_row.buying_amount += flt(row.buying_amount, self.currency_precision) new_row.base_amount += flt(row.base_amount, self.currency_precision) new_row = self.set_average_rate(new_row) @@ -183,16 +250,19 @@ class GrossProfitGenerator(object): and row.item_code in self.returned_invoices[row.parent]: returned_item_rows = self.returned_invoices[row.parent][row.item_code] for returned_item_row in returned_item_rows: - row.qty += returned_item_row.qty + row.qty += flt(returned_item_row.qty) row.base_amount += flt(returned_item_row.base_amount, self.currency_precision) - row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision) - if row.qty or row.base_amount: + row.buying_amount = flt(flt(row.qty) * flt(row.buying_rate), self.currency_precision) + if (flt(row.qty) or row.base_amount) and self.is_not_invoice_row(row): row = self.set_average_rate(row) self.grouped_data.append(row) self.add_to_totals(row) self.set_average_gross_profit(self.totals) self.grouped_data.append(self.totals) + def is_not_invoice_row(self, row): + return (self.filters.get("group_by") == "Invoice" and row.indent != 0.0) or self.filters.get("group_by") != "Invoice" + def set_average_rate(self, new_row): self.set_average_gross_profit(new_row) new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0 @@ -203,6 +273,8 @@ class GrossProfitGenerator(object): new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision) new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \ if new_row.base_amount else 0 + new_row.buying_rate = flt(new_row.buying_amount / flt(new_row.qty), self.float_precision) if flt(new_row.qty) else 0 + new_row.base_rate = flt(new_row.base_amount / flt(new_row.qty), self.float_precision) if flt(new_row.qty) else 0 def add_to_totals(self, new_row): for key in self.totals: @@ -354,6 +426,109 @@ class GrossProfitGenerator(object): .format(conditions=conditions, sales_person_cols=sales_person_cols, sales_team_table=sales_team_table, match_cond = get_match_cond('Sales Invoice')), self.filters, as_dict=1) + def group_items_by_invoice(self): + """ + Turns list of Sales Invoice Items to a tree of Sales Invoices with their Items as children. + """ + + parents = [] + + for row in self.si_list: + if row.parent not in parents: + parents.append(row.parent) + + parents_index = 0 + for index, row in enumerate(self.si_list): + if parents_index < len(parents) and row.parent == parents[parents_index]: + invoice = self.get_invoice_row(row) + self.si_list.insert(index, invoice) + parents_index += 1 + + else: + # skipping the bundle items rows + if not row.indent: + row.indent = 1.0 + row.parent_invoice = row.parent + row.parent = row.item_code + + if frappe.db.exists('Product Bundle', row.item_code): + self.add_bundle_items(row, index) + + def get_invoice_row(self, row): + return frappe._dict({ + 'parent_invoice': "", + 'indent': 0.0, + 'parent': row.parent, + 'posting_date': row.posting_date, + 'posting_time': row.posting_time, + 'project': row.project, + 'update_stock': row.update_stock, + 'customer': row.customer, + 'customer_group': row.customer_group, + 'item_code': None, + 'item_name': None, + 'description': None, + 'warehouse': None, + 'item_group': None, + 'brand': None, + 'dn_detail': None, + 'delivery_note': None, + 'qty': None, + 'item_row': None, + 'is_return': row.is_return, + 'cost_center': row.cost_center, + 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total') + }) + + def add_bundle_items(self, product_bundle, index): + bundle_items = self.get_bundle_items(product_bundle) + + for i, item in enumerate(bundle_items): + bundle_item = self.get_bundle_item_row(product_bundle, item) + self.si_list.insert((index+i+1), bundle_item) + + def get_bundle_items(self, product_bundle): + return frappe.get_all( + 'Product Bundle Item', + filters = { + 'parent': product_bundle.item_code + }, + fields = ['item_code', 'qty'] + ) + + def get_bundle_item_row(self, product_bundle, item): + item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) + + return frappe._dict({ + 'parent_invoice': product_bundle.item_code, + 'indent': product_bundle.indent + 1, + 'parent': item.item_code, + 'posting_date': product_bundle.posting_date, + 'posting_time': product_bundle.posting_time, + 'project': product_bundle.project, + 'customer': product_bundle.customer, + 'customer_group': product_bundle.customer_group, + 'item_code': item.item_code, + 'item_name': item_name, + 'description': description, + 'warehouse': product_bundle.warehouse, + 'item_group': item_group, + 'brand': brand, + 'dn_detail': product_bundle.dn_detail, + 'delivery_note': product_bundle.delivery_note, + 'qty': (flt(product_bundle.qty) * flt(item.qty)), + 'item_row': None, + 'is_return': product_bundle.is_return, + 'cost_center': product_bundle.cost_center + }) + + def get_bundle_item_details(self, item_code): + return frappe.db.get_value( + 'Item', + item_code, + ['item_name', 'description', 'item_group', 'brand'] + ) + def load_stock_ledger_entries(self): res = frappe.db.sql("""select item_code, voucher_type, voucher_no, voucher_detail_no, stock_value, warehouse, actual_qty as qty diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py index 7dea80cbe26..8f822711a7a 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import getdate, add_days, today, cint from frappe import _ +from frappe.utils import cint + def execute(filters=None): columns = get_columns() diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index 685419a17e4..cd25c050040 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -2,14 +2,23 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ from frappe.utils import flt -from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts, - get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row, - get_group_by_conditions) + +import erpnext +from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import ( + add_sub_total_row, + add_total_row, + get_grand_total, + get_group_by_and_display_fields, + get_group_by_conditions, + get_tax_accounts, +) from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details + def execute(filters=None): return _execute(filters) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index c9c22c246ed..847a127d365 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -2,13 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt, cstr from frappe.model.meta import get_field_precision +from frappe.utils import cstr, flt from frappe.utils.xlsxutils import handle_html + from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments -from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details, get_customer_details +from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import ( + get_customer_details, + get_item_details, +) + def execute(filters=None): return _execute(filters) diff --git a/erpnext/accounts/report/non_billed_report.py b/erpnext/accounts/report/non_billed_report.py index 51735056896..b61f87df5bf 100644 --- a/erpnext/accounts/report/non_billed_report.py +++ b/erpnext/accounts/report/non_billed_report.py @@ -2,11 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import _ -from erpnext import get_default_currency from frappe.model.meta import get_field_precision +from erpnext import get_default_currency + + def get_ordered_to_be_billed_data(args): doctype, party = args.get('doctype'), args.get('party') child_tab = doctype + " Item" diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py index 556f5ad4f79..6c6af1cc5a2 100644 --- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py +++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ +from frappe.utils import flt, getdate + from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport -from frappe.utils import getdate, flt def execute(filters=None): diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py index b7e112c0c9a..c9463caa6db 100644 --- a/erpnext/accounts/report/pos_register/pos_register.py +++ b/erpnext/accounts/report/pos_register/pos_register.py @@ -2,11 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import _, _dict -from erpnext import get_company_currency, get_default_company +from frappe import _ + from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments + def execute(filters=None): if not filters: return [], [] diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 5d04824b571..ef799f63bf9 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -2,11 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt -from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data, - get_filtered_list_for_consolidated_report) + +from erpnext.accounts.report.financial_statements import ( + get_columns, + get_data, + get_filtered_list_for_consolidated_report, + get_period_list, +) + def execute(filters=None): period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py index 48bd7308bca..ad97808973b 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py @@ -2,10 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, getdate, formatdate, cstr -from erpnext.accounts.report.financial_statements import filter_accounts, filter_out_zero_value_rows +from frappe.utils import cstr, flt + +from erpnext.accounts.report.financial_statements import ( + filter_accounts, + filter_out_zero_value_rows, +) from erpnext.accounts.report.trial_balance.trial_balance import validate_filters value_fields = ("income", "expense", "gross_profit_loss") diff --git a/erpnext/accounts/report/purchase_invoice_trends/purchase_invoice_trends.py b/erpnext/accounts/report/purchase_invoice_trends/purchase_invoice_trends.py index ba236b9969d..b26c733bc7e 100644 --- a/erpnext/accounts/report/purchase_invoice_trends/purchase_invoice_trends.py +++ b/erpnext/accounts/report/purchase_invoice_trends/purchase_invoice_trends.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 10edd41aa88..5d4a03ce60a 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -2,10 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _, msgprint from frappe.utils import flt -from frappe import msgprint, _ -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) + def execute(filters=None): return _execute(filters) diff --git a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py index a5eced5f80b..adf6b29ea8f 100644 --- a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py +++ b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe import _ + from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data + def execute(filters=None): columns = get_column() args = get_args() diff --git a/erpnext/accounts/report/sales_invoice_trends/sales_invoice_trends.py b/erpnext/accounts/report/sales_invoice_trends/sales_invoice_trends.py index ee3992f6f48..0ec54c932b8 100644 --- a/erpnext/accounts/report/sales_invoice_trends/sales_invoice_trends.py +++ b/erpnext/accounts/report/sales_invoice_trends/sales_invoice_trends.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py index ff774681a29..9ad7007a2cc 100644 --- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py @@ -1,6 +1,7 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cstr diff --git a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py index e4a3d3527fd..9fd7bc3de73 100644 --- a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py @@ -2,11 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest + import frappe -from erpnext.accounts.report.sales_payment_summary.sales_payment_summary import get_mode_of_payments, get_mode_of_payment_details from frappe.utils import today + from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry +from erpnext.accounts.report.sales_payment_summary.sales_payment_summary import ( + get_mode_of_payment_details, + get_mode_of_payments, +) test_dependencies = ["Sales Invoice"] diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index f38bd78c0d2..57b69aa8187 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -2,11 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt -from frappe import msgprint, _ +from frappe import _, msgprint from frappe.model.meta import get_field_precision -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children +from frappe.utils import flt + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) + def execute(filters=None): return _execute(filters) diff --git a/erpnext/accounts/report/share_balance/share_balance.py b/erpnext/accounts/report/share_balance/share_balance.py index 9f22f81d2bc..03efc9ec33a 100644 --- a/erpnext/accounts/report/share_balance/share_balance.py +++ b/erpnext/accounts/report/share_balance/share_balance.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/accounts/report/share_ledger/share_ledger.py b/erpnext/accounts/report/share_ledger/share_ledger.py index 3ed3c91141e..9be662220d0 100644 --- a/erpnext/accounts/report/share_ledger/share_ledger.py +++ b/erpnext/accounts/report/share_ledger/share_ledger.py @@ -3,9 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cstr, cint, getdate -from frappe import msgprint, _ +from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py index fbd25b13bb5..00316ba2652 100644 --- a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py +++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py @@ -2,8 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from erpnext.accounts.report.customer_ledger_summary.customer_ledger_summary import PartyLedgerSummaryReport + +from erpnext.accounts.report.customer_ledger_summary.customer_ledger_summary import ( + PartyLedgerSummaryReport, +) + def execute(filters=None): args = { diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index 6b9df41f54e..c4a8c7a899a 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -1,10 +1,15 @@ from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + +from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( + get_advance_vouchers, + get_debit_note_amount, +) from erpnext.accounts.utils import get_fiscal_year -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category \ - import get_advance_vouchers, get_debit_note_amount + def execute(filters=None): validate_filters(filters) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index ceefa31cfa1..9e1382b9222 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -2,9 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate + def execute(filters=None): filters["invoices"] = frappe.cache().hget("invoices", frappe.session.user) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 1fc0faab3a7..d65bcc4ada3 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -2,12 +2,21 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt, getdate, formatdate, cstr -from erpnext.accounts.report.financial_statements \ - import filter_accounts, set_gl_entries_by_account, filter_out_zero_value_rows -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children +from frappe.utils import cstr, flt, formatdate, getdate + +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) +from erpnext.accounts.report.financial_statements import ( + filter_accounts, + filter_out_zero_value_rows, + set_gl_entries_by_account, +) value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit") diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py index f034e7450ee..8e245443c33 100644 --- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py +++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py @@ -2,11 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, cint +from frappe.utils import cint, flt + from erpnext.accounts.report.trial_balance.trial_balance import validate_filters + def execute(filters=None): validate_filters(filters) diff --git a/erpnext/accounts/report/unpaid_expense_claim/unpaid_expense_claim.py b/erpnext/accounts/report/unpaid_expense_claim/unpaid_expense_claim.py index 1250d676a06..71fe4a294a3 100644 --- a/erpnext/accounts/report/unpaid_expense_claim/unpaid_expense_claim.py +++ b/erpnext/accounts/report/unpaid_expense_claim/unpaid_expense_claim.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns, data = [], [] columns = get_columns() diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index ba461edaf86..2f9e9578ccb 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -1,9 +1,11 @@ from __future__ import unicode_literals + import frappe +from frappe.utils import flt, formatdate, get_datetime_str + from erpnext import get_company_currency, get_default_company -from erpnext.setup.utils import get_exchange_rate from erpnext.accounts.doctype.fiscal_year.fiscal_year import get_from_and_to_date -from frappe.utils import cint, get_datetime_str, formatdate, flt +from erpnext.setup.utils import get_exchange_rate __exchange_rates = {} @@ -98,15 +100,15 @@ def convert_to_presentation_currency(gl_entries, currency_info, company): if entry.get('credit'): entry['credit'] = credit_in_account_currency else: - value = debit or credit date = currency_info['report_date'] - converted_value = convert(value, presentation_currency, company_currency, date) + converted_debit_value = convert(debit, presentation_currency, company_currency, date) + converted_credit_value = convert(credit, presentation_currency, company_currency, date) if entry.get('debit'): - entry['debit'] = converted_value + entry['debit'] = converted_debit_value if entry.get('credit'): - entry['credit'] = converted_value + entry['credit'] = converted_credit_value converted_gl_list.append(entry) diff --git a/erpnext/accounts/test/test_utils.py b/erpnext/accounts/test/test_utils.py index 628c8ce6463..c3f6d274437 100644 --- a/erpnext/accounts/test/test_utils.py +++ b/erpnext/accounts/test/test_utils.py @@ -1,22 +1,52 @@ from __future__ import unicode_literals + import unittest -from erpnext.accounts.party import get_party_shipping_address + from frappe.test_runner import make_test_objects +from erpnext.accounts.party import get_party_shipping_address +from erpnext.accounts.utils import get_future_stock_vouchers, get_voucherwise_gl_entries +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + class TestUtils(unittest.TestCase): @classmethod def setUpClass(cls): super(TestUtils, cls).setUpClass() - make_test_objects('Address', ADDRESS_RECORDS) + make_test_objects("Address", ADDRESS_RECORDS) def test_get_party_shipping_address(self): - address = get_party_shipping_address('Customer', '_Test Customer 1') - self.assertEqual(address, '_Test Billing Address 2 Title-Billing') + address = get_party_shipping_address("Customer", "_Test Customer 1") + self.assertEqual(address, "_Test Billing Address 2 Title-Billing") def test_get_party_shipping_address2(self): - address = get_party_shipping_address('Customer', '_Test Customer 2') - self.assertEqual(address, '_Test Shipping Address 2 Title-Shipping') + address = get_party_shipping_address("Customer", "_Test Customer 2") + self.assertEqual(address, "_Test Shipping Address 2 Title-Shipping") + + def test_get_voucher_wise_gl_entry(self): + + pr = make_purchase_receipt( + item_code="_Test Item", + posting_date="2021-02-01", + rate=100, + qty=1, + warehouse="Stores - TCP1", + company="_Test Company with perpetual inventory", + ) + + future_vouchers = get_future_stock_vouchers("2021-01-01", "00:00:00", for_items=["_Test Item"]) + + voucher_type_and_no = ("Purchase Receipt", pr.name) + self.assertTrue( + voucher_type_and_no in future_vouchers, + msg="get_future_stock_vouchers not returning correct value", + ) + + posting_date = "2021-01-01" + gl_entries = get_voucherwise_gl_entries(future_vouchers, posting_date) + self.assertTrue( + voucher_type_and_no in gl_entries, msg="get_voucherwise_gl_entries not returning expected GLes", + ) ADDRESS_RECORDS = [ @@ -28,12 +58,8 @@ ADDRESS_RECORDS = [ "city": "Lagos", "country": "Nigeria", "links": [ - { - "link_doctype": "Customer", - "link_name": "_Test Customer 2", - "doctype": "Dynamic Link" - } - ] + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], }, { "doctype": "Address", @@ -43,12 +69,8 @@ ADDRESS_RECORDS = [ "city": "Lagos", "country": "Nigeria", "links": [ - { - "link_doctype": "Customer", - "link_name": "_Test Customer 2", - "doctype": "Dynamic Link" - } - ] + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], }, { "doctype": "Address", @@ -59,12 +81,8 @@ ADDRESS_RECORDS = [ "country": "Nigeria", "is_shipping_address": "1", "links": [ - { - "link_doctype": "Customer", - "link_name": "_Test Customer 2", - "doctype": "Dynamic Link" - } - ] + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], }, { "doctype": "Address", @@ -75,11 +93,7 @@ ADDRESS_RECORDS = [ "country": "Nigeria", "is_shipping_address": "1", "links": [ - { - "link_doctype": "Customer", - "link_name": "_Test Customer 1", - "doctype": "Dynamic Link" - } - ] - } + {"link_doctype": "Customer", "link_name": "_Test Customer 1", "doctype": "Dynamic Link"} + ], + }, ] diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 9120602adf2..848a3a36b12 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -4,18 +4,19 @@ from __future__ import unicode_literals -import frappe, erpnext +import frappe import frappe.defaults -from frappe.utils import nowdate, cstr, flt, cint, now, getdate -from frappe import throw, _ -from frappe.utils import formatdate, get_number_format_info -from six import iteritems -# imported to enable erpnext.accounts.utils.get_account_currency -from erpnext.accounts.doctype.account.account import get_account_currency +from frappe import _, throw from frappe.model.meta import get_field_precision +from frappe.utils import cint, cstr, flt, formatdate, get_number_format_info, getdate, now, nowdate -from erpnext.stock.utils import get_stock_value_on +import erpnext + +# imported to enable erpnext.accounts.utils.get_account_currency +from erpnext.accounts.doctype.account.account import get_account_currency # noqa from erpnext.stock import get_warehouse_account_map +from erpnext.stock.utils import get_stock_value_on + class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass class FiscalYearError(frappe.ValidationError): pass @@ -341,31 +342,42 @@ def add_cc(args=None): def reconcile_against_document(args): """ - Cancel JV, Update aginst document, split if required and resubmit jv + Cancel PE or JV, Update against document, split if required and resubmit """ - for d in args: + # To optimize making GL Entry for PE or JV with multiple references + reconciled_entries = {} + for row in args: + if not reconciled_entries.get((row.voucher_type, row.voucher_no)): + reconciled_entries[(row.voucher_type, row.voucher_no)] = [] - check_if_advance_entry_modified(d) - validate_allocated_amount(d) + reconciled_entries[(row.voucher_type, row.voucher_no)].append(row) + + for key, entries in reconciled_entries.items(): + voucher_type = key[0] + voucher_no = key[1] # cancel advance entry - doc = frappe.get_doc(d.voucher_type, d.voucher_no) - + doc = frappe.get_doc(voucher_type, voucher_no) frappe.flags.ignore_party_validation = True doc.make_gl_entries(cancel=1, adv_adj=1) - # update ref in advance entry - if d.voucher_type == "Journal Entry": - update_reference_in_journal_entry(d, doc) - else: - update_reference_in_payment_entry(d, doc) + for entry in entries: + check_if_advance_entry_modified(entry) + validate_allocated_amount(entry) + # update ref in advance entry + if voucher_type == "Journal Entry": + update_reference_in_journal_entry(entry, doc, do_not_save=True) + else: + update_reference_in_payment_entry(entry, doc, do_not_save=True) + + doc.save(ignore_permissions=True) # re-submit advance entry - doc = frappe.get_doc(d.voucher_type, d.voucher_no) + doc = frappe.get_doc(entry.voucher_type, entry.voucher_no) doc.make_gl_entries(cancel = 0, adv_adj =1) frappe.flags.ignore_party_validation = False - if d.voucher_type in ('Payment Entry', 'Journal Entry'): + if entry.voucher_type in ('Payment Entry', 'Journal Entry'): doc.update_expense_claim() def check_if_advance_entry_modified(args): @@ -374,6 +386,9 @@ def check_if_advance_entry_modified(args): check if amount is same check if jv is submitted """ + if not args.get('unreconciled_amount'): + args.update({'unreconciled_amount': args.get('unadjusted_amount')}) + ret = None if args.voucher_type == "Journal Entry": ret = frappe.db.sql(""" @@ -395,14 +410,14 @@ def check_if_advance_entry_modified(args): and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s and t2.reference_doctype in ("", "Sales Order", "Purchase Order") - and t2.allocated_amount = %(unadjusted_amount)s + and t2.allocated_amount = %(unreconciled_amount)s """.format(party_account_field), args) else: ret = frappe.db.sql("""select name from `tabPayment Entry` where name = %(voucher_no)s and docstatus = 1 and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s - and unallocated_amount = %(unadjusted_amount)s + and unallocated_amount = %(unreconciled_amount)s """.format(party_account_field), args) if not ret: @@ -415,58 +430,44 @@ def validate_allocated_amount(args): elif flt(args.get("allocated_amount"), precision) > flt(args.get("unadjusted_amount"), precision): throw(_("Allocated amount cannot be greater than unadjusted amount")) -def update_reference_in_journal_entry(d, jv_obj): +def update_reference_in_journal_entry(d, journal_entry, do_not_save=False): """ Updates against document, if partial amount splits into rows """ - jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0] - jv_detail.set(d["dr_or_cr"], d["allocated_amount"]) - jv_detail.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit', - d["allocated_amount"]*flt(jv_detail.exchange_rate)) - - original_reference_type = jv_detail.reference_type - original_reference_name = jv_detail.reference_name - - jv_detail.set("reference_type", d["against_voucher_type"]) - jv_detail.set("reference_name", d["against_voucher"]) - - if d['allocated_amount'] < d['unadjusted_amount']: - jvd = frappe.db.sql(""" - select cost_center, balance, against_account, is_advance, - account_type, exchange_rate, account_currency - from `tabJournal Entry Account` where name = %s - """, d['voucher_detail_no'], as_dict=True) + jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0] + if flt(d['unadjusted_amount']) - flt(d['allocated_amount']) != 0: + # adjust the unreconciled balance amount_in_account_currency = flt(d['unadjusted_amount']) - flt(d['allocated_amount']) - amount_in_company_currency = amount_in_account_currency * flt(jvd[0]['exchange_rate']) + amount_in_company_currency = amount_in_account_currency * flt(jv_detail.exchange_rate) + jv_detail.set(d['dr_or_cr'], amount_in_account_currency) + jv_detail.set('debit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'credit', amount_in_company_currency) + else: + journal_entry.remove(jv_detail) - # new entry with balance amount - ch = jv_obj.append("accounts") - ch.account = d['account'] - ch.account_type = jvd[0]['account_type'] - ch.account_currency = jvd[0]['account_currency'] - ch.exchange_rate = jvd[0]['exchange_rate'] - ch.party_type = d["party_type"] - ch.party = d["party"] - ch.cost_center = cstr(jvd[0]["cost_center"]) - ch.balance = flt(jvd[0]["balance"]) + # new row with references + new_row = journal_entry.append("accounts") + new_row.update(jv_detail.as_dict().copy()) - ch.set(d['dr_or_cr'], amount_in_account_currency) - ch.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit', amount_in_company_currency) + new_row.set(d["dr_or_cr"], d["allocated_amount"]) + new_row.set('debit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'credit', + d["allocated_amount"] * flt(jv_detail.exchange_rate)) - ch.set('credit_in_account_currency' if d['dr_or_cr']== 'debit_in_account_currency' - else 'debit_in_account_currency', 0) - ch.set('credit' if d['dr_or_cr']== 'debit_in_account_currency' else 'debit', 0) + new_row.set('credit_in_account_currency' if d['dr_or_cr'] == 'debit_in_account_currency' + else 'debit_in_account_currency', 0) + new_row.set('credit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'debit', 0) - ch.against_account = cstr(jvd[0]["against_account"]) - ch.reference_type = original_reference_type - ch.reference_name = original_reference_name - ch.is_advance = cstr(jvd[0]["is_advance"]) - ch.docstatus = 1 + new_row.set("reference_type", d["against_voucher_type"]) + new_row.set("reference_name", d["against_voucher"]) + + new_row.against_account = cstr(jv_detail.against_account) + new_row.is_advance = cstr(jv_detail.is_advance) + new_row.docstatus = 1 # will work as update after submit - jv_obj.flags.ignore_validate_update_after_submit = True - jv_obj.save(ignore_permissions=True) + journal_entry.flags.ignore_validate_update_after_submit = True + if not do_not_save: + journal_entry.save(ignore_permissions=True) def update_reference_in_payment_entry(d, payment_entry, do_not_save=False): reference_details = { @@ -886,7 +887,9 @@ def get_autoname_with_number(number_value, doc_title, name, company): @frappe.whitelist() def get_coa(doctype, parent, is_root, chart=None): - from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import build_tree_from_json + from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import ( + build_tree_from_json, + ) # add chart to flags to retrieve when called from expand all function chart = chart if chart else frappe.flags.chart @@ -960,6 +963,9 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date): Only fetches GLE fields required for comparing with new GLE. Check compare_existing_and_expected_gle function below. + + returns: + Dict[Tuple[voucher_type, voucher_no], List[GL Entries]] """ gl_entries = {} if not future_stock_vouchers: @@ -968,7 +974,7 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date): voucher_nos = [d[1] for d in future_stock_vouchers] gles = frappe.db.sql(""" - select name, account, credit, debit, cost_center, project + select name, account, credit, debit, cost_center, project, voucher_type, voucher_no from `tabGL Entry` where posting_date >= %s and voucher_no in (%s)""" % diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py b/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py index 3bd3d7db065..b0441c236fc 100644 --- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py +++ b/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AgricultureAnalysisCriteria(Document): pass diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py b/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py index d79970b742f..4213e45c078 100644 --- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py +++ b/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestAgricultureAnalysisCriteria(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py b/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py index ce39368cd99..642f49189da 100644 --- a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py +++ b/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AgricultureTask(Document): pass diff --git a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py b/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py index e828151d0d8..2b3c3386972 100644 --- a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py +++ b/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestAgricultureTask(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/crop/crop_dashboard.py b/erpnext/agriculture/doctype/crop/crop_dashboard.py index 8f37735c812..02b937a74b2 100644 --- a/erpnext/agriculture/doctype/crop/crop_dashboard.py +++ b/erpnext/agriculture/doctype/crop/crop_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'transactions': [ diff --git a/erpnext/agriculture/doctype/crop/test_crop.py b/erpnext/agriculture/doctype/crop/test_crop.py index b3079837c35..1968a04796d 100644 --- a/erpnext/agriculture/doctype/crop/test_crop.py +++ b/erpnext/agriculture/doctype/crop/test_crop.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_dependencies = ["Fertilizer"] class TestCrop(unittest.TestCase): diff --git a/erpnext/agriculture/doctype/detected_disease/detected_disease.py b/erpnext/agriculture/doctype/detected_disease/detected_disease.py index 8c90b839b59..b73fc32f7fd 100644 --- a/erpnext/agriculture/doctype/detected_disease/detected_disease.py +++ b/erpnext/agriculture/doctype/detected_disease/detected_disease.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class DetectedDisease(Document): pass diff --git a/erpnext/agriculture/doctype/disease/disease.py b/erpnext/agriculture/doctype/disease/disease.py index affa57046e5..e474efe5153 100644 --- a/erpnext/agriculture/doctype/disease/disease.py +++ b/erpnext/agriculture/doctype/disease/disease.py @@ -3,10 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe import _ + class Disease(Document): def validate(self): diff --git a/erpnext/agriculture/doctype/disease/test_disease.py b/erpnext/agriculture/doctype/disease/test_disease.py index 80861770b0d..1959d1f8112 100644 --- a/erpnext/agriculture/doctype/disease/test_disease.py +++ b/erpnext/agriculture/doctype/disease/test_disease.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestDisease(unittest.TestCase): def test_treatment_period(self): disease = frappe.get_doc('Disease', 'Aphids') diff --git a/erpnext/agriculture/doctype/fertilizer/fertilizer.py b/erpnext/agriculture/doctype/fertilizer/fertilizer.py index c475f002981..75c2542b85a 100644 --- a/erpnext/agriculture/doctype/fertilizer/fertilizer.py +++ b/erpnext/agriculture/doctype/fertilizer/fertilizer.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class Fertilizer(Document): @frappe.whitelist() def load_contents(self): diff --git a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py b/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py index 4c71d33fe80..c11c61afec2 100644 --- a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py +++ b/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestFertilizer(unittest.TestCase): def test_fertilizer_creation(self): self.assertEqual(frappe.db.exists('Fertilizer', 'Urea'), 'Urea') diff --git a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py b/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py index d3852425918..a050b710107 100644 --- a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py +++ b/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class FertilizerContent(Document): pass diff --git a/erpnext/agriculture/doctype/linked_location/linked_location.py b/erpnext/agriculture/doctype/linked_location/linked_location.py index 3e49d3e18fd..e622e84dc32 100644 --- a/erpnext/agriculture/doctype/linked_location/linked_location.py +++ b/erpnext/agriculture/doctype/linked_location/linked_location.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LinkedLocation(Document): pass diff --git a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py b/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py index daea54b6132..608bf8c5e3a 100644 --- a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py +++ b/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LinkedPlantAnalysis(Document): pass diff --git a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py b/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py index c4e9245cd79..02eb133de91 100644 --- a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py +++ b/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LinkedSoilAnalysis(Document): pass diff --git a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py b/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py index 1b7589298e2..f580e165762 100644 --- a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py +++ b/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LinkedSoilTexture(Document): pass diff --git a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py b/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py index b65f93de0a0..62382500166 100644 --- a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py +++ b/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py @@ -3,10 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.naming import make_autoname from frappe.model.document import Document + class PlantAnalysis(Document): @frappe.whitelist() def load_contents(self): diff --git a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py b/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py index cbd2fd7431a..6b6e8436124 100644 --- a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py +++ b/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestPlantAnalysis(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py b/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py index c1731846a86..9f719874ed2 100644 --- a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py +++ b/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PlantAnalysisCriteria(Document): pass diff --git a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py b/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py index 234d0d4b011..e0c8177e630 100644 --- a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py +++ b/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class SoilAnalysis(Document): @frappe.whitelist() def load_contents(self): diff --git a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py b/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py index b89d7563115..24fe0748d38 100644 --- a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py +++ b/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestSoilAnalysis(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py b/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py index b073c200c09..09b917c549a 100644 --- a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py +++ b/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SoilAnalysisCriteria(Document): pass diff --git a/erpnext/agriculture/doctype/soil_texture/soil_texture.py b/erpnext/agriculture/doctype/soil_texture/soil_texture.py index 209b2c8598f..636af77f4f8 100644 --- a/erpnext/agriculture/doctype/soil_texture/soil_texture.py +++ b/erpnext/agriculture/doctype/soil_texture/soil_texture.py @@ -3,11 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt, cint -from frappe import _ +from frappe.utils import cint, flt + class SoilTexture(Document): soil_edit_order = [2, 1, 0] diff --git a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py b/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py index 16d105c9c58..c701eb8f271 100644 --- a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py +++ b/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestSoilTexture(unittest.TestCase): def test_texture_selection(self): soil_tex = frappe.get_all('Soil Texture', fields=['name'], filters={'collection_datetime': '2017-11-08'}) diff --git a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py b/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py index a7525ae6e96..9980e8b0cae 100644 --- a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py +++ b/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SoilTextureCriteria(Document): pass diff --git a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py b/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py index b6467b7f45d..5cddeeb1616 100644 --- a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py +++ b/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestWaterAnalysis(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/water_analysis/water_analysis.py b/erpnext/agriculture/doctype/water_analysis/water_analysis.py index cb2691d4555..228ae340f20 100644 --- a/erpnext/agriculture/doctype/water_analysis/water_analysis.py +++ b/erpnext/agriculture/doctype/water_analysis/water_analysis.py @@ -3,10 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe import _ + class WaterAnalysis(Document): @frappe.whitelist() diff --git a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py b/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py index 6833f905394..8771733213c 100644 --- a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py +++ b/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class WaterAnalysisCriteria(Document): pass diff --git a/erpnext/agriculture/doctype/weather/test_weather.py b/erpnext/agriculture/doctype/weather/test_weather.py index b4ab3ae6f35..1b4bab9a53a 100644 --- a/erpnext/agriculture/doctype/weather/test_weather.py +++ b/erpnext/agriculture/doctype/weather/test_weather.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestWeather(unittest.TestCase): pass diff --git a/erpnext/agriculture/doctype/weather/weather.py b/erpnext/agriculture/doctype/weather/weather.py index 235e684e511..b41964dafda 100644 --- a/erpnext/agriculture/doctype/weather/weather.py +++ b/erpnext/agriculture/doctype/weather/weather.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class Weather(Document): @frappe.whitelist() def load_contents(self): diff --git a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py b/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py index 89db74cd7cb..42fcbcb719a 100644 --- a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py +++ b/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class WeatherParameter(Document): pass diff --git a/erpnext/agriculture/setup.py b/erpnext/agriculture/setup.py index 75f07be5de2..d47fb812903 100644 --- a/erpnext/agriculture/setup.py +++ b/erpnext/agriculture/setup.py @@ -1,8 +1,11 @@ from __future__ import unicode_literals + import frappe from frappe import _ + from erpnext.setup.utils import insert_record + def setup_agriculture(): if frappe.get_all('Agriculture Analysis Criteria'): # already setup diff --git a/erpnext/assets/dashboard_fixtures.py b/erpnext/assets/dashboard_fixtures.py index 2c701796072..39f0f1a88be 100644 --- a/erpnext/assets/dashboard_fixtures.py +++ b/erpnext/assets/dashboard_fixtures.py @@ -1,13 +1,16 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import frappe import json -from frappe.utils import nowdate, add_months, get_date_str + +import frappe from frappe import _ +from frappe.utils import get_date_str, nowdate + from erpnext.accounts.dashboard_fixtures import _get_fiscal_year from erpnext.buying.dashboard_fixtures import get_company_for_dashboards + def get_data(): fiscal_year = _get_fiscal_year(nowdate()) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 6828c58960b..8ff4f9790aa 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -3,18 +3,37 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext, math, json + +import json +import math + +import frappe from frappe import _ +from frappe.utils import ( + add_days, + add_months, + cint, + date_diff, + flt, + get_datetime, + get_last_day, + getdate, + month_diff, + nowdate, + today, +) from six import string_types -from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, month_diff, add_days, get_last_day, get_datetime -from frappe.model.document import Document + +import erpnext +from erpnext.accounts.general_ledger import make_reverse_gl_entries +from erpnext.assets.doctype.asset.depreciation import ( + get_depreciation_accounts, + get_disposal_account_and_cost_center, +) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account -from erpnext.assets.doctype.asset.depreciation \ - import get_disposal_account_and_cost_center, get_depreciation_accounts -from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries -from erpnext.accounts.utils import get_account_currency from erpnext.controllers.accounts_controller import AccountsController + class Asset(AccountsController): def validate(self): self.validate_asset_values() @@ -321,10 +340,10 @@ class Asset(AccountsController): def get_from_date(self, finance_book): if not self.get('schedules'): return self.available_for_use_date - + if len(self.finance_books) == 1: return self.schedules[-1].schedule_date - + from_date = "" for schedule in self.get('schedules'): if schedule.finance_book == finance_book: @@ -546,7 +565,7 @@ class Asset(AccountsController): cwip_account = None try: cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company) - except: + except Exception: # if no cwip account found in category or company and "cwip is enabled" then raise else silently pass if cwip_enabled: raise @@ -783,6 +802,7 @@ def make_journal_entry(asset_name): @frappe.whitelist() def make_asset_movement(assets, purpose=None): import json + from six import string_types if isinstance(assets, string_types): diff --git a/erpnext/assets/doctype/asset/asset_dashboard.py b/erpnext/assets/doctype/asset/asset_dashboard.py index 62bb4be53aa..cd04e1d8f04 100644 --- a/erpnext/assets/doctype/asset/asset_dashboard.py +++ b/erpnext/assets/doctype/asset/asset_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'non_standard_fieldnames': { diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 9a61b79ed35..609791012a2 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -3,10 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, today, getdate, cint -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts +from frappe.utils import cint, flt, getdate, today + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_checks_for_pl_and_bs_accounts, +) + def post_depreciation_entries(date=None): # Return if automatic booking of asset depreciation is disabled diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 605ce2e2503..4cc9be5b05d 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -3,14 +3,23 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, add_months -from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset -from erpnext.assets.doctype.asset.asset import make_sales_invoice -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + +import frappe +from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice +from erpnext.assets.doctype.asset.asset import make_sales_invoice +from erpnext.assets.doctype.asset.depreciation import ( + post_depreciation_entries, + restore_asset, + scrap_asset, +) +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + make_purchase_invoice as make_invoice, +) +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + class TestAsset(unittest.TestCase): def setUp(self): diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 39032d637b5..1e56c010c46 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cint, get_link_to_form from frappe.model.document import Document +from frappe.utils import cint, get_link_to_form + class AssetCategory(Document): def validate(self): diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py index 9f7ada65d82..53ec4ed38ef 100644 --- a/erpnext/assets/doctype/asset_category/test_asset_category.py +++ b/erpnext/assets/doctype/asset_category/test_asset_category.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestAssetCategory(unittest.TestCase): def test_mandatory_fields(self): asset_category = frappe.new_doc("Asset Category") diff --git a/erpnext/assets/doctype/asset_category_account/asset_category_account.py b/erpnext/assets/doctype/asset_category_account/asset_category_account.py index 67925f4fe8b..66280acb2e8 100644 --- a/erpnext/assets/doctype/asset_category_account/asset_category_account.py +++ b/erpnext/assets/doctype/asset_category_account/asset_category_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssetCategoryAccount(Document): pass diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py index bdc2acfb792..c4f095305c5 100644 --- a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py +++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssetFinanceBook(Document): pass diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py index e14f1d88dcb..ec55fa4efcb 100644 --- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py @@ -3,12 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document +from frappe import _, throw from frappe.desk.form import assign_to -from frappe import throw, _ +from frappe.model.document import Document from frappe.utils import add_days, add_months, add_years, getdate, nowdate + class AssetMaintenance(Document): def validate(self): for task in self.get('asset_maintenance_tasks'): diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py index 7610152039d..0f915086a9f 100644 --- a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py @@ -3,11 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, get_last_day, add_days -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + +import frappe +from frappe.utils import add_days, get_last_day, nowdate + from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate_next_due_date +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + class TestAssetMaintenance(unittest.TestCase): def setUp(self): diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py index 34facd8d050..1f2393649d0 100644 --- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import nowdate, getdate +from frappe.model.document import Document +from frappe.utils import getdate, nowdate + from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate_next_due_date + class AssetMaintenanceLog(Document): def validate(self): if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]: diff --git a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py index a1ec8792b2d..7ad69e92aba 100644 --- a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py +++ b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestAssetMaintenanceLog(unittest.TestCase): pass diff --git a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py index 2a5666d5064..2280f557284 100644 --- a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py +++ b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssetMaintenanceTask(Document): pass diff --git a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py index f741a8fff3e..46e9029941c 100644 --- a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py +++ b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssetMaintenanceTeam(Document): pass diff --git a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py index a0c0b146f1b..8d757b74c06 100644 --- a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py +++ b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestAssetMaintenanceTeam(unittest.TestCase): pass diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index 1771e27ddfe..901bdb5c001 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class AssetMovement(Document): def validate(self): self.validate_asset() diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py index 2b2d2b44004..058bbd1abd6 100644 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -3,16 +3,16 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -import erpnext -from erpnext.stock.doctype.item.test_item import make_item -from frappe.utils import now, nowdate, get_last_day, add_days + +import frappe +from frappe.utils import now + from erpnext.assets.doctype.asset.test_asset import create_asset_data -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + class TestAssetMovement(unittest.TestCase): def setUp(self): frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "CWIP Account - _TC") diff --git a/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py b/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py index 4c6aaab58a0..24da37176e8 100644 --- a/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py +++ b/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AssetMovementItem(Document): pass diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 746f582fdcd..99a7d9bfbf8 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -3,13 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import time_diff_in_hours, getdate, add_months, flt, cint +from frappe.utils import add_months, cint, flt, getdate, time_diff_in_hours + from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.controllers.accounts_controller import AccountsController + class AssetRepair(AccountsController): def validate(self): self.asset_doc = frappe.get_doc('Asset', self.asset) diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 5e727d007a9..9945a328cfc 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -2,10 +2,18 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import nowdate, flt + import unittest -from erpnext.assets.doctype.asset.test_asset import create_asset_data, create_asset, set_depreciation_settings_in_company + +import frappe +from frappe.utils import flt, nowdate + +from erpnext.assets.doctype.asset.test_asset import ( + create_asset, + create_asset_data, + set_depreciation_settings_in_company, +) + class TestAssetRepair(unittest.TestCase): def setUp(self): @@ -110,8 +118,8 @@ def num_of_depreciations(asset): return asset.finance_books[0].total_number_of_depreciations def create_asset_repair(**args): - from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse args = frappe._dict(args) diff --git a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py index fa22a5712f4..2a8d64ef490 100644 --- a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py +++ b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class AssetRepairConsumedItem(Document): pass diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 2f6b5ee2dc9..2c11018caa9 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -3,12 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, getdate, cint, date_diff, formatdate -from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from frappe.model.document import Document -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts +from frappe.utils import cint, date_diff, flt, formatdate, getdate + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_checks_for_pl_and_bs_accounts, +) +from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts + class AssetValueAdjustment(Document): def validate(self): diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py index a9dc9795ee3..52728d6fd69 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py @@ -3,12 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, get_last_day, add_days + +import frappe +from frappe.utils import add_days, get_last_day, nowdate + from erpnext.assets.doctype.asset.test_asset import create_asset_data +from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( + get_current_asset_value, +) from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt -from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import get_current_asset_value + class TestAssetValueAdjustment(unittest.TestCase): def setUp(self): diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py index 54fba3f68c1..3199b7dc8dc 100644 --- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class DepreciationSchedule(Document): pass diff --git a/erpnext/assets/doctype/linked_location/linked_location.py b/erpnext/assets/doctype/linked_location/linked_location.py index 3e49d3e18fd..e622e84dc32 100644 --- a/erpnext/assets/doctype/linked_location/linked_location.py +++ b/erpnext/assets/doctype/linked_location/linked_location.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LinkedLocation(Document): pass diff --git a/erpnext/assets/doctype/location/location.py b/erpnext/assets/doctype/location/location.py index 317894cb58e..1430306bec1 100644 --- a/erpnext/assets/doctype/location/location.py +++ b/erpnext/assets/doctype/location/location.py @@ -8,8 +8,6 @@ import json import math import frappe -from frappe import _ -from frappe.model.document import Document from frappe.utils import flt from frappe.utils.nestedset import NestedSet, update_nsm diff --git a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py index 3d9e555db6d..8fc5c9c43c1 100644 --- a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py +++ b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MaintenanceTeamMember(Document): pass diff --git a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py index c805e56e5ca..f8958c6bbef 100644 --- a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py +++ b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestMaintenanceTeamMember(unittest.TestCase): pass diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 7d07397944b..e370b9d0cb3 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -2,10 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cstr, today, flt, add_years, formatdate, getdate -from erpnext.accounts.report.financial_statements import get_period_list, get_fiscal_year_data, validate_fiscal_year +from frappe.utils import cstr, flt, formatdate, getdate + +from erpnext.accounts.report.financial_statements import ( + get_fiscal_year_data, + get_period_list, + validate_fiscal_year, +) + def execute(filters=None): filters = frappe._dict(filters or {}) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py index a634a0908b0..9e72c1890c5 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/buying_settings.py @@ -4,10 +4,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe.model.document import Document + class BuyingSettings(Document): def validate(self): for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]: diff --git a/erpnext/buying/doctype/buying_settings/test_buying_settings.py b/erpnext/buying/doctype/buying_settings/test_buying_settings.py index bf6eec67d4c..4998aebd6bb 100644 --- a/erpnext/buying/doctype/buying_settings/test_buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/test_buying_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBuyingSettings(unittest.TestCase): pass diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index a55a0b7f9fc..ef54538fcd4 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -144,9 +144,7 @@ { "fieldname": "supplier_section", "fieldtype": "Section Break", - "options": "fa fa-user", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-user" }, { "allow_on_submit": 1, @@ -156,9 +154,7 @@ "hidden": 1, "label": "Title", "no_copy": 1, - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "naming_series", @@ -170,9 +166,7 @@ "options": "PUR-ORD-.YYYY.-", "print_hide": 1, "reqd": 1, - "set_only_once": 1, - "show_days": 1, - "show_seconds": 1 + "set_only_once": 1 }, { "bold": 1, @@ -186,18 +180,14 @@ "options": "Supplier", "print_hide": 1, "reqd": 1, - "search_index": 1, - "show_days": 1, - "show_seconds": 1 + "search_index": 1 }, { "depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))", "description": "Fetch items based on Default Supplier.", "fieldname": "get_items_from_open_material_requests", "fieldtype": "Button", - "label": "Get Items from Open Material Requests", - "show_days": 1, - "show_seconds": 1 + "label": "Get Items from Open Material Requests" }, { "bold": 1, @@ -206,9 +196,7 @@ "fieldtype": "Data", "in_global_search": 1, "label": "Supplier Name", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "company", @@ -220,17 +208,13 @@ "options": "Company", "print_hide": 1, "remember_last_selected_value": 1, - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "fieldname": "column_break1", "fieldtype": "Column Break", "oldfieldtype": "Column Break", "print_width": "50%", - "show_days": 1, - "show_seconds": 1, "width": "50%" }, { @@ -242,35 +226,27 @@ "oldfieldname": "transaction_date", "oldfieldtype": "Date", "reqd": 1, - "search_index": 1, - "show_days": 1, - "show_seconds": 1 + "search_index": 1 }, { "allow_on_submit": 1, "fieldname": "schedule_date", "fieldtype": "Date", - "label": "Required By", - "show_days": 1, - "show_seconds": 1 + "label": "Required By" }, { "allow_on_submit": 1, "depends_on": "eval:doc.docstatus===1", "fieldname": "order_confirmation_no", "fieldtype": "Data", - "label": "Order Confirmation No", - "show_days": 1, - "show_seconds": 1 + "label": "Order Confirmation No" }, { "allow_on_submit": 1, "depends_on": "eval:doc.order_confirmation_no", "fieldname": "order_confirmation_date", "fieldtype": "Date", - "label": "Order Confirmation Date", - "show_days": 1, - "show_seconds": 1 + "label": "Order Confirmation Date" }, { "fieldname": "amended_from", @@ -282,25 +258,19 @@ "oldfieldtype": "Data", "options": "Purchase Order", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "drop_ship", "fieldtype": "Section Break", - "label": "Drop Ship", - "show_days": 1, - "show_seconds": 1 + "label": "Drop Ship" }, { "fieldname": "customer", "fieldtype": "Link", "label": "Customer", "options": "Customer", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "bold": 1, @@ -308,41 +278,31 @@ "fieldtype": "Data", "label": "Customer Name", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_19", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "customer_contact_person", "fieldtype": "Link", "label": "Customer Contact", - "options": "Contact", - "show_days": 1, - "show_seconds": 1 + "options": "Contact" }, { "fieldname": "customer_contact_display", "fieldtype": "Small Text", "hidden": 1, "label": "Customer Contact", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "customer_contact_mobile", "fieldtype": "Small Text", "hidden": 1, "label": "Customer Mobile No", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "customer_contact_email", @@ -350,35 +310,27 @@ "hidden": 1, "label": "Customer Contact Email", "options": "Email", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "collapsible": 1, "fieldname": "section_addresses", "fieldtype": "Section Break", - "label": "Address and Contact", - "show_days": 1, - "show_seconds": 1 + "label": "Address and Contact" }, { "fieldname": "supplier_address", "fieldtype": "Link", "label": "Supplier Address", "options": "Address", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "contact_person", "fieldtype": "Link", "label": "Supplier Contact", "options": "Contact", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "address_display", @@ -405,42 +357,32 @@ "label": "Contact Email", "options": "Email", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "col_break_address", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "shipping_address", "fieldtype": "Link", "label": "Company Shipping Address", "options": "Address", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "shipping_address_display", "fieldtype": "Small Text", "label": "Shipping Address Details", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "collapsible": 1, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", "label": "Currency and Price List", - "options": "fa fa-tag", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-tag" }, { "fieldname": "currency", @@ -450,9 +392,7 @@ "oldfieldtype": "Select", "options": "Currency", "print_hide": 1, - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "fieldname": "conversion_rate", @@ -462,24 +402,18 @@ "oldfieldtype": "Currency", "precision": "9", "print_hide": 1, - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "fieldname": "cb_price_list", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "buying_price_list", "fieldtype": "Link", "label": "Price List", "options": "Price List", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "price_list_currency", @@ -487,18 +421,14 @@ "label": "Price List Currency", "options": "Currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "plc_conversion_rate", "fieldtype": "Float", "label": "Price List Exchange Rate", "precision": "9", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "default": "0", @@ -507,9 +437,7 @@ "label": "Ignore Pricing Rule", "no_copy": 1, "permlevel": 1, - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "sec_warehouse", @@ -522,15 +450,11 @@ "fieldtype": "Link", "label": "Set Target Warehouse", "options": "Warehouse", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "col_break_warehouse", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "default": "No", @@ -539,35 +463,27 @@ "in_standard_filter": 1, "label": "Supply Raw Materials", "options": "No\nYes", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "depends_on": "eval:doc.is_subcontracted==\"Yes\"", "fieldname": "supplier_warehouse", "fieldtype": "Link", "label": "Supplier Warehouse", - "options": "Warehouse", - "show_days": 1, - "show_seconds": 1 + "options": "Warehouse" }, { "fieldname": "items_section", "fieldtype": "Section Break", "hide_border": 1, "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-shopping-cart" }, { "fieldname": "scan_barcode", "fieldtype": "Data", "label": "Scan Barcode", - "options": "Barcode", - "show_days": 1, - "show_seconds": 1 + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -577,34 +493,26 @@ "oldfieldname": "po_details", "oldfieldtype": "Table", "options": "Purchase Order Item", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "collapsible": 1, "fieldname": "section_break_48", "fieldtype": "Section Break", - "label": "Pricing Rules", - "show_days": 1, - "show_seconds": 1 + "label": "Pricing Rules" }, { "fieldname": "pricing_rules", "fieldtype": "Table", "label": "Purchase Order Pricing Rule", "options": "Pricing Rule Detail", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "collapsible_depends_on": "supplied_items", "fieldname": "raw_material_details", "fieldtype": "Section Break", - "label": "Raw Materials Supplied", - "show_days": 1, - "show_seconds": 1 + "label": "Raw Materials Supplied" }, { "fieldname": "supplied_items", @@ -615,23 +523,17 @@ "oldfieldtype": "Table", "options": "Purchase Order Item Supplied", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "sb_last_purchase", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "fieldname": "total_qty", "fieldtype": "Float", "label": "Total Quantity", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "base_total", @@ -639,9 +541,7 @@ "label": "Total (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "base_net_total", @@ -652,24 +552,18 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_26", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "total", "fieldtype": "Currency", "label": "Total", "options": "currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "net_total", @@ -679,26 +573,20 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "total_net_weight", "fieldtype": "Float", "label": "Total Net Weight", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "taxes_section", "fieldtype": "Section Break", "oldfieldtype": "Section Break", - "options": "fa fa-money", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-money" }, { "fieldname": "taxes_and_charges", @@ -707,24 +595,18 @@ "oldfieldname": "purchase_other_charges", "oldfieldtype": "Link", "options": "Purchase Taxes and Charges Template", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "column_break_50", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "shipping_rule", "fieldtype": "Link", "label": "Shipping Rule", "options": "Shipping Rule", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "section_break_52", @@ -737,17 +619,13 @@ "label": "Purchase Taxes and Charges", "oldfieldname": "purchase_tax_details", "oldfieldtype": "Table", - "options": "Purchase Taxes and Charges", - "show_days": 1, - "show_seconds": 1 + "options": "Purchase Taxes and Charges" }, { "collapsible": 1, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", - "label": "Tax Breakup", - "show_days": 1, - "show_seconds": 1 + "label": "Tax Breakup" }, { "fieldname": "other_charges_calculation", @@ -756,18 +634,14 @@ "no_copy": 1, "oldfieldtype": "HTML", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "totals", "fieldtype": "Section Break", "label": "Taxes and Charges", "oldfieldtype": "Section Break", - "options": "fa fa-money", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-money" }, { "depends_on": "base_taxes_and_charges_added", @@ -778,9 +652,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "base_taxes_and_charges_deducted", @@ -791,9 +663,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "base_total_taxes_and_charges", @@ -805,15 +675,11 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_39", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "depends_on": "taxes_and_charges_added", @@ -824,9 +690,7 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "taxes_and_charges_deducted", @@ -837,9 +701,7 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "total_taxes_and_charges", @@ -848,18 +710,14 @@ "label": "Total Taxes and Charges", "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "collapsible": 1, "collapsible_depends_on": "apply_discount_on", "fieldname": "discount_section", "fieldtype": "Section Break", - "label": "Additional Discount", - "show_days": 1, - "show_seconds": 1 + "label": "Additional Discount" }, { "default": "Grand Total", @@ -867,9 +725,7 @@ "fieldtype": "Select", "label": "Apply Additional Discount On", "options": "\nGrand Total\nNet Total", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "base_discount_amount", @@ -877,32 +733,24 @@ "label": "Additional Discount Amount (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_45", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "additional_discount_percentage", "fieldtype": "Float", "label": "Additional Discount Percentage", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "discount_amount", "fieldtype": "Currency", "label": "Additional Discount Amount", "options": "currency", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "totals_section", @@ -918,9 +766,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -930,9 +776,7 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "description": "In Words will be visible once you save the Purchase Order.", @@ -943,9 +787,7 @@ "oldfieldname": "in_words", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "base_rounded_total", @@ -955,16 +797,12 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break4", "fieldtype": "Column Break", - "oldfieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Column Break" }, { "fieldname": "grand_total", @@ -974,9 +812,7 @@ "oldfieldname": "grand_total_import", "oldfieldtype": "Currency", "options": "currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -986,26 +822,20 @@ "no_copy": 1, "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "rounded_total", "fieldtype": "Currency", "label": "Rounded Total", "options": "currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "default": "0", "fieldname": "disable_rounded_total", "fieldtype": "Check", - "label": "Disable Rounded Total", - "show_days": 1, - "show_seconds": 1 + "label": "Disable Rounded Total" }, { "fieldname": "in_words", @@ -1015,9 +845,7 @@ "oldfieldname": "in_words_import", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "advance_paid", @@ -1026,25 +854,19 @@ "no_copy": 1, "options": "party_account_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "collapsible": 1, "fieldname": "payment_schedule_section", "fieldtype": "Section Break", - "label": "Payment Terms", - "show_days": 1, - "show_seconds": 1 + "label": "Payment Terms" }, { "fieldname": "payment_terms_template", "fieldtype": "Link", "label": "Payment Terms Template", - "options": "Payment Terms Template", - "show_days": 1, - "show_seconds": 1 + "options": "Payment Terms Template" }, { "fieldname": "payment_schedule", @@ -1052,9 +874,7 @@ "label": "Payment Schedule", "no_copy": 1, "options": "Payment Schedule", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "collapsible": 1, @@ -1063,9 +883,7 @@ "fieldtype": "Section Break", "label": "Terms and Conditions", "oldfieldtype": "Section Break", - "options": "fa fa-legal", - "show_days": 1, - "show_seconds": 1 + "options": "fa fa-legal" }, { "fieldname": "tc_name", @@ -1074,27 +892,21 @@ "oldfieldname": "tc_name", "oldfieldtype": "Link", "options": "Terms and Conditions", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "terms", "fieldtype": "Text Editor", "label": "Terms and Conditions", "oldfieldname": "terms", - "oldfieldtype": "Text Editor", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Text Editor" }, { "collapsible": 1, "fieldname": "more_info", "fieldtype": "Section Break", "label": "More Information", - "oldfieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Section Break" }, { "default": "Draft", @@ -1109,9 +921,7 @@ "print_hide": 1, "read_only": 1, "reqd": 1, - "search_index": 1, - "show_days": 1, - "show_seconds": 1 + "search_index": 1 }, { "fieldname": "ref_sq", @@ -1122,9 +932,7 @@ "oldfieldtype": "Data", "options": "Supplier Quotation", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "party_account_currency", @@ -1134,24 +942,18 @@ "no_copy": 1, "options": "Currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "inter_company_order_reference", "fieldtype": "Link", "label": "Inter Company Order Reference", "options": "Sales Order", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_74", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "depends_on": "eval:!doc.__islocal", @@ -1161,9 +963,7 @@ "label": "% Received", "no_copy": 1, "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "depends_on": "eval:!doc.__islocal", @@ -1173,9 +973,7 @@ "label": "% Billed", "no_copy": 1, "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "collapsible": 1, @@ -1185,8 +983,6 @@ "oldfieldtype": "Column Break", "print_hide": 1, "print_width": "50%", - "show_days": 1, - "show_seconds": 1, "width": "50%" }, { @@ -1197,9 +993,7 @@ "oldfieldname": "letter_head", "oldfieldtype": "Select", "options": "Letter Head", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "allow_on_submit": 1, @@ -1211,15 +1005,11 @@ "oldfieldtype": "Link", "options": "Print Heading", "print_hide": 1, - "report_hide": 1, - "show_days": 1, - "show_seconds": 1 + "report_hide": 1 }, { "fieldname": "column_break_86", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "allow_on_submit": 1, @@ -1227,25 +1017,19 @@ "fieldname": "group_same_items", "fieldtype": "Check", "label": "Group same items", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "language", "fieldtype": "Data", "label": "Print Language", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "collapsible": 1, "fieldname": "subscription_section", "fieldtype": "Section Break", - "label": "Subscription Section", - "show_days": 1, - "show_seconds": 1 + "label": "Subscription Section" }, { "allow_on_submit": 1, @@ -1253,9 +1037,7 @@ "fieldtype": "Date", "label": "From Date", "no_copy": 1, - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "allow_on_submit": 1, @@ -1263,15 +1045,11 @@ "fieldtype": "Date", "label": "To Date", "no_copy": 1, - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "column_break_97", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "auto_repeat", @@ -1280,35 +1058,27 @@ "no_copy": 1, "options": "Auto Repeat", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "allow_on_submit": 1, "depends_on": "eval: doc.auto_repeat", "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", - "label": "Update Auto Repeat Reference", - "show_days": 1, - "show_seconds": 1 + "label": "Update Auto Repeat Reference" }, { "fieldname": "tax_category", "fieldtype": "Link", "label": "Tax Category", - "options": "Tax Category", - "show_days": 1, - "show_seconds": 1 + "options": "Tax Category" }, { "depends_on": "supplied_items", "fieldname": "set_reserve_warehouse", "fieldtype": "Link", "label": "Set Reserve Warehouse", - "options": "Warehouse", - "show_days": 1, - "show_seconds": 1 + "options": "Warehouse" }, { "collapsible": 1, @@ -1318,9 +1088,7 @@ }, { "fieldname": "column_break_75", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "billing_address", @@ -1361,25 +1129,21 @@ "default": "0", "fieldname": "apply_tds", "fieldtype": "Check", - "label": "Apply Tax Withholding Amount", - "show_days": 1, - "show_seconds": 1 + "label": "Apply Tax Withholding Amount" }, { "depends_on": "eval: doc.apply_tds", "fieldname": "tax_withholding_category", "fieldtype": "Link", "label": "Tax Withholding Category", - "options": "Tax Withholding Category", - "show_days": 1, - "show_seconds": 1 + "options": "Tax Withholding Category" } ], "icon": "fa fa-file-text", "idx": 105, "is_submittable": 1, "links": [], - "modified": "2021-08-17 20:16:12.737743", + "modified": "2021-08-30 20:03:14.008804", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index ca3bd90960c..ac86337b257 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -2,23 +2,30 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json -from frappe.utils import cstr, flt, cint -from frappe import msgprint, _ -from frappe.model.mapper import get_mapped_doc -from erpnext.controllers.buying_controller import BuyingController -from erpnext.stock.doctype.item.item import get_last_purchase_details -from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty + +import frappe +from frappe import _, msgprint from frappe.desk.notifications import clear_doctype_notifications -from erpnext.buying.utils import validate_for_items, check_on_hold_or_closed_status -from erpnext.stock.utils import get_bin +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, cstr, flt + +from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + unlink_inter_company_doc, + update_linked_doc, + validate_inter_company_party, +) +from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( + get_party_tax_withholding_details, +) from erpnext.accounts.party import get_party_account_currency -from erpnext.stock.doctype.item.item import get_item_defaults +from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_items +from erpnext.controllers.buying_controller import BuyingController from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults -from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details -from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_party, - update_linked_doc, unlink_inter_company_doc) +from erpnext.stock.doctype.item.item import get_item_defaults, get_last_purchase_details +from erpnext.stock.stock_balance import get_ordered_qty, update_bin_qty +from erpnext.stock.utils import get_bin form_grid_templates = { "items": "templates/form_grid/item_grid.html" diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py index ab514dac308..af1dceb4070 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'purchase_order', diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index fa174ba8fa8..1453b8e7e4d 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -2,24 +2,31 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest -import frappe -import json -import frappe.defaults -from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry -from frappe.utils import flt, add_days, nowdate, getdate -from erpnext.stock.doctype.item.test_item import make_item -from erpnext.buying.doctype.purchase_order.purchase_order \ - import (make_purchase_receipt, make_purchase_invoice as make_pi_from_po, make_rm_stock_entry as make_subcontract_transfer_entry) -from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_pi_from_pr -from erpnext.stock.doctype.material_request.test_material_request import make_material_request -from erpnext.stock.doctype.material_request.material_request import make_purchase_order -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry -from erpnext.controllers.accounts_controller import update_child_qty_rate -from erpnext.controllers.status_updater import OverAllowanceError -from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order -from erpnext.stock.doctype.batch.test_batch import make_new_batch +import json +import unittest + +import frappe +from frappe.utils import add_days, flt, getdate, nowdate + +from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry +from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_purchase_invoice as make_pi_from_po, +) +from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt +from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_rm_stock_entry as make_subcontract_transfer_entry, +) +from erpnext.controllers.accounts_controller import update_child_qty_rate +from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.material_request.material_request import make_purchase_order +from erpnext.stock.doctype.material_request.test_material_request import make_material_request +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + make_purchase_invoice as make_pi_from_pr, +) +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_receipt(self): @@ -415,10 +422,12 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEqual(po.get("items")[0].received_qty, 9) # Make return purchase receipt, purchase invoice and check quantity - from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ - import make_purchase_receipt as make_purchase_receipt_return - from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice \ - import make_purchase_invoice as make_purchase_invoice_return + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import ( + make_purchase_invoice as make_purchase_invoice_return, + ) + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import ( + make_purchase_receipt as make_purchase_receipt_return, + ) pr1 = make_purchase_receipt_return(is_return=1, return_against=pr.name, qty=-3, do_not_submit=True) pr1.items[0].purchase_order = po.name @@ -484,7 +493,9 @@ class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_invoice_with_terms(self): - from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + from erpnext.selling.doctype.sales_order.test_sales_order import ( + automatically_fetch_payment_terms, + ) automatically_fetch_payment_terms() po = create_purchase_order(do_not_save=True) @@ -977,9 +988,14 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEqual(po_doc.items[0].blanket_order, None) def test_payment_terms_are_fetched_when_creating_purchase_invoice(self): - from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.payment_entry.test_payment_entry import ( + create_payment_terms_template, + ) from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice - from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + from erpnext.selling.doctype.sales_order.test_sales_order import ( + automatically_fetch_payment_terms, + compare_payment_schedules, + ) automatically_fetch_payment_terms() diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 132dd1769c5..87cd57517e2 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -10,6 +10,7 @@ "item_code", "supplier_part_no", "item_name", + "product_bundle", "column_break_4", "schedule_date", "expected_delivery_date", @@ -488,7 +489,6 @@ "no_copy": 1, "options": "Sales Order", "print_hide": 1, - "read_only": 1, "search_index": 1 }, { @@ -830,13 +830,20 @@ "label": "Production Plan Sub Assembly Item", "no_copy": 1, "read_only": 1 + }, + { + "fieldname": "product_bundle", + "fieldtype": "Link", + "label": "Product Bundle", + "options": "Product Bundle", + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-28 19:22:22.715365", + "modified": "2021-08-30 20:06:26.712097", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py index b6e28b6c674..a391a3d0688 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe.model.document import Document + class PurchaseOrderItem(Document): pass diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py index c85ca2fbafc..909faeca6ad 100644 --- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py +++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseOrderItemSupplied(Document): pass diff --git a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py index 00c93ed1ea3..caec4e8b7aa 100644 --- a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py +++ b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseReceiptItemSupplied(Document): pass diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 8ed6c9e2a6d..af1a9a907a9 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -3,21 +3,24 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe import _ -from frappe.model.mapper import get_mapped_doc -from frappe.utils import get_url, cint -from frappe.utils.user import get_user_fullname -from frappe.utils.print_format import download_pdf -from frappe.desk.form.load import get_attachments -from frappe.core.doctype.communication.email import make -from erpnext.accounts.party import get_party_account_currency, get_party_details -from erpnext.stock.doctype.material_request.material_request import set_missing_values -from erpnext.controllers.buying_controller import BuyingController -from erpnext.buying.utils import validate_for_items +import json + +import frappe +from frappe import _ +from frappe.core.doctype.communication.email import make +from frappe.desk.form.load import get_attachments +from frappe.model.mapper import get_mapped_doc +from frappe.utils import get_url +from frappe.utils.print_format import download_pdf +from frappe.utils.user import get_user_fullname from six import string_types +from erpnext.accounts.party import get_party_account_currency, get_party_details +from erpnext.buying.utils import validate_for_items +from erpnext.controllers.buying_controller import BuyingController +from erpnext.stock.doctype.material_request.material_request import set_missing_values + STANDARD_USERS = ("Guest", "Administrator") class RequestforQuotation(BuyingController): diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation_dashboard.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation_dashboard.py index 751336dc4c6..0708cab30a1 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation_dashboard.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py index 36f87b0b841..33fde8e6dc8 100644 --- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py @@ -7,12 +7,16 @@ import unittest import frappe from frappe.utils import nowdate + +from erpnext.buying.doctype.request_for_quotation.request_for_quotation import ( + create_supplier_quotation, + make_supplier_quotation_from_rfq, +) +from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq +from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity from erpnext.stock.doctype.item.test_item import make_item from erpnext.templates.pages.rfq import check_supplier_has_docname_access -from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation_from_rfq -from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation -from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity -from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq + class TestRequestforQuotation(unittest.TestCase): def test_quote_status(self): diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py index cc897af944b..35f3305b8ef 100644 --- a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py +++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class RequestforQuotationItem(Document): pass diff --git a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py index 4b0bbbee8c2..47c0deb39f3 100644 --- a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py +++ b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class RequestforQuotationSupplier(Document): pass diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index c9750caa65a..2a9f784ec6e 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -2,13 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe import frappe.defaults -from frappe import msgprint, _ +from frappe import _, msgprint +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) from frappe.model.naming import set_name_by_naming_series -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address + +from erpnext.accounts.party import get_dashboard_info, validate_party_accounts from erpnext.utilities.transaction_base import TransactionBase -from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this class Supplier(TransactionBase): @@ -92,9 +97,10 @@ class Supplier(TransactionBase): self.db_set('email_id', self.email_id) def create_primary_address(self): - from erpnext.selling.doctype.customer.customer import make_address from frappe.contacts.doctype.address.address import get_address_display + from erpnext.selling.doctype.customer.customer import make_address + if self.flags.is_new_doc and self.get('address_line1'): address = make_address(self) address_display = get_address_display(address.name) diff --git a/erpnext/buying/doctype/supplier/test_supplier.py b/erpnext/buying/doctype/supplier/test_supplier.py index 89804662700..8a4eefa4fd3 100644 --- a/erpnext/buying/doctype/supplier/test_supplier.py +++ b/erpnext/buying/doctype/supplier/test_supplier.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals +import unittest + +import frappe +from frappe.test_runner import make_test_records -import frappe, unittest from erpnext.accounts.party import get_due_date from erpnext.exceptions import PartyDisabled -from frappe.test_runner import make_test_records test_dependencies = ['Payment Term', 'Payment Terms Template'] test_records = frappe.get_test_records('Supplier') diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py index 4473ddea28e..6d71f7d5160 100644 --- a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class SupplierItemGroup(Document): def validate(self): exists = frappe.db.exists({ diff --git a/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py b/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py index c75044d44eb..55ba85ef2d6 100644 --- a/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py +++ b/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestSupplierItemGroup(unittest.TestCase): pass diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 25e4e2a4dcf..af462fc6859 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -2,13 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, nowdate, add_days, getdate from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, getdate, nowdate -from erpnext.controllers.buying_controller import BuyingController from erpnext.buying.utils import validate_for_items +from erpnext.controllers.buying_controller import BuyingController form_grid_templates = { "items": "templates/form_grid/item_grid.html" diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py index 6b40305e01f..014b1025dd3 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'supplier_quotation', diff --git a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py index 6f34ca6c390..2db8e22f08b 100644 --- a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py @@ -3,9 +3,11 @@ from __future__ import unicode_literals + import unittest + import frappe -import frappe.defaults + class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_order(self): diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py index 64dda879450..03adab54626 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class SupplierQuotationItem(Document): pass diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py index e956afdf749..f944fe44665 100644 --- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py @@ -3,13 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import throw, _ -from frappe.model.document import Document + import time from datetime import timedelta -from frappe.utils import nowdate, get_last_day, getdate, add_days, add_years -from erpnext.buying.doctype.supplier_scorecard_period.supplier_scorecard_period import make_supplier_scorecard + +import frappe +from frappe import _, throw +from frappe.model.document import Document +from frappe.utils import add_days, add_years, get_last_day, getdate, nowdate + +from erpnext.buying.doctype.supplier_scorecard_period.supplier_scorecard_period import ( + make_supplier_scorecard, +) + class SupplierScorecard(Document): diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard_dashboard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard_dashboard.py index 8e5cce5696b..7186e01d084 100644 --- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard_dashboard.py +++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py index a5f05ea5258..ef7fae3f111 100644 --- a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestSupplierScorecard(unittest.TestCase): def test_create_scorecard(self): diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py index 33a0dc78377..c456377d9b7 100644 --- a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import re + import frappe from frappe import _ -import re from frappe.model.document import Document + class InvalidFormulaVariable(frappe.ValidationError): pass class SupplierScorecardCriteria(Document): diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py index 3babfc8cab3..9fca9a9f17a 100644 --- a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestSupplierScorecardCriteria(unittest.TestCase): def test_variables_exist(self): delete_test_scorecards() diff --git a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py index cc345e96bb8..b03d216ce23 100644 --- a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py +++ b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py @@ -3,12 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import throw, _ +from frappe import _, throw from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc + import erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable as variable_functions -from erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria import get_variables +from erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria import ( + get_variables, +) + class SupplierScorecardPeriod(Document): diff --git a/erpnext/buying/doctype/supplier_scorecard_period/test_supplier_scorecard_period.py b/erpnext/buying/doctype/supplier_scorecard_period/test_supplier_scorecard_period.py index 8baa3185ba7..de8bc0a0272 100644 --- a/erpnext/buying/doctype/supplier_scorecard_period/test_supplier_scorecard_period.py +++ b/erpnext/buying/doctype/supplier_scorecard_period/test_supplier_scorecard_period.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSupplierScorecardPeriod(unittest.TestCase): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py b/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py index b64abed8a67..79d5082ab6a 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SupplierScorecardScoringCriteria(Document): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py b/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py index e8ad79f33d3..5063b20ddbb 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SupplierScorecardScoringStanding(Document): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py b/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py index 58a8a99a09c..476cb35e8cd 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SupplierScorecardScoringVariable(Document): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py index 678855a457b..4fc45e89c7b 100644 --- a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py +++ b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class SupplierScorecardStanding(Document): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_standing/test_supplier_scorecard_standing.py b/erpnext/buying/doctype/supplier_scorecard_standing/test_supplier_scorecard_standing.py index 4d966513137..5ac5927d081 100644 --- a/erpnext/buying/doctype/supplier_scorecard_standing/test_supplier_scorecard_standing.py +++ b/erpnext/buying/doctype/supplier_scorecard_standing/test_supplier_scorecard_standing.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSupplierScorecardStanding(unittest.TestCase): pass diff --git a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py index 89a6459bbab..30b2a1893f1 100644 --- a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py +++ b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import sys + +import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import getdate + class VariablePathNotFound(frappe.ValidationError): pass class SupplierScorecardVariable(Document): @@ -18,7 +21,9 @@ class SupplierScorecardVariable(Document): def validate_path_exists(self): if '.' in self.path: try: - from erpnext.buying.doctype.supplier_scorecard_period.supplier_scorecard_period import import_string_path + from erpnext.buying.doctype.supplier_scorecard_period.supplier_scorecard_period import ( + import_string_path, + ) import_string_path(self.path) except AttributeError: frappe.throw(_("Could not find path for " + self.path), VariablePathNotFound) diff --git a/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py b/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py index 14b87105e66..990413cd404 100644 --- a/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py +++ b/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py @@ -3,10 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable import VariablePathNotFound +import frappe + +from erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable import ( + VariablePathNotFound, +) class TestSupplierScorecardVariable(unittest.TestCase): diff --git a/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json b/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json deleted file mode 100644 index ce3d8cfb7b2..00000000000 --- a/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "add_more_button": 1, - "app": "ERPNext", - "creation": "2019-11-15 14:45:32.626641", - "docstatus": 0, - "doctype": "Onboarding Slide", - "domains": [], - "help_links": [ - { - "label": "Learn More", - "video_id": "zsrrVDk6VBs" - } - ], - "idx": 0, - "image_src": "", - "is_completed": 0, - "max_count": 3, - "modified": "2019-12-09 17:54:18.452038", - "modified_by": "Administrator", - "name": "Add A Few Suppliers", - "owner": "Administrator", - "ref_doctype": "Supplier", - "slide_desc": "", - "slide_fields": [ - { - "align": "", - "fieldname": "supplier_name", - "fieldtype": "Data", - "label": "Supplier Name", - "placeholder": "", - "reqd": 1 - }, - { - "align": "", - "fieldtype": "Column Break", - "reqd": 0 - }, - { - "align": "", - "fieldname": "supplier_email", - "fieldtype": "Data", - "label": "Supplier Email", - "reqd": 1 - } - ], - "slide_order": 50, - "slide_title": "Add A Few Suppliers", - "slide_type": "Create" -} \ No newline at end of file diff --git a/erpnext/buying/report/procurement_tracker/procurement_tracker.py b/erpnext/buying/report/procurement_tracker/procurement_tracker.py index 99bcbe633cc..cb992342820 100644 --- a/erpnext/buying/report/procurement_tracker/procurement_tracker.py +++ b/erpnext/buying/report/procurement_tracker/procurement_tracker.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + def execute(filters=None): columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py index c36083f2aff..a5b09473a05 100644 --- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py +++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py @@ -2,15 +2,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + import unittest from datetime import datetime + import frappe -from erpnext.buying.report.procurement_tracker.procurement_tracker import execute -from erpnext.stock.doctype.material_request.test_material_request import make_material_request -from erpnext.stock.doctype.material_request.material_request import make_purchase_order + from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt +from erpnext.buying.report.procurement_tracker.procurement_tracker import execute +from erpnext.stock.doctype.material_request.material_request import make_purchase_order +from erpnext.stock.doctype.material_request.test_material_request import make_material_request from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + class TestProcurementTracker(unittest.TestCase): def test_result_for_procurement_tracker(self): filters = { diff --git a/erpnext/buying/report/purchase_analytics/purchase_analytics.py b/erpnext/buying/report/purchase_analytics/purchase_analytics.py index 0f949477b1c..bef66da4818 100644 --- a/erpnext/buying/report/purchase_analytics/purchase_analytics.py +++ b/erpnext/buying/report/purchase_analytics/purchase_analytics.py @@ -2,7 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from erpnext.selling.report.sales_analytics.sales_analytics import Analytics + def execute(filters=None): return Analytics(filters).run() diff --git a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py index bda172769a9..5d59456550b 100644 --- a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py +++ b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import copy + +import frappe from frappe import _ -from frappe.utils import flt, date_diff, getdate +from frappe.utils import date_diff, flt, getdate + def execute(filters=None): if not filters: diff --git a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py index 095a44319d6..9781480afa7 100644 --- a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py +++ b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe import _ -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py index faf67c9f7f3..42cc6ebc0a6 100644 --- a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py +++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import copy + +import frappe from frappe import _ -from frappe.utils import flt, date_diff, getdate +from frappe.utils import date_diff, flt, getdate + def execute(filters=None): if not filters: diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py index 9a45972837b..202d3641859 100644 --- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py +++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns, data = [], [] columns = get_columns() diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py index 2da53d726b7..9299cca0da4 100644 --- a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py +++ b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if filters.from_date >= filters.to_date: frappe.msgprint(_("To Date must be greater than From Date")) diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py index cb304a1fdab..7aeae451645 100644 --- a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py +++ b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py @@ -3,12 +3,18 @@ # Compiled at: 2019-05-06 09:51:46 # Decompiled by https://python-decompiler.com from __future__ import unicode_literals -from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order + +import unittest + +import frappe + from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.buying.report.subcontracted_item_to_be_received.subcontracted_item_to_be_received import ( + execute, +) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry -from erpnext.buying.report.subcontracted_item_to_be_received.subcontracted_item_to_be_received import execute -import frappe, unittest -from pprint import pprint + class TestSubcontractedItemToBeReceived(unittest.TestCase): diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py index 96cacb6f1b5..a8fad967d40 100644 --- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py +++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if filters.from_date >= filters.to_date: frappe.msgprint(_("To Date must be greater than From Date")) diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py index 2448e17c50f..dcdc5e36abe 100644 --- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py +++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py @@ -3,11 +3,19 @@ # Compiled at: 2019-05-06 10:24:35 # Decompiled by https://python-decompiler.com from __future__ import unicode_literals -from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order + +import json +import unittest + +import frappe + from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.buying.report.subcontracted_raw_materials_to_be_transferred.subcontracted_raw_materials_to_be_transferred import ( + execute, +) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry -from erpnext.buying.report.subcontracted_raw_materials_to_be_transferred.subcontracted_raw_materials_to_be_transferred import execute -import json, frappe, unittest + class TestSubcontractedItemToBeTransferred(unittest.TestCase): diff --git a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py index a5a3105a847..62b83ede04b 100644 --- a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py +++ b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py @@ -2,12 +2,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import flt, cint -from frappe import _ + from collections import defaultdict + +import frappe +from frappe import _ +from frappe.utils import cint, flt + from erpnext.setup.utils import get_exchange_rate + def execute(filters=None): if not filters: return [], [] diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index 17928634e78..81d995ce8de 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -2,13 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import flt, cstr, cint -from frappe import _ + import json -from erpnext.stock.doctype.item.item import get_last_purchase_details -from erpnext.stock.doctype.item.item import validate_end_of_life +import frappe +from frappe import _ +from frappe.utils import cint, cstr, flt + +from erpnext.stock.doctype.item.item import get_last_purchase_details, validate_end_of_life + def update_last_purchase_rate(doc, is_submit): """updates last_purchase_rate in item table for each item""" diff --git a/erpnext/commands/__init__.py b/erpnext/commands/__init__.py index 2276c738fbe..f3bf11ad652 100644 --- a/erpnext/commands/__init__.py +++ b/erpnext/commands/__init__.py @@ -1,10 +1,12 @@ # Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals, absolute_import, print_function +from __future__ import absolute_import, print_function, unicode_literals + import click import frappe -from frappe.commands import pass_context, get_site +from frappe.commands import get_site, pass_context + def call_command(cmd, context): return click.Context(cmd, obj=context).forward(cmd) diff --git a/erpnext/communication/doctype/communication_medium/communication_medium.py b/erpnext/communication/doctype/communication_medium/communication_medium.py index f233da07d5d..b15c3bed71b 100644 --- a/erpnext/communication/doctype/communication_medium/communication_medium.py +++ b/erpnext/communication/doctype/communication_medium/communication_medium.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class CommunicationMedium(Document): pass diff --git a/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py b/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py index d68d2d67a76..5189b09dc3e 100644 --- a/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py +++ b/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class CommunicationMediumTimeslot(Document): pass diff --git a/erpnext/config/education.py b/erpnext/config/education.py index 1c8ab10f537..ecd771f608c 100644 --- a/erpnext/config/education.py +++ b/erpnext/config/education.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return [ { diff --git a/erpnext/config/projects.py b/erpnext/config/projects.py index ab4db964772..d4d4a72a5d1 100644 --- a/erpnext/config/projects.py +++ b/erpnext/config/projects.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return [ { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index fbe060d67c2..feb88ff06e8 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2,27 +2,60 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + import json + +import frappe from frappe import _, throw -from frappe.utils import (today, flt, cint, fmt_money, formatdate, - getdate, add_days, add_months, get_last_day, nowdate, get_link_to_form) -from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied, WorkflowPermissionError -from erpnext.stock.get_item_details import get_conversion_factor, get_item_details -from erpnext.setup.utils import get_exchange_rate -from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency -from erpnext.utilities.transaction_base import TransactionBase -from erpnext.buying.utils import update_last_purchase_rate -from erpnext.controllers.sales_and_purchase_return import validate_return -from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled, get_party_account -from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction, - apply_pricing_rule_for_free_items, get_applied_pricing_rules) -from erpnext.exceptions import InvalidCurrency +from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied +from frappe.utils import ( + add_days, + add_months, + cint, + flt, + fmt_money, + formatdate, + get_last_day, + get_link_to_form, + getdate, + nowdate, + today, +) from six import text_type -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions -from erpnext.stock.get_item_details import get_item_warehouse, _get_item_tax_template, get_item_tax_map + +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) +from erpnext.accounts.doctype.pricing_rule.utils import ( + apply_pricing_rule_for_free_items, + apply_pricing_rule_on_transaction, + get_applied_pricing_rules, +) +from erpnext.accounts.party import ( + get_party_account, + get_party_account_currency, + validate_party_frozen_disabled, +) +from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year +from erpnext.buying.utils import update_last_purchase_rate +from erpnext.controllers.print_settings import ( + set_print_templates_for_item_table, + set_print_templates_for_taxes, +) +from erpnext.controllers.sales_and_purchase_return import validate_return +from erpnext.exceptions import InvalidCurrency +from erpnext.setup.utils import get_exchange_rate from erpnext.stock.doctype.packed_item.packed_item import make_packing_list -from erpnext.controllers.print_settings import set_print_templates_for_item_table, set_print_templates_for_taxes +from erpnext.stock.get_item_details import ( + _get_item_tax_template, + get_conversion_factor, + get_item_details, + get_item_tax_map, + get_item_warehouse, +) +from erpnext.utilities.transaction_base import TransactionBase + class AccountMissingError(frappe.ValidationError): pass @@ -1592,7 +1625,7 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field, def get_advance_payment_entries(party_type, party, party_account, order_doctype, - order_list=None, include_unallocated=True, against_all_orders=False, limit=None): + order_list=None, include_unallocated=True, against_all_orders=False, limit=None, condition=None): party_account_field = "paid_from" if party_type == "Customer" else "paid_to" currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency" payment_type = "Receive" if party_type == "Customer" else "Pay" @@ -1627,14 +1660,14 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype, if include_unallocated: unallocated_payment_entries = frappe.db.sql(""" - select "Payment Entry" as reference_type, name as reference_name, - remarks, unallocated_amount as amount, {2} as exchange_rate + select "Payment Entry" as reference_type, name as reference_name, posting_date, + remarks, unallocated_amount as amount, {2} as exchange_rate, {3} as currency from `tabPayment Entry` where {0} = %s and party_type = %s and party = %s and payment_type = %s - and docstatus = 1 and unallocated_amount > 0 + and docstatus = 1 and unallocated_amount > 0 {condition} order by posting_date {1} - """.format(party_account_field, limit_cond, exchange_rate_field), + """.format(party_account_field, limit_cond, exchange_rate_field, currency_field, condition=condition or ""), (party_account, party_type, party, payment_type), as_dict=1) return list(payment_entries_against_order) + list(unallocated_payment_entries) @@ -1816,7 +1849,12 @@ def validate_child_on_delete(row, parent): def update_bin_on_delete(row, doctype): """Update bin for deleted item (row).""" - from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty, get_ordered_qty, get_indented_qty + from erpnext.stock.stock_balance import ( + get_indented_qty, + get_ordered_qty, + get_reserved_qty, + update_bin_qty, + ) qty_dict = {} if doctype == "Sales Order": diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 974ade35849..e0b3ad801ec 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -2,24 +2,21 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _, msgprint -from frappe.utils import flt,cint, cstr, getdate -from six import iteritems -from collections import OrderedDict -from erpnext.accounts.party import get_party_details -from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.buying.utils import validate_for_items, update_last_purchase_rate -from erpnext.stock.stock_ledger import get_valuation_rate -from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos from frappe.contacts.doctype.address.address import get_address_display +from frappe.utils import cint, cstr, flt, getdate from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget +from erpnext.accounts.party import get_party_details +from erpnext.buying.utils import update_last_purchase_rate, validate_for_items from erpnext.controllers.sales_and_purchase_return import get_rate_for_return -from erpnext.stock.utils import get_incoming_rate - from erpnext.controllers.stock_controller import StockController from erpnext.controllers.subcontracting import Subcontracting +from erpnext.stock.get_item_details import get_conversion_factor +from erpnext.stock.utils import get_incoming_rate + class BuyingController(StockController, Subcontracting): diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 8c361a2e561..86ab20fafd3 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -2,13 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + +import copy +import json + import frappe from frappe import _ from frappe.utils import cstr, flt -import json, copy - from six import string_types + class ItemVariantExistsError(frappe.ValidationError): pass class InvalidItemAttributeValueError(frappe.ValidationError): pass class ItemTemplateCannotHaveStock(frappe.ValidationError): pass @@ -131,7 +134,7 @@ def find_variant(template, args, variant_item_code=None): conditions = " or ".join(conditions) - from erpnext.portal.product_configurator.utils import get_item_codes_by_attributes + from erpnext.e_commerce.variant_selector.utils import get_item_codes_by_attributes possible_variants = [i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code] for variant in possible_variants: @@ -261,9 +264,8 @@ def generate_keyed_value_combinations(args): def copy_attributes_to_variant(item, variant): # copy non no-copy fields - exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website", - "show_variant_in_website", "opening_stock", "variant_of", "valuation_rate", - "has_variants", "attributes"] + exclude_fields = ["naming_series", "item_code", "item_name", "published_in_website", + "opening_stock", "variant_of", "valuation_rate", "has_variants", "attributes"] if item.variant_based_on=='Manufacturer': # don't copy manufacturer values if based on part no diff --git a/erpnext/controllers/print_settings.py b/erpnext/controllers/print_settings.py index e08c400068b..f6e061bcdcf 100644 --- a/erpnext/controllers/print_settings.py +++ b/erpnext/controllers/print_settings.py @@ -2,8 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import cint + def set_print_templates_for_item_table(doc, settings): doc.print_templates = { diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 4b4c8befa53..aafaf5b9e08 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -2,14 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -import erpnext + import json -from frappe.desk.reportview import get_match_cond, get_filters_cond -from frappe.utils import nowdate, getdate from collections import defaultdict + +import frappe +from frappe.desk.reportview import get_filters_cond, get_match_cond +from frappe.utils import nowdate, unique + +import erpnext from erpnext.stock.get_item_details import _get_item_tax_template -from frappe.utils import unique + # searches for active employees @frappe.whitelist() @@ -517,7 +520,9 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def get_filtered_dimensions(doctype, txt, searchfield, start, page_len, filters): - from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import get_dimension_filter_map + from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import ( + get_dimension_filter_map, + ) dimension_filters = get_dimension_filter_map() dimension_filters = dimension_filters.get((filters.get('dimension'),filters.get('account'))) query_filters = [] @@ -692,7 +697,9 @@ def get_healthcare_service_units(doctype, txt, searchfield, start, page_len, fil company = frappe.db.escape(filters.get('company')), txt = frappe.db.escape('%{0}%'.format(txt))) if filters and filters.get('inpatient_record'): - from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit + from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import ( + get_current_healthcare_service_unit, + ) service_unit = get_current_healthcare_service_unit(filters.get('inpatient_record')) # if the patient is admitted, then appointments should be allowed against the admission service unit, diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 01486fcd65d..5f2fbeb0c93 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -2,11 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ from frappe.model.meta import get_field_precision +from frappe.utils import flt, format_datetime, get_datetime + +import erpnext from erpnext.stock.utils import get_incoming_rate -from frappe.utils import flt, get_datetime, format_datetime + class StockOverReturnError(frappe.ValidationError): pass @@ -63,7 +67,7 @@ def validate_returned_items(doc): if doc.doctype in ("Delivery Note", "Sales Invoice"): for d in frappe.db.sql("""select item_code, qty, serial_no, batch_no from `tabPacked Item` - where parent = %s""".format(doc.doctype), doc.return_against, as_dict=1): + where parent = %s""", doc.return_against, as_dict=1): valid_items = get_ref_item_dict(valid_items, d) already_returned_items = get_already_returned_items(doc) @@ -235,6 +239,7 @@ def get_returned_qty_map_for_row(row_name, doctype): def make_return_doc(doctype, source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos company = frappe.db.get_value("Delivery Note", source_name, "company") default_warehouse_for_sales_return = frappe.db.get_value("Company", company, "default_warehouse_for_sales_return") diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 844c40c8a64..0158a1120f9 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -2,18 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import cint, flt, cstr, get_link_to_form, nowtime -from frappe import _, bold, throw -from erpnext.stock.get_item_details import get_bin_details -from erpnext.stock.utils import get_incoming_rate -from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.stock.doctype.item.item import set_item_default -from frappe.contacts.doctype.address.address import get_address_display -from erpnext.controllers.accounts_controller import get_taxes_and_charges -from erpnext.controllers.stock_controller import StockController +import frappe +from frappe import _, bold, throw +from frappe.contacts.doctype.address.address import get_address_display +from frappe.utils import cint, cstr, flt, get_link_to_form, nowtime + +from erpnext.controllers.accounts_controller import get_taxes_and_charges from erpnext.controllers.sales_and_purchase_return import get_rate_for_return +from erpnext.controllers.stock_controller import StockController +from erpnext.stock.doctype.item.item import set_item_default +from erpnext.stock.get_item_details import get_bin_details, get_conversion_factor +from erpnext.stock.utils import get_incoming_rate + class SellingController(StockController): def get_feed(self): diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 7b24e50b143..8738204ce09 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt, comma_or, nowdate, getdate, now from frappe import _ from frappe.model.document import Document +from frappe.utils import comma_or, flt, getdate, now, nowdate + class OverAllowanceError(frappe.ValidationError): pass diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 17707ecae7f..78a6e52e4d7 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -5,12 +5,15 @@ import json from collections import defaultdict import frappe -import frappe.defaults from frappe import _ from frappe.utils import cint, cstr, flt, get_link_to_form, getdate import erpnext -from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries, process_gl_map +from erpnext.accounts.general_ledger import ( + make_gl_entries, + make_reverse_gl_entries, + process_gl_map, +) from erpnext.accounts.utils import get_fiscal_year from erpnext.controllers.accounts_controller import AccountsController from erpnext.stock import get_warehouse_account_map diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py index 969829f9651..3addb91aaa0 100644 --- a/erpnext/controllers/subcontracting.py +++ b/erpnext/controllers/subcontracting.py @@ -1,10 +1,13 @@ -import frappe import copy -from frappe import _ -from frappe.utils import flt, cint, get_link_to_form from collections import defaultdict + +import frappe +from frappe import _ +from frappe.utils import cint, flt, get_link_to_form + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + class Subcontracting(): def set_materials_for_subcontracted_items(self, raw_material_table): if self.doctype == 'Purchase Invoice' and not self.update_stock: diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 05edb2530c2..fbfdfdfac89 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -2,15 +2,23 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import json -import frappe, erpnext + +import frappe from frappe import _, scrub from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction -from erpnext.controllers.accounts_controller import validate_conversion_rate, \ - validate_taxes_and_charges, validate_inclusive_tax -from erpnext.stock.get_item_details import _get_item_tax_template -from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules + +import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate +from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules +from erpnext.controllers.accounts_controller import ( + validate_conversion_rate, + validate_inclusive_tax, + validate_taxes_and_charges, +) +from erpnext.stock.get_item_details import _get_item_tax_template + class calculate_taxes_and_totals(object): def __init__(self, doc): diff --git a/erpnext/controllers/tests/test_item_variant.py b/erpnext/controllers/tests/test_item_variant.py index 813f0a00758..b3633e6ff09 100644 --- a/erpnext/controllers/tests/test_item_variant.py +++ b/erpnext/controllers/tests/test_item_variant.py @@ -1,15 +1,18 @@ from __future__ import unicode_literals -import frappe import json import unittest -from erpnext.stock.doctype.item.test_item import set_item_variant_settings -from erpnext.controllers.item_variant import copy_attributes_to_variant, make_variant_item_code -from erpnext.stock.doctype.quality_inspection.test_quality_inspection import create_quality_inspection_parameter - +import frappe from six import string_types +from erpnext.controllers.item_variant import copy_attributes_to_variant, make_variant_item_code +from erpnext.stock.doctype.item.test_item import set_item_variant_settings +from erpnext.stock.doctype.quality_inspection.test_quality_inspection import ( + create_quality_inspection_parameter, +) + + class TestItemVariant(unittest.TestCase): def test_tables_in_template_copied_to_variant(self): fields = [{'field_name': 'quality_inspection_template'}] diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py index 7a4b2d36148..2d1ae43f074 100644 --- a/erpnext/controllers/tests/test_mapper.py +++ b/erpnext/controllers/tests/test_mapper.py @@ -1,12 +1,14 @@ from __future__ import unicode_literals -import unittest -import frappe -import random, json +import json +import unittest + +import frappe import frappe.utils -from frappe.utils import nowdate, add_months from frappe.model import mapper from frappe.test_runner import make_test_records +from frappe.utils import add_months, nowdate + class TestMapper(unittest.TestCase): def test_map_docs(self): diff --git a/erpnext/controllers/tests/test_qty_based_taxes.py b/erpnext/controllers/tests/test_qty_based_taxes.py index aaeac5d9399..41673d1e6fb 100644 --- a/erpnext/controllers/tests/test_qty_based_taxes.py +++ b/erpnext/controllers/tests/test_qty_based_taxes.py @@ -1,8 +1,11 @@ -from __future__ import unicode_literals, print_function +from __future__ import print_function, unicode_literals + import unittest -import frappe from uuid import uuid4 as _uuid4 +import frappe + + def uuid4(): return str(_uuid4()) diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 9b4b0eb9173..05d900d0f04 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import getdate from frappe import _ +from frappe.utils import getdate + def get_columns(filters, trans): validate_filters(filters) diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 7c072e4fad3..ff2ed45bd24 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import json + import frappe from frappe import _ from frappe.utils import flt, has_common from frappe.utils.user import is_website_user + def get_list_context(context=None): return { "global_number_format": frappe.db.get_default("number_format") or "#,###.##", diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index f7c6b6c7993..f2055349bd2 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -4,15 +4,13 @@ from __future__ import unicode_literals -import urllib from collections import Counter -from datetime import timedelta import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import get_url, getdate -from frappe.utils.verified_command import verify_request, get_signed_params +from frappe.utils.verified_command import get_signed_params class Appointment(Document): diff --git a/erpnext/crm/doctype/appointment/test_appointment.py b/erpnext/crm/doctype/appointment/test_appointment.py index 50c98c59de6..8c4924f696c 100644 --- a/erpnext/crm/doctype/appointment/test_appointment.py +++ b/erpnext/crm/doctype/appointment/test_appointment.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest import datetime +import unittest + +import frappe def create_test_lead(): diff --git a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py index 27f14b1dbd8..7e1da677312 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py +++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import datetime + import frappe from frappe import _ -import datetime from frappe.model.document import Document @@ -28,10 +30,10 @@ class AppointmentBookingSettings(Document): to_time = datetime.datetime.strptime( self.min_date+record.to_time, self.format_string) timedelta = to_time-from_time - self.validate_from_and_to_time(from_time, to_time) + self.validate_from_and_to_time(from_time, to_time, record) self.duration_is_divisible(from_time, to_time) - def validate_from_and_to_time(self, from_time, to_time): + def validate_from_and_to_time(self, from_time, to_time, record): if from_time > to_time: err_msg = _('From Time cannot be later than To Time for {0}').format(record.day_of_week) frappe.throw(_(err_msg)) diff --git a/erpnext/crm/doctype/appointment_booking_settings/test_appointment_booking_settings.py b/erpnext/crm/doctype/appointment_booking_settings/test_appointment_booking_settings.py index 3dc3c399712..5c5432c5246 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/test_appointment_booking_settings.py +++ b/erpnext/crm/doctype/appointment_booking_settings/test_appointment_booking_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestAppointmentBookingSettings(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py b/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py index 3cadbc95590..4741c8af5a1 100644 --- a/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py +++ b/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AppointmentBookingSlots(Document): pass diff --git a/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py b/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py index 8258471eed1..e33d87b1939 100644 --- a/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py +++ b/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AvailabilityOfSlots(Document): pass diff --git a/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py b/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py index 8445b8a397e..f053e6e7e4f 100644 --- a/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py +++ b/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class CampaignEmailSchedule(Document): pass diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py index c39397bf4b4..9654613f041 100644 --- a/erpnext/crm/doctype/contract/contract.py +++ b/erpnext/crm/doctype/contract/contract.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import getdate, now_datetime, nowdate +from frappe.utils import getdate, nowdate class Contract(Document): diff --git a/erpnext/crm/doctype/contract/test_contract.py b/erpnext/crm/doctype/contract/test_contract.py index d5f4e71bffa..87716368177 100644 --- a/erpnext/crm/doctype/contract/test_contract.py +++ b/erpnext/crm/doctype/contract/test_contract.py @@ -8,6 +8,7 @@ import unittest import frappe from frappe.utils import add_days, nowdate + class TestContract(unittest.TestCase): def setUp(self): diff --git a/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py b/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py index 60390357277..ae56f93fc84 100644 --- a/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py +++ b/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ContractFulfilmentChecklist(Document): pass diff --git a/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.py b/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.py index c78796be6bd..82e7ad35c9e 100644 --- a/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.py +++ b/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestContractFulfilmentChecklist(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/contract_template/contract_template.py b/erpnext/crm/doctype/contract_template/contract_template.py index 9281220eef4..fc1845c372d 100644 --- a/erpnext/crm/doctype/contract_template/contract_template.py +++ b/erpnext/crm/doctype/contract_template/contract_template.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import json + import frappe from frappe.model.document import Document from frappe.utils.jinja import validate_template from six import string_types -import json + class ContractTemplate(Document): def validate(self): diff --git a/erpnext/crm/doctype/contract_template/test_contract_template.py b/erpnext/crm/doctype/contract_template/test_contract_template.py index b2b0db66a59..50655054c85 100644 --- a/erpnext/crm/doctype/contract_template/test_contract_template.py +++ b/erpnext/crm/doctype/contract_template/test_contract_template.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestContractTemplate(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py b/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py index 767b1901ab9..28f844d0970 100644 --- a/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py +++ b/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ContractTemplateFulfilmentTerms(Document): pass diff --git a/erpnext/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py index 71c93e8d393..4b74f25ead7 100644 --- a/erpnext/crm/doctype/email_campaign/email_campaign.py +++ b/erpnext/crm/doctype/email_campaign/email_campaign.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate, add_days, today, nowdate, cstr -from frappe.model.document import Document from frappe.core.doctype.communication.email import make +from frappe.model.document import Document +from frappe.utils import add_days, getdate, today + class EmailCampaign(Document): def validate(self): diff --git a/erpnext/crm/doctype/email_campaign/test_email_campaign.py b/erpnext/crm/doctype/email_campaign/test_email_campaign.py index f5eab483330..f68b8c6d290 100644 --- a/erpnext/crm/doctype/email_campaign/test_email_campaign.py +++ b/erpnext/crm/doctype/email_campaign/test_email_campaign.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestEmailCampaign(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index ce3de40fc3d..9a5ef496bb9 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -4,13 +4,23 @@ from __future__ import unicode_literals import frappe -from erpnext.accounts.party import set_taxes -from erpnext.controllers.selling_controller import SellingController from frappe import _ from frappe.contacts.address_and_contact import load_address_and_contact from frappe.email.inbox import link_communication_to_document from frappe.model.mapper import get_mapped_doc -from frappe.utils import cint, comma_and, cstr, getdate, has_gravatar, nowdate, validate_email_address +from frappe.utils import ( + cint, + comma_and, + cstr, + getdate, + has_gravatar, + nowdate, + validate_email_address, +) + +from erpnext.accounts.party import set_taxes +from erpnext.controllers.selling_controller import SellingController + class Lead(SellingController): def get_feed(self): @@ -157,6 +167,7 @@ class Lead(SellingController): "salutation": self.salutation, "gender": self.gender, "designation": self.designation, + "company_name": self.company_name, }) if self.email_id: diff --git a/erpnext/crm/doctype/lead/lead_dashboard.py b/erpnext/crm/doctype/lead/lead_dashboard.py index 3950d063f22..fa351c70779 100644 --- a/erpnext/crm/doctype/lead/lead_dashboard.py +++ b/erpnext/crm/doctype/lead/lead_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index d428a453f9f..3655c97f368 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -3,9 +3,10 @@ from __future__ import unicode_literals -import frappe import unittest +import frappe + test_records = frappe.get_test_records('Lead') class TestLead(unittest.TestCase): diff --git a/erpnext/crm/doctype/lead_source/lead_source.py b/erpnext/crm/doctype/lead_source/lead_source.py index 5c64fb8b4ad..8de1c4301b1 100644 --- a/erpnext/crm/doctype/lead_source/lead_source.py +++ b/erpnext/crm/doctype/lead_source/lead_source.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class LeadSource(Document): pass diff --git a/erpnext/crm/doctype/lead_source/test_lead_source.py b/erpnext/crm/doctype/lead_source/test_lead_source.py index b5bc6490cf9..ecf61171e99 100644 --- a/erpnext/crm/doctype/lead_source/test_lead_source.py +++ b/erpnext/crm/doctype/lead_source/test_lead_source.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLeadSource(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py index 9b88d78c1ff..03c9d9c762c 100644 --- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py +++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py @@ -3,14 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe import requests from frappe import _ -from frappe.utils import get_url_to_form from frappe.model.document import Document +from frappe.utils import get_url_to_form from frappe.utils.file_manager import get_file_path from six.moves.urllib.parse import urlencode + class LinkedInSettings(Document): @frappe.whitelist() def get_authorization_url(self): @@ -146,7 +148,7 @@ class LinkedInSettings(Document): except Exception as e: self.api_error(response) - + return response def get_headers(self): @@ -168,7 +170,7 @@ class LinkedInSettings(Document): raise except Exception: self.api_error(response) - + def get_post(self, post_id): url = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:{0}&shares[0]=urn:li:share:{1}".format(self.company_id, post_id) @@ -176,7 +178,7 @@ class LinkedInSettings(Document): response = requests.get(url=url, headers=self.get_headers()) if response.status_code !=200: raise - + except Exception: self.api_error(response) diff --git a/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py index 9c3ef3f32f0..1d86f0c66fe 100644 --- a/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py +++ b/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLinkedInSettings(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py b/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py index 3baa011e64d..88abd423cfa 100644 --- a/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py +++ b/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class LostReasonDetail(Document): pass diff --git a/erpnext/crm/doctype/market_segment/market_segment.py b/erpnext/crm/doctype/market_segment/market_segment.py index 830ea693437..92adf56876c 100644 --- a/erpnext/crm/doctype/market_segment/market_segment.py +++ b/erpnext/crm/doctype/market_segment/market_segment.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MarketSegment(Document): pass diff --git a/erpnext/crm/doctype/market_segment/test_market_segment.py b/erpnext/crm/doctype/market_segment/test_market_segment.py index 2f9ed34f7c4..b95cc4cde0d 100644 --- a/erpnext/crm/doctype/market_segment/test_market_segment.py +++ b/erpnext/crm/doctype/market_segment/test_market_segment.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestMarketSegment(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index a74a94afd68..0b3f50897ab 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -2,14 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import cstr, cint, get_fullname -from frappe import msgprint, _ + +import json + +import frappe +from frappe import _ +from frappe.email.inbox import link_communication_to_document from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, cstr, get_fullname + +from erpnext.accounts.party import get_party_account_currency from erpnext.setup.utils import get_exchange_rate from erpnext.utilities.transaction_base import TransactionBase -from erpnext.accounts.party import get_party_account_currency -from frappe.email.inbox import link_communication_to_document + class Opportunity(TransactionBase): def after_insert(self): diff --git a/erpnext/crm/doctype/opportunity/opportunity_dashboard.py b/erpnext/crm/doctype/opportunity/opportunity_dashboard.py index b8c53f077ae..693a86cfcdf 100644 --- a/erpnext/crm/doctype/opportunity/opportunity_dashboard.py +++ b/erpnext/crm/doctype/opportunity/opportunity_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index 52aa0b036ae..347bf6366d2 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -2,11 +2,13 @@ # See license.txt from __future__ import unicode_literals +import unittest + import frappe -from frappe.utils import today, random_string +from frappe.utils import random_string, today + from erpnext.crm.doctype.lead.lead import make_customer from erpnext.crm.doctype.opportunity.opportunity import make_quotation -import unittest test_records = frappe.get_test_records('Opportunity') diff --git a/erpnext/crm/doctype/opportunity_item/opportunity_item.py b/erpnext/crm/doctype/opportunity_item/opportunity_item.py index 7a5ed63f883..225cfe9d324 100644 --- a/erpnext/crm/doctype/opportunity_item/opportunity_item.py +++ b/erpnext/crm/doctype/opportunity_item/opportunity_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class OpportunityItem(Document): pass diff --git a/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py b/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py index 48b63b091e2..b25f02afffd 100644 --- a/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py +++ b/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class OpportunityLostReason(Document): pass diff --git a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py index 8723f1d0457..4bb5c54b1d9 100644 --- a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py +++ b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class OpportunityLostReasonDetail(Document): pass diff --git a/erpnext/crm/doctype/opportunity_type/opportunity_type.py b/erpnext/crm/doctype/opportunity_type/opportunity_type.py index 48abac3fe29..5b64e980965 100644 --- a/erpnext/crm/doctype/opportunity_type/opportunity_type.py +++ b/erpnext/crm/doctype/opportunity_type/opportunity_type.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class OpportunityType(Document): pass diff --git a/erpnext/crm/doctype/opportunity_type/test_opportunity_type.py b/erpnext/crm/doctype/opportunity_type/test_opportunity_type.py index 6410bbc3401..f86a70e8cfa 100644 --- a/erpnext/crm/doctype/opportunity_type/test_opportunity_type.py +++ b/erpnext/crm/doctype/opportunity_type/test_opportunity_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestOpportunityType(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/sales_stage/sales_stage.py b/erpnext/crm/doctype/sales_stage/sales_stage.py index a80f4cc0894..e9e176f0871 100644 --- a/erpnext/crm/doctype/sales_stage/sales_stage.py +++ b/erpnext/crm/doctype/sales_stage/sales_stage.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SalesStage(Document): pass diff --git a/erpnext/crm/doctype/sales_stage/test_sales_stage.py b/erpnext/crm/doctype/sales_stage/test_sales_stage.py index 80b65130e67..83d1f269fd7 100644 --- a/erpnext/crm/doctype/sales_stage/test_sales_stage.py +++ b/erpnext/crm/doctype/sales_stage/test_sales_stage.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestSalesStage(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js index a8f5deea535..6874caac71f 100644 --- a/erpnext/crm/doctype/social_media_post/social_media_post.js +++ b/erpnext/crm/doctype/social_media_post/social_media_post.js @@ -80,10 +80,10 @@ frappe.ui.form.on('Social Media Post', { refresh: function(frm) { frm.trigger('text'); - + if (frm.doc.docstatus === 1) { if (!['Posted', 'Deleted'].includes(frm.doc.post_status)) { - frm.trigger('add_post_btn'); + frm.trigger('add_post_btn'); } if (frm.doc.post_status !='Deleted') { frm.add_custom_button(('Delete Post'), function() { diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.py b/erpnext/crm/doctype/social_media_post/social_media_post.py index 95320bff535..14d4521e1e6 100644 --- a/erpnext/crm/doctype/social_media_post/social_media_post.py +++ b/erpnext/crm/doctype/social_media_post/social_media_post.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document -from frappe import _ + import datetime +import frappe +from frappe import _ +from frappe.model.document import Document + + class SocialMediaPost(Document): def validate(self): if (not self.twitter and not self.linkedin): @@ -26,7 +29,7 @@ class SocialMediaPost(Document): if self.scheduled_time: self.post_status = "Scheduled" super(SocialMediaPost, self).submit() - + def on_cancel(self): self.db_set('post_status', 'Cancelled') @@ -35,11 +38,11 @@ class SocialMediaPost(Document): if self.twitter and self.twitter_post_id: twitter = frappe.get_doc("Twitter Settings") twitter.delete_tweet(self.twitter_post_id) - + if self.linkedin and self.linkedin_post_id: linkedin = frappe.get_doc("LinkedIn Settings") linkedin.delete_post(self.linkedin_post_id) - + self.db_set('post_status', 'Deleted') @frappe.whitelist() @@ -51,7 +54,7 @@ class SocialMediaPost(Document): if self.twitter and self.twitter_post_id: twitter = frappe.get_doc("Twitter Settings") response['twitter'] = twitter.get_tweet(self.twitter_post_id) - + return response @frappe.whitelist() @@ -67,7 +70,7 @@ class SocialMediaPost(Document): self.db_set("linkedin_post_id", linkedin_post.headers['X-RestLi-Id']) self.db_set("post_status", "Posted") - except: + except Exception: self.db_set("post_status", "Error") title = _("Error while POSTING {0}").format(self.name) frappe.log_error(message=frappe.get_traceback(), title=title) diff --git a/erpnext/crm/doctype/social_media_post/test_social_media_post.py b/erpnext/crm/doctype/social_media_post/test_social_media_post.py index ec81ee58710..c2d041898aa 100644 --- a/erpnext/crm/doctype/social_media_post/test_social_media_post.py +++ b/erpnext/crm/doctype/social_media_post/test_social_media_post.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestSocialMediaPost(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py b/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py index 3f999c1af4b..ff3163c559b 100644 --- a/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py +++ b/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestTwitterSettings(unittest.TestCase): pass diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.py b/erpnext/crm/doctype/twitter_settings/twitter_settings.py index 47756560ec5..0205cca2b92 100644 --- a/erpnext/crm/doctype/twitter_settings/twitter_settings.py +++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.py @@ -3,13 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, os, tweepy, json + +import json + +import frappe +import tweepy from frappe import _ from frappe.model.document import Document +from frappe.utils import get_url_to_form from frappe.utils.file_manager import get_file_path -from frappe.utils import get_url_to_form, get_link_to_form from tweepy.error import TweepError + class TwitterSettings(Document): @frappe.whitelist() def get_authorize_url(self): @@ -53,10 +58,10 @@ class TwitterSettings(Document): frappe.throw(_('Invalid Consumer Key or Consumer Secret Key')) def get_api(self): - # authentication of consumer key and secret - auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret")) - # authentication of access token and secret - auth.set_access_token(self.access_token, self.access_token_secret) + # authentication of consumer key and secret + auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret")) + # authentication of access token and secret + auth.set_access_token(self.access_token, self.access_token_secret) return tweepy.API(auth) @@ -90,20 +95,20 @@ class TwitterSettings(Document): def delete_tweet(self, tweet_id): api = self.get_api() - try: + try: api.destroy_status(tweet_id) except TweepError as e: self.api_error(e) def get_tweet(self, tweet_id): api = self.get_api() - try: + try: response = api.get_status(tweet_id, trim_user=True, include_entities=True) except TweepError as e: self.api_error(e) - + return response._json - + def api_error(self, e): content = json.loads(e.response.content) content = content["errors"][0] diff --git a/erpnext/crm/doctype/utils.py b/erpnext/crm/doctype/utils.py index f244daffea3..0da0e0e71af 100644 --- a/erpnext/crm/doctype/utils.py +++ b/erpnext/crm/doctype/utils.py @@ -1,6 +1,6 @@ + import frappe -from frappe import _ -import json + @frappe.whitelist() def get_last_interaction(contact=None, lead=None): diff --git a/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py b/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py index 238884b5190..87f516b8c72 100644 --- a/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py +++ b/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + def execute(filters=None): columns, data = [], [] columns=get_columns("Campaign Name") diff --git a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py index 2ffbc3e62ac..df57893ef49 100644 --- a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py +++ b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe + def execute(filters=None): columns = [ { diff --git a/erpnext/crm/report/lead_conversion_time/lead_conversion_time.py b/erpnext/crm/report/lead_conversion_time/lead_conversion_time.py index e66bc1ec8e3..71efdb96e75 100644 --- a/erpnext/crm/report/lead_conversion_time/lead_conversion_time.py +++ b/erpnext/crm/report/lead_conversion_time/lead_conversion_time.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _, msgprint from frappe.utils import date_diff, flt + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/crm/report/lead_details/lead_details.py b/erpnext/crm/report/lead_details/lead_details.py index 072a47611b7..11e82764278 100644 --- a/erpnext/crm/report/lead_details/lead_details.py +++ b/erpnext/crm/report/lead_details/lead_details.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe import _ + import frappe +from frappe import _ + def execute(filters=None): columns, data = get_columns(), get_data(filters) diff --git a/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py b/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py index 8fe16a2f4ce..5406eba6d8e 100644 --- a/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py +++ b/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe import _ + from erpnext.crm.report.campaign_efficiency.campaign_efficiency import get_lead_data + def execute(filters=None): columns, data = [], [] columns=get_columns() diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.py b/erpnext/crm/report/lost_opportunity/lost_opportunity.py index 858dcc4da81..b308ceb272d 100644 --- a/erpnext/crm/report/lost_opportunity/lost_opportunity.py +++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe import _ + import frappe +from frappe import _ + def execute(filters=None): columns, data = get_columns(), get_data(filters) diff --git a/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py b/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py index 425b7a8fdd7..4a16f3d5396 100644 --- a/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py +++ b/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import add_days, now + def execute(filters=None): columns, data = [], [] set_defaut_value_for_filters(filters) diff --git a/erpnext/demo/data/drug_list.json b/erpnext/demo/data/drug_list.json index e91c30d199a..c7c06c946de 100644 --- a/erpnext/demo/data/drug_list.json +++ b/erpnext/demo/data/drug_list.json @@ -54,7 +54,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -138,7 +137,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -220,7 +218,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -302,7 +299,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -384,7 +380,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -466,7 +461,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -548,7 +542,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -630,7 +623,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -712,7 +704,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -794,7 +785,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -876,7 +866,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -958,7 +947,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1040,7 +1028,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1122,7 +1109,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1204,7 +1190,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1286,7 +1271,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1368,7 +1352,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1450,7 +1433,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1532,7 +1514,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1614,7 +1595,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1696,7 +1676,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1778,7 +1757,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1860,7 +1838,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -1942,7 +1919,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2024,7 +2000,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2106,7 +2081,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2188,7 +2162,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2270,7 +2243,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2352,7 +2324,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2434,7 +2405,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2516,7 +2486,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2598,7 +2567,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2680,7 +2648,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2762,7 +2729,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2844,7 +2810,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -2926,7 +2891,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3008,7 +2972,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3092,7 +3055,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3174,7 +3136,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3256,7 +3217,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3338,7 +3298,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3420,7 +3379,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3502,7 +3460,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3584,7 +3541,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3666,7 +3622,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3748,7 +3703,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3830,7 +3784,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3912,7 +3865,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -3994,7 +3946,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4076,7 +4027,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4158,7 +4108,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4240,7 +4189,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4322,7 +4270,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4404,7 +4351,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4486,7 +4432,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4568,7 +4513,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4650,7 +4594,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4732,7 +4675,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4814,7 +4756,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4896,7 +4837,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -4978,7 +4918,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -5060,7 +4999,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, @@ -5142,7 +5080,6 @@ "safety_stock": 0.0, "selling_cost_center": null, "serial_no_series": null, - "show_in_website": 0, "show_variant_in_website": 0, "slideshow": null, "standard_rate": 0.0, diff --git a/erpnext/demo/demo.py b/erpnext/demo/demo.py index e89b6895a08..5be24206ca0 100644 --- a/erpnext/demo/demo.py +++ b/erpnext/demo/demo.py @@ -1,11 +1,16 @@ from __future__ import unicode_literals -import frappe, sys -import erpnext +import sys + +import frappe import frappe.utils -from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset + +import erpnext +from erpnext.demo.setup import education, healthcare, manufacture, retail, setup_data +from erpnext.demo.user import accounts from erpnext.demo.user import education as edu -from erpnext.demo.setup import education, manufacture, setup_data, healthcare, retail +from erpnext.demo.user import fixed_asset, hr, manufacturing, projects, purchase, sales, stock + """ Make a demo @@ -88,7 +93,7 @@ def simulate(domain='Manufacturing', days=100): elif domain=='Education': edu.work() - except: + except Exception: frappe.db.set_global('demo_last_date', current_date) raise finally: diff --git a/erpnext/demo/setup/education.py b/erpnext/demo/setup/education.py index cf9451d5dae..304bc3d2c3c 100644 --- a/erpnext/demo/setup/education.py +++ b/erpnext/demo/setup/education.py @@ -2,11 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils.make_random import get_random -from datetime import datetime -from erpnext.demo.setup.setup_data import import_json +import json import random +from datetime import datetime + +import frappe +from frappe.utils.make_random import get_random + +from erpnext.demo.setup.setup_data import import_json + def setup_data(): frappe.flags.mute_emails = True diff --git a/erpnext/demo/setup/healthcare.py b/erpnext/demo/setup/healthcare.py index aa389e56b41..5d5707f6470 100644 --- a/erpnext/demo/setup/healthcare.py +++ b/erpnext/demo/setup/healthcare.py @@ -2,13 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils.make_random import get_random import datetime -from erpnext.demo.setup.setup_data import import_json +import json + +import frappe from frappe.utils import getdate +from frappe.utils.make_random import get_random + +from erpnext.demo.setup.setup_data import import_json from erpnext.healthcare.doctype.lab_test.lab_test import create_test_from_template + def setup_data(): frappe.flags.mute_emails = True make_masters() diff --git a/erpnext/demo/setup/manufacture.py b/erpnext/demo/setup/manufacture.py index 7d6b5012ea6..5db3519c2ce 100644 --- a/erpnext/demo/setup/manufacture.py +++ b/erpnext/demo/setup/manufacture.py @@ -1,13 +1,16 @@ from __future__ import unicode_literals -import random, json -import frappe -from frappe.utils import nowdate, add_days -from erpnext.demo.setup.setup_data import import_json -from erpnext.demo.domains import data +import json +import random +import frappe +from frappe.utils import add_days, nowdate from six import iteritems +from erpnext.demo.domains import data +from erpnext.demo.setup.setup_data import import_json + + def setup_data(): import_json("Location") import_json("Asset Category") diff --git a/erpnext/demo/setup/retail.py b/erpnext/demo/setup/retail.py index 82d1c15ea3e..d94d2d6763a 100644 --- a/erpnext/demo/setup/retail.py +++ b/erpnext/demo/setup/retail.py @@ -1,12 +1,12 @@ from __future__ import unicode_literals -import random, json +import json + import frappe -from frappe.utils import nowdate, add_days -from erpnext.demo.setup.setup_data import import_json +from six import iteritems + from erpnext.demo.domains import data -from six import iteritems def setup_data(): setup_item() diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py index 05ee28a24a4..42f83a3b4e8 100644 --- a/erpnext/demo/setup/setup_data.py +++ b/erpnext/demo/setup/setup_data.py @@ -1,13 +1,18 @@ from __future__ import print_function, unicode_literals -import random, json -import frappe, erpnext -from frappe.utils.nestedset import get_root_of -from frappe.utils import flt, now_datetime, cstr, random_string -from frappe.utils.make_random import add_random_children, get_random -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields -from erpnext.demo.domains import data +import json +import random + +import frappe from frappe import _ +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from frappe.utils import cstr, flt, now_datetime, random_string +from frappe.utils.make_random import add_random_children, get_random +from frappe.utils.nestedset import get_root_of + +import erpnext +from erpnext.demo.domains import data + def setup(domain): frappe.flags.in_demo = 1 diff --git a/erpnext/demo/user/accounts.py b/erpnext/demo/user/accounts.py index 7fab7722358..2a248244850 100644 --- a/erpnext/demo/user/accounts.py +++ b/erpnext/demo/user/accounts.py @@ -4,19 +4,25 @@ from __future__ import unicode_literals -import erpnext -import frappe import random -from frappe.utils import random_string + +import frappe from frappe.desk import query_report +from frappe.utils import random_string +from frappe.utils.make_random import get_random + +import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry -from frappe.utils.make_random import get_random -from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request, make_payment_entry +from erpnext.accounts.doctype.payment_request.payment_request import ( + make_payment_entry, + make_payment_request, +) from erpnext.demo.user.sales import make_sales_order from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice + def work(): frappe.set_user(frappe.db.get_global('demo_accounts_user')) diff --git a/erpnext/demo/user/education.py b/erpnext/demo/user/education.py index 883a6d88cf2..adc0463a7ff 100644 --- a/erpnext/demo/user/education.py +++ b/erpnext/demo/user/education.py @@ -4,13 +4,21 @@ from __future__ import unicode_literals -import frappe import random +from datetime import timedelta + +import frappe from frappe.utils import cstr from frappe.utils.make_random import get_random -from datetime import timedelta -from erpnext.education.api import get_student_group_students, make_attendance_records, enroll_student, \ - get_fee_schedule, collect_fees, get_course + +from erpnext.education.api import ( + collect_fees, + enroll_student, + get_course, + get_fee_schedule, + get_student_group_students, + make_attendance_records, +) def work(): diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py index dc094e1c918..ec0e4c818ba 100644 --- a/erpnext/demo/user/fixed_asset.py +++ b/erpnext/demo/user/fixed_asset.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.utils.make_random import get_random + from erpnext.assets.doctype.asset.asset import make_sales_invoice from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py index 0211bc8a90a..17d5829f908 100644 --- a/erpnext/demo/user/hr.py +++ b/erpnext/demo/user/hr.py @@ -1,15 +1,23 @@ from __future__ import unicode_literals -import frappe, erpnext -import random + import datetime -from frappe.utils import random_string, add_days, get_last_day, getdate +import random + +import frappe +from frappe.utils import add_days, get_last_day, getdate, random_string +from frappe.utils.make_random import get_random + +import erpnext +from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry +from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account +from erpnext.hr.doctype.leave_application.leave_application import ( + AttendanceAlreadyMarkedError, + OverlapError, + get_leave_balance_on, +) from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice -from frappe.utils.make_random import get_random -from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account -from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry -from erpnext.hr.doctype.leave_application.leave_application import (get_leave_balance_on, - OverlapError, AttendanceAlreadyMarkedError) + def work(): frappe.set_user(frappe.db.get_global('demo_hr_user')) diff --git a/erpnext/demo/user/manufacturing.py b/erpnext/demo/user/manufacturing.py index bece0798faa..6e01f0f5a67 100644 --- a/erpnext/demo/user/manufacturing.py +++ b/erpnext/demo/user/manufacturing.py @@ -3,21 +3,23 @@ from __future__ import unicode_literals -import frappe, random, erpnext +import random from datetime import timedelta -from frappe.utils.make_random import how_many + +import frappe from frappe.desk import query_report -from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError +from frappe.utils.make_random import how_many + +import erpnext from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record + def work(): if random.random() < 0.3: return frappe.set_user(frappe.db.get_global('demo_manufacturing_user')) if not frappe.get_all('Sales Order'): return - from erpnext.projects.doctype.timesheet.timesheet import OverlapError - ppt = frappe.new_doc("Production Plan") ppt.company = erpnext.get_default_company() # ppt.use_multi_level_bom = 1 #refactored @@ -68,9 +70,12 @@ def work(): def make_stock_entry_from_pro(pro_id, purpose): from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry + from erpnext.stock.doctype.stock_entry.stock_entry import ( + DuplicateEntryForWorkOrderError, + IncorrectValuationRateError, + OperationsNotCompleteError, + ) from erpnext.stock.stock_ledger import NegativeStockError - from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \ - DuplicateEntryForWorkOrderError, OperationsNotCompleteError try: st = frappe.get_doc(make_stock_entry(pro_id, purpose)) diff --git a/erpnext/demo/user/projects.py b/erpnext/demo/user/projects.py index 044e2967fde..b6b99de532d 100644 --- a/erpnext/demo/user/projects.py +++ b/erpnext/demo/user/projects.py @@ -3,11 +3,14 @@ from __future__ import unicode_literals -import frappe, erpnext +import frappe from frappe.utils import flt from frappe.utils.make_random import get_random -from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet + +import erpnext from erpnext.demo.user.hr import make_sales_invoice_for_timesheet +from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet + def run_projects(current_date): frappe.set_user(frappe.db.get_global('demo_projects_user')) diff --git a/erpnext/demo/user/purchase.py b/erpnext/demo/user/purchase.py index b7aca79cf9b..ec32f973dae 100644 --- a/erpnext/demo/user/purchase.py +++ b/erpnext/demo/user/purchase.py @@ -3,15 +3,22 @@ from __future__ import unicode_literals -import frappe, random, json, erpnext -from frappe.utils.make_random import how_many, get_random +import json +import random + +import frappe from frappe.desk import query_report -from erpnext.setup.utils import get_exchange_rate +from frappe.utils.make_random import get_random, how_many + +import erpnext from erpnext.accounts.party import get_party_account_currency +from erpnext.buying.doctype.request_for_quotation.request_for_quotation import ( + make_supplier_quotation_from_rfq, +) from erpnext.exceptions import InvalidCurrency +from erpnext.setup.utils import get_exchange_rate from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation -from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \ - make_supplier_quotation_from_rfq + def work(): frappe.set_user(frappe.db.get_global('demo_purchase_user')) diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py index 8d5ba28b79a..95494ee3242 100644 --- a/erpnext/demo/user/sales.py +++ b/erpnext/demo/user/sales.py @@ -3,12 +3,20 @@ from __future__ import unicode_literals -import frappe, random, erpnext +import random + +import frappe from frappe.utils import flt from frappe.utils.make_random import add_random_children, get_random -from erpnext.setup.utils import get_exchange_rate + +import erpnext +from erpnext.accounts.doctype.payment_request.payment_request import ( + make_payment_entry, + make_payment_request, +) from erpnext.accounts.party import get_party_account_currency -from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request, make_payment_entry +from erpnext.setup.utils import get_exchange_rate + def work(domain="Manufacturing"): frappe.set_user(frappe.db.get_global('demo_sales_user_2')) diff --git a/erpnext/demo/user/stock.py b/erpnext/demo/user/stock.py index d44da7d127e..188fc13f24d 100644 --- a/erpnext/demo/user/stock.py +++ b/erpnext/demo/user/stock.py @@ -3,13 +3,18 @@ from __future__ import print_function, unicode_literals -import frappe, random, erpnext +import random + +import frappe from frappe.desk import query_report -from erpnext.stock.stock_ledger import NegativeStockError -from erpnext.stock.doctype.serial_no.serial_no import SerialNoRequiredError, SerialNoQtyError + +import erpnext from erpnext.stock.doctype.batch.batch import UnableToSelectBatchError from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_return +from erpnext.stock.doctype.serial_no.serial_no import SerialNoQtyError, SerialNoRequiredError +from erpnext.stock.stock_ledger import NegativeStockError + def work(): frappe.set_user(frappe.db.get_global('demo_manufacturing_user')) @@ -66,8 +71,10 @@ def make_delivery_note(): def make_stock_reconciliation(): # random set some items as damaged - from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \ - import OpeningEntryAccountError, EmptyStockReconciliationItemsError + from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( + EmptyStockReconciliationItemsError, + OpeningEntryAccountError, + ) if random.random() < 0.4: stock_reco = frappe.new_doc("Stock Reconciliation") @@ -88,8 +95,11 @@ def make_stock_reconciliation(): frappe.db.rollback() def submit_draft_stock_entries(): - from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \ - DuplicateEntryForWorkOrderError, OperationsNotCompleteError + from erpnext.stock.doctype.stock_entry.stock_entry import ( + DuplicateEntryForWorkOrderError, + IncorrectValuationRateError, + OperationsNotCompleteError, + ) # try posting older drafts (if exists) frappe.db.commit() diff --git a/erpnext/portal/product_configurator/__init__.py b/erpnext/e_commerce/__init__.py similarity index 100% rename from erpnext/portal/product_configurator/__init__.py rename to erpnext/e_commerce/__init__.py diff --git a/erpnext/e_commerce/api.py b/erpnext/e_commerce/api.py new file mode 100644 index 00000000000..43cb36ca2e2 --- /dev/null +++ b/erpnext/e_commerce/api.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import json + +import frappe +from frappe.utils import cint + +from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder +from erpnext.e_commerce.product_data_engine.query import ProductQuery +from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website + + +@frappe.whitelist(allow_guest=True) +def get_product_filter_data(query_args=None): + """ + Returns filtered products and discount filters. + :param query_args (dict): contains filters to get products list + + Query Args filters: + search (str): Search Term. + field_filters (dict): Keys include item_group, brand, etc. + attribute_filters(dict): Keys include Color, Size, etc. + start (int): Offset items by + item_group (str): Valid Item Group + from_filters (bool): Set as True to jump to page 1 + """ + if isinstance(query_args, str): + query_args = json.loads(query_args) + + query_args = frappe._dict(query_args) + if query_args: + search = query_args.get("search") + field_filters = query_args.get("field_filters", {}) + attribute_filters = query_args.get("attribute_filters", {}) + start = cint(query_args.start) if query_args.get("start") else 0 + item_group = query_args.get("item_group") + from_filters = query_args.get("from_filters") + else: + search, attribute_filters, item_group, from_filters = None, None, None, None + field_filters = {} + start = 0 + + # if new filter is checked, reset start to show filtered items from page 1 + if from_filters: + start = 0 + + sub_categories = [] + if item_group: + field_filters['item_group'] = item_group + sub_categories = get_child_groups_for_website(item_group, immediate=True) + + engine = ProductQuery() + try: + result = engine.query( + attribute_filters, + field_filters, + search_term=search, + start=start, + item_group=item_group + ) + except Exception: + traceback = frappe.get_traceback() + frappe.log_error(traceback, frappe._("Product Engine Error")) + return {"exc": "Something went wrong!"} + + # discount filter data + filters = {} + discounts = result["discounts"] + + if discounts: + filter_engine = ProductFiltersBuilder() + filters["discount_filters"] = filter_engine.get_discount_filters(discounts) + + return { + "items": result["items"] or [], + "filters": filters, + "settings": engine.settings, + "sub_categories": sub_categories, + "items_count": result["items_count"] + } + +@frappe.whitelist(allow_guest=True) +def get_guest_redirect_on_action(): + return frappe.db.get_single_value("E Commerce Settings", "redirect_on_action") \ No newline at end of file diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/__init__.py b/erpnext/e_commerce/doctype/__init__.py similarity index 100% rename from erpnext/shopping_cart/doctype/shopping_cart_settings/__init__.py rename to erpnext/e_commerce/doctype/__init__.py diff --git a/erpnext/shopping_cart/web_template/hero_slider/__init__.py b/erpnext/e_commerce/doctype/e_commerce_settings/__init__.py similarity index 100% rename from erpnext/shopping_cart/web_template/hero_slider/__init__.py rename to erpnext/e_commerce/doctype/e_commerce_settings/__init__.py diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js similarity index 60% rename from erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js rename to erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js index b38828e0d75..6302d260e0a 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js @@ -1,7 +1,7 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt -frappe.ui.form.on("Shopping Cart Settings", { +frappe.ui.form.on("E Commerce Settings", { onload: function(frm) { if(frm.doc.__onload && frm.doc.__onload.quotation_series) { frm.fields_dict.quotation_series.df.options = frm.doc.__onload.quotation_series; @@ -23,6 +23,21 @@ frappe.ui.form.on("Shopping Cart Settings", { ` ); } + + frappe.model.with_doctype("Item", () => { + const web_item_meta = frappe.get_meta('Website Item'); + + const valid_fields = web_item_meta.fields.filter( + df => ["Link", "Table MultiSelect"].includes(df.fieldtype) && !df.hidden + ).map(df => ({ label: df.label, value: df.fieldname })); + + frm.fields_dict.filter_fields.grid.update_docfield_property( + 'fieldname', 'fieldtype', 'Select' + ); + frm.fields_dict.filter_fields.grid.update_docfield_property( + 'fieldname', 'options', valid_fields + ); + }); }, enabled: function(frm) { if (frm.doc.enabled === 1) { diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json new file mode 100644 index 00000000000..d5fb9697f89 --- /dev/null +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json @@ -0,0 +1,393 @@ +{ + "actions": [], + "creation": "2021-02-10 17:13:39.139103", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "products_per_page", + "filter_categories_section", + "enable_field_filters", + "filter_fields", + "enable_attribute_filters", + "filter_attributes", + "display_settings_section", + "hide_variants", + "enable_variants", + "show_price", + "column_break_9", + "show_stock_availability", + "show_quantity_in_website", + "allow_items_not_in_stock", + "column_break_13", + "show_apply_coupon_code_in_website", + "show_contact_us_button", + "show_attachments", + "section_break_18", + "company", + "price_list", + "enabled", + "store_page_docs", + "column_break_21", + "default_customer_group", + "quotation_series", + "checkout_settings_section", + "enable_checkout", + "show_price_in_quotation", + "column_break_27", + "save_quotations_as_draft", + "payment_gateway_account", + "payment_success_url", + "add_ons_section", + "enable_wishlist", + "column_break_22", + "enable_reviews", + "column_break_23", + "enable_recommendations", + "item_search_settings_section", + "redisearch_warning", + "search_index_fields", + "show_categories_in_search_autocomplete", + "is_redisearch_loaded", + "shop_by_category_section", + "slideshow", + "guest_display_settings_section", + "hide_price_for_guest", + "redirect_on_action" + ], + "fields": [ + { + "default": "6", + "fieldname": "products_per_page", + "fieldtype": "Int", + "label": "Products per Page" + }, + { + "collapsible": 1, + "fieldname": "filter_categories_section", + "fieldtype": "Section Break", + "label": "Filters and Categories" + }, + { + "default": "0", + "fieldname": "hide_variants", + "fieldtype": "Check", + "label": "Hide Variants" + }, + { + "default": "0", + "description": "The field filters will also work as categories in the Shop by Category page.", + "fieldname": "enable_field_filters", + "fieldtype": "Check", + "label": "Enable Field Filters (Categories)" + }, + { + "default": "0", + "fieldname": "enable_attribute_filters", + "fieldtype": "Check", + "label": "Enable Attribute Filters" + }, + { + "depends_on": "enable_field_filters", + "fieldname": "filter_fields", + "fieldtype": "Table", + "label": "Website Item Fields", + "options": "Website Filter Field" + }, + { + "depends_on": "enable_attribute_filters", + "fieldname": "filter_attributes", + "fieldtype": "Table", + "label": "Attributes", + "options": "Website Attribute" + }, + { + "default": "0", + "fieldname": "enabled", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Enable Shopping Cart" + }, + { + "depends_on": "doc.enabled", + "fieldname": "store_page_docs", + "fieldtype": "HTML" + }, + { + "fieldname": "display_settings_section", + "fieldtype": "Section Break", + "label": "Display Settings" + }, + { + "default": "0", + "fieldname": "show_attachments", + "fieldtype": "Check", + "label": "Show Public Attachments" + }, + { + "default": "0", + "fieldname": "show_price", + "fieldtype": "Check", + "label": "Show Price" + }, + { + "default": "0", + "fieldname": "show_stock_availability", + "fieldtype": "Check", + "label": "Show Stock Availability" + }, + { + "default": "0", + "fieldname": "enable_variants", + "fieldtype": "Check", + "label": "Enable Variant Selection" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "show_contact_us_button", + "fieldtype": "Check", + "label": "Show Contact Us Button" + }, + { + "default": "0", + "depends_on": "show_stock_availability", + "fieldname": "show_quantity_in_website", + "fieldtype": "Check", + "label": "Show Stock Quantity" + }, + { + "default": "0", + "fieldname": "show_apply_coupon_code_in_website", + "fieldtype": "Check", + "label": "Show Apply Coupon Code" + }, + { + "default": "0", + "fieldname": "allow_items_not_in_stock", + "fieldtype": "Check", + "label": "Allow items not in stock to be added to cart" + }, + { + "fieldname": "section_break_18", + "fieldtype": "Section Break", + "label": "Shopping Cart" + }, + { + "depends_on": "enabled", + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "mandatory_depends_on": "eval: doc.enabled === 1", + "options": "Company", + "remember_last_selected_value": 1 + }, + { + "depends_on": "enabled", + "description": "Prices will not be shown if Price List is not set", + "fieldname": "price_list", + "fieldtype": "Link", + "label": "Price List", + "mandatory_depends_on": "eval: doc.enabled === 1", + "options": "Price List" + }, + { + "fieldname": "column_break_21", + "fieldtype": "Column Break" + }, + { + "depends_on": "enabled", + "fieldname": "default_customer_group", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Default Customer Group", + "mandatory_depends_on": "eval: doc.enabled === 1", + "options": "Customer Group" + }, + { + "depends_on": "enabled", + "fieldname": "quotation_series", + "fieldtype": "Select", + "label": "Quotation Series", + "mandatory_depends_on": "eval: doc.enabled === 1" + }, + { + "collapsible": 1, + "collapsible_depends_on": "eval:doc.enable_checkout", + "depends_on": "enabled", + "fieldname": "checkout_settings_section", + "fieldtype": "Section Break", + "label": "Checkout Settings" + }, + { + "default": "0", + "fieldname": "enable_checkout", + "fieldtype": "Check", + "label": "Enable Checkout" + }, + { + "default": "Orders", + "depends_on": "enable_checkout", + "description": "After payment completion redirect user to selected page.", + "fieldname": "payment_success_url", + "fieldtype": "Select", + "label": "Payment Success Url", + "mandatory_depends_on": "enable_checkout", + "options": "\nOrders\nInvoices\nMy Account" + }, + { + "fieldname": "column_break_27", + "fieldtype": "Column Break" + }, + { + "default": "0", + "depends_on": "eval: doc.enable_checkout == 0", + "fieldname": "save_quotations_as_draft", + "fieldtype": "Check", + "label": "Save Quotations as Draft" + }, + { + "depends_on": "enable_checkout", + "fieldname": "payment_gateway_account", + "fieldtype": "Link", + "label": "Payment Gateway Account", + "mandatory_depends_on": "enable_checkout", + "options": "Payment Gateway Account" + }, + { + "collapsible": 1, + "depends_on": "enable_field_filters", + "fieldname": "shop_by_category_section", + "fieldtype": "Section Break", + "label": "Shop by Category" + }, + { + "fieldname": "slideshow", + "fieldtype": "Link", + "label": "Slideshow", + "options": "Website Slideshow" + }, + { + "collapsible": 1, + "fieldname": "add_ons_section", + "fieldtype": "Section Break", + "label": "Add-ons" + }, + { + "default": "0", + "fieldname": "enable_wishlist", + "fieldtype": "Check", + "label": "Enable Wishlist" + }, + { + "default": "0", + "fieldname": "enable_reviews", + "fieldtype": "Check", + "label": "Enable Reviews and Ratings" + }, + { + "fieldname": "search_index_fields", + "fieldtype": "Small Text", + "label": "Search Index Fields", + "read_only_depends_on": "eval:!doc.is_redisearch_loaded" + }, + { + "collapsible": 1, + "fieldname": "item_search_settings_section", + "fieldtype": "Section Break", + "label": "Item Search Settings" + }, + { + "default": "1", + "fieldname": "show_categories_in_search_autocomplete", + "fieldtype": "Check", + "label": "Show Categories in Search Autocomplete", + "read_only_depends_on": "eval:!doc.is_redisearch_loaded" + }, + { + "default": "0", + "fieldname": "is_redisearch_loaded", + "fieldtype": "Check", + "hidden": 1, + "label": "Is Redisearch Loaded" + }, + { + "depends_on": "eval:!doc.is_redisearch_loaded", + "fieldname": "redisearch_warning", + "fieldtype": "HTML", + "label": "Redisearch Warning", + "options": "

Redisearch is not loaded. If you want to use the advanced product search feature, refer here.

" + }, + { + "default": "0", + "depends_on": "eval:doc.show_price", + "fieldname": "hide_price_for_guest", + "fieldtype": "Check", + "label": "Hide Price for Guest" + }, + { + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, + { + "collapsible": 1, + "fieldname": "guest_display_settings_section", + "fieldtype": "Section Break", + "label": "Guest Display Settings" + }, + { + "description": "Link to redirect Guest on actions that need login such as add to cart, wishlist, etc. E.g.: /login", + "fieldname": "redirect_on_action", + "fieldtype": "Data", + "label": "Redirect on Action" + }, + { + "fieldname": "column_break_22", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_23", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "enable_recommendations", + "fieldtype": "Check", + "label": "Enable Recommendations" + }, + { + "default": "0", + "depends_on": "eval: doc.enable_checkout == 0", + "fieldname": "show_price_in_quotation", + "fieldtype": "Check", + "label": "Show Price in Quotation" + } + ], + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2021-09-02 14:02:44.785824", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "E Commerce Settings", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py similarity index 50% rename from erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py rename to erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py index efed1968a14..6fc5ef9e958 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py @@ -1,25 +1,81 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe -from frappe import _, msgprint -from frappe.utils import flt +from frappe import _ from frappe.model.document import Document -from frappe.utils import get_datetime, get_datetime_str, now_datetime +from frappe.utils import comma_and, flt, unique + +from erpnext.e_commerce.redisearch import ( + create_website_items_index, + get_indexable_web_fields, + is_search_module_loaded, +) + class ShoppingCartSetupError(frappe.ValidationError): pass -class ShoppingCartSettings(Document): +class ECommerceSettings(Document): def onload(self): self.get("__onload").quotation_series = frappe.get_meta("Quotation").get_options("naming_series") + self.is_redisearch_loaded = is_search_module_loaded() def validate(self): + self.validate_field_filters() + self.validate_attribute_filters() + self.validate_checkout() + self.validate_search_index_fields() + if self.enabled: self.validate_price_list_exchange_rate() + frappe.clear_document_cache("E Commerce Settings", "E Commerce Settings") + + def validate_field_filters(self): + if not (self.enable_field_filters and self.filter_fields): + return + + item_meta = frappe.get_meta("Item") + valid_fields = [df.fieldname for df in item_meta.fields if df.fieldtype in ["Link", "Table MultiSelect"]] + + for f in self.filter_fields: + if f.fieldname not in valid_fields: + frappe.throw(_("Filter Fields Row #{0}: Fieldname {1} must be of type 'Link' or 'Table MultiSelect'").format(f.idx, f.fieldname)) + + def validate_attribute_filters(self): + if not (self.enable_attribute_filters and self.filter_attributes): + return + + # if attribute filters are enabled, hide_variants should be disabled + self.hide_variants = 0 + + def validate_checkout(self): + if self.enable_checkout and not self.payment_gateway_account: + self.enable_checkout = 0 + + def validate_search_index_fields(self): + if not self.search_index_fields: + return + + fields = self.search_index_fields.replace(' ', '') + fields = unique(fields.strip(',').split(',')) # Remove extra ',' and remove duplicates + + # All fields should be indexable + allowed_indexable_fields = get_indexable_web_fields() + + if not (set(fields).issubset(allowed_indexable_fields)): + invalid_fields = list(set(fields).difference(allowed_indexable_fields)) + num_invalid_fields = len(invalid_fields) + invalid_fields = comma_and(invalid_fields) + + if num_invalid_fields > 1: + frappe.throw(_("{0} are not valid options for Search Index Field.").format(frappe.bold(invalid_fields))) + else: + frappe.throw(_("{0} is not a valid option for Search Index Field.").format(frappe.bold(invalid_fields))) + + self.search_index_fields = ','.join(fields) + def validate_price_list_exchange_rate(self): "Check if exchange rate exists for Price List currency (to Company's currency)." from erpnext.setup.utils import get_exchange_rate @@ -60,12 +116,23 @@ class ShoppingCartSettings(Document): def get_shipping_rules(self, shipping_territory): return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule") -def validate_cart_settings(doc=None, method=None): - frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate") + def on_change(self): + old_doc = self.get_doc_before_save() + + if old_doc: + old_fields = old_doc.search_index_fields + new_fields = self.search_index_fields + + # if search index fields get changed + if not (new_fields == old_fields): + create_website_items_index() + +def validate_cart_settings(doc, method): + frappe.get_doc("E Commerce Settings", "E Commerce Settings").run_method("validate") def get_shopping_cart_settings(): if not getattr(frappe.local, "shopping_cart_settings", None): - frappe.local.shopping_cart_settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings") + frappe.local.shopping_cart_settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings") return frappe.local.shopping_cart_settings diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py similarity index 74% rename from erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py rename to erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py index 9965e1af672..e3a1e1a16a4 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py @@ -1,19 +1,22 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe import unittest -from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import ShoppingCartSetupError -class TestShoppingCartSettings(unittest.TestCase): +import frappe + +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + ShoppingCartSetupError, +) + + +class TestECommerceSettings(unittest.TestCase): def setUp(self): frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """) def get_cart_settings(self): - return frappe.get_doc({"doctype": "Shopping Cart Settings", + return frappe.get_doc({"doctype": "E Commerce Settings", "company": "_Test Company"}) # NOTE: Exchangrate API has all enabled currencies that ERPNext supports. @@ -47,4 +50,13 @@ class TestShoppingCartSettings(unittest.TestCase): frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 1") +def setup_e_commerce_settings(values_dict): + "Accepts a dict of values that updates E Commerce Settings." + if not values_dict: + return + + doc = frappe.get_doc("E Commerce Settings", "E Commerce Settings") + doc.update(values_dict) + doc.save() + test_dependencies = ["Tax Rule"] diff --git a/erpnext/shopping_cart/web_template/item_card_group/__init__.py b/erpnext/e_commerce/doctype/item_review/__init__.py similarity index 100% rename from erpnext/shopping_cart/web_template/item_card_group/__init__.py rename to erpnext/e_commerce/doctype/item_review/__init__.py diff --git a/erpnext/e_commerce/doctype/item_review/item_review.js b/erpnext/e_commerce/doctype/item_review/item_review.js new file mode 100644 index 00000000000..a57c370287b --- /dev/null +++ b/erpnext/e_commerce/doctype/item_review/item_review.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Item Review', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/e_commerce/doctype/item_review/item_review.json b/erpnext/e_commerce/doctype/item_review/item_review.json new file mode 100644 index 00000000000..57f719fc3c4 --- /dev/null +++ b/erpnext/e_commerce/doctype/item_review/item_review.json @@ -0,0 +1,134 @@ +{ + "actions": [], + "beta": 1, + "creation": "2021-03-23 16:47:26.542226", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "website_item", + "user", + "customer", + "column_break_3", + "item", + "published_on", + "reviews_section", + "review_title", + "rating", + "comment" + ], + "fields": [ + { + "fieldname": "website_item", + "fieldtype": "Link", + "label": "Website Item", + "options": "Website Item", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "user", + "fieldtype": "Link", + "in_list_view": 1, + "label": "User", + "options": "User", + "read_only": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fetch_from": "website_item.item_code", + "fieldname": "item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item", + "options": "Item", + "read_only": 1 + }, + { + "fieldname": "reviews_section", + "fieldtype": "Section Break", + "label": "Reviews" + }, + { + "fieldname": "rating", + "fieldtype": "Rating", + "in_list_view": 1, + "label": "Rating", + "read_only": 1 + }, + { + "fieldname": "comment", + "fieldtype": "Small Text", + "label": "Comment", + "read_only": 1 + }, + { + "fieldname": "review_title", + "fieldtype": "Data", + "label": "Review Title", + "read_only": 1 + }, + { + "fieldname": "customer", + "fieldtype": "Link", + "label": "Customer", + "options": "Customer", + "read_only": 1 + }, + { + "fieldname": "published_on", + "fieldtype": "Data", + "label": "Published on", + "read_only": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-08-10 12:08:58.119691", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Item Review", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Website Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "report": 1, + "role": "Customer", + "share": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/item_review/item_review.py b/erpnext/e_commerce/doctype/item_review/item_review.py new file mode 100644 index 00000000000..91e98427d43 --- /dev/null +++ b/erpnext/e_commerce/doctype/item_review/item_review.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals + +from datetime import datetime + +import frappe +from frappe import _ +from frappe.contacts.doctype.contact.contact import get_contact_name +from frappe.model.document import Document +from frappe.utils import cint, flt + +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + get_shopping_cart_settings, +) + + +class UnverifiedReviewer(frappe.ValidationError): + pass + +class ItemReview(Document): + def after_insert(self): + # regenerate cache on review creation + reviews_dict = get_queried_reviews(self.website_item) + set_reviews_in_cache(self.website_item, reviews_dict) + + def after_delete(self): + # regenerate cache on review deletion + reviews_dict = get_queried_reviews(self.website_item) + set_reviews_in_cache(self.website_item, reviews_dict) + + +@frappe.whitelist() +def get_item_reviews(web_item, start=0, end=10, data=None): + "Get Website Item Review Data." + start, end = cint(start), cint(end) + settings = get_shopping_cart_settings() + + # Get cached reviews for first page (start=0) + # avoid cache when page is different + from_cache = not bool(start) + + if not data: + data = frappe._dict() + + if settings and settings.get("enable_reviews"): + reviews_cache = frappe.cache().hget("item_reviews", web_item) + if from_cache and reviews_cache: + data = reviews_cache + else: + data = get_queried_reviews(web_item, start, end, data) + if from_cache: + set_reviews_in_cache(web_item, data) + + return data + +def get_queried_reviews(web_item, start=0, end=10, data=None): + """ + Query Website Item wise reviews and cache if needed. + Cache stores only first page of reviews i.e. 10 reviews maximum. + Returns: + dict: Containing reviews, average ratings, % of reviews per rating and total reviews. + """ + if not data: + data = frappe._dict() + + data.reviews = frappe.db.get_all( + "Item Review", + filters={"website_item": web_item}, + fields=["*"], + limit_start=start, + limit_page_length=end + ) + + rating_data = frappe.db.get_all( + "Item Review", + filters={"website_item": web_item}, + fields=["avg(rating) as average, count(*) as total"] + )[0] + + data.average_rating = flt(rating_data.average, 1) + data.average_whole_rating = flt(data.average_rating, 0) + + # get % of reviews per rating + reviews_per_rating = [] + for i in range(1,6): + count = frappe.db.get_all( + "Item Review", + filters={"website_item": web_item, "rating": i}, + fields=["count(*) as count"] + )[0].count + + percent = flt((count / rating_data.total or 1) * 100, 0) if count else 0 + reviews_per_rating.append(percent) + + data.reviews_per_rating = reviews_per_rating + data.total_reviews = rating_data.total + + return data + +def set_reviews_in_cache(web_item, reviews_dict): + frappe.cache().hset("item_reviews", web_item, reviews_dict) + +@frappe.whitelist() +def add_item_review(web_item, title, rating, comment=None): + """ Add an Item Review by a user if non-existent. """ + if frappe.session.user == "Guest": + # guest user should not reach here ideally in the case they do via an API, throw error + frappe.throw(_("You are not verified to write a review yet."), exc=UnverifiedReviewer) + + if not frappe.db.exists("Item Review", {"user": frappe.session.user, "website_item": web_item}): + doc = frappe.get_doc({ + "doctype": "Item Review", + "user": frappe.session.user, + "customer": get_customer(), + "website_item": web_item, + "item": frappe.db.get_value("Website Item", web_item, "item_code"), + "review_title": title, + "rating": rating, + "comment": comment + }) + doc.published_on = datetime.today().strftime("%d %B %Y") + doc.insert() + +def get_customer(silent=False): + """ + silent: Return customer if exists else return nothing. Dont throw error. + """ + user = frappe.session.user + contact_name = get_contact_name(user) + customer = None + + if contact_name: + contact = frappe.get_doc('Contact', contact_name) + for link in contact.links: + if link.link_doctype == "Customer": + customer = link.link_name + break + + if customer: + return frappe.db.get_value("Customer", customer) + elif silent: + return None + else: + # should not reach here unless via an API + frappe.throw(_("You are not a verified customer yet. Please contact us to proceed."), + exc=UnverifiedReviewer) diff --git a/erpnext/e_commerce/doctype/item_review/test_item_review.py b/erpnext/e_commerce/doctype/item_review/test_item_review.py new file mode 100644 index 00000000000..8a4befc800a --- /dev/null +++ b/erpnext/e_commerce/doctype/item_review/test_item_review.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +import unittest + +import frappe +from frappe.core.doctype.user_permission.test_user_permission import create_user + +from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import ( + setup_e_commerce_settings, +) +from erpnext.e_commerce.doctype.item_review.item_review import ( + UnverifiedReviewer, + add_item_review, + get_item_reviews, +) +from erpnext.e_commerce.doctype.website_item.website_item import make_website_item +from erpnext.e_commerce.shopping_cart.cart import get_party +from erpnext.stock.doctype.item.test_item import make_item + + +class TestItemReview(unittest.TestCase): + def setUp(self): + item = make_item("Test Mobile Phone") + if not frappe.db.exists("Website Item", {"item_code": "Test Mobile Phone"}): + make_website_item(item, save=True) + + setup_e_commerce_settings({"enable_reviews": 1}) + frappe.local.shopping_cart_settings = None + + def tearDown(self): + frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete() + setup_e_commerce_settings({"enable_reviews": 0}) + + def test_add_and_get_item_reviews_from_customer(self): + "Add / Get Reviews from a User that is a valid customer (has added to cart or purchased in the past)" + # create user + web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"}) + test_user = create_user("test_reviewer@example.com", "Customer") + frappe.set_user(test_user.name) + + # create customer and contact against user + customer = get_party() + + # post review on "Test Mobile Phone" + try: + add_item_review(web_item, "Great Product", 3, "Would recommend this product") + review_name = frappe.db.get_value("Item Review", {"website_item": web_item}) + except Exception: + self.fail(f"Error while publishing review for {web_item}") + + review_data = get_item_reviews(web_item, 0, 10) + + self.assertEqual(len(review_data.reviews), 1) + self.assertEqual(review_data.average_rating, 3) + self.assertEqual(review_data.reviews_per_rating[2], 100) + + # tear down + frappe.set_user("Administrator") + frappe.delete_doc("Item Review", review_name) + customer.delete() + + def test_add_item_review_from_non_customer(self): + "Check if logged in user (who is not a customer yet) is blocked from posting reviews." + web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"}) + test_user = create_user("test_reviewer@example.com", "Customer") + frappe.set_user(test_user.name) + + with self.assertRaises(UnverifiedReviewer): + add_item_review(web_item, "Great Product", 3, "Would recommend this product") + + # tear down + frappe.set_user("Administrator") + + def test_add_item_reviews_from_guest_user(self): + "Check if Guest user is blocked from posting reviews." + web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"}) + frappe.set_user("Guest") + + with self.assertRaises(UnverifiedReviewer): + add_item_review(web_item, "Great Product", 3, "Would recommend this product") + + # tear down + frappe.set_user("Administrator") diff --git a/erpnext/shopping_cart/web_template/product_card/__init__.py b/erpnext/e_commerce/doctype/recommended_items/__init__.py similarity index 100% rename from erpnext/shopping_cart/web_template/product_card/__init__.py rename to erpnext/e_commerce/doctype/recommended_items/__init__.py diff --git a/erpnext/e_commerce/doctype/recommended_items/recommended_items.json b/erpnext/e_commerce/doctype/recommended_items/recommended_items.json new file mode 100644 index 00000000000..06ac3dc03b7 --- /dev/null +++ b/erpnext/e_commerce/doctype/recommended_items/recommended_items.json @@ -0,0 +1,87 @@ +{ + "actions": [], + "creation": "2021-07-12 20:52:12.503470", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "website_item", + "website_item_name", + "column_break_2", + "item_code", + "more_information_section", + "route", + "column_break_6", + "website_item_image", + "website_item_thumbnail" + ], + "fields": [ + { + "fieldname": "website_item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Website Item", + "options": "Website Item" + }, + { + "fetch_from": "website_item.web_item_name", + "fieldname": "website_item_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Website Item Name", + "read_only": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "more_information_section", + "fieldtype": "Section Break", + "label": "More Information" + }, + { + "fetch_from": "website_item.route", + "fieldname": "route", + "fieldtype": "Small Text", + "label": "Route", + "read_only": 1 + }, + { + "fetch_from": "website_item.image", + "fieldname": "website_item_image", + "fieldtype": "Attach", + "label": "Website Item Image", + "read_only": 1 + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "fetch_from": "website_item.thumbnail", + "fieldname": "website_item_thumbnail", + "fieldtype": "Data", + "label": "Website Item Thumbnail", + "read_only": 1 + }, + { + "fetch_from": "website_item.item_code", + "fieldname": "item_code", + "fieldtype": "Data", + "label": "Item Code" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-07-13 21:02:19.031652", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Recommended Items", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/recommended_items/recommended_items.py b/erpnext/e_commerce/doctype/recommended_items/recommended_items.py new file mode 100644 index 00000000000..16b6e52047f --- /dev/null +++ b/erpnext/e_commerce/doctype/recommended_items/recommended_items.py @@ -0,0 +1,9 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class RecommendedItems(Document): + pass diff --git a/erpnext/shopping_cart/web_template/product_category_cards/__init__.py b/erpnext/e_commerce/doctype/website_item/__init__.py similarity index 100% rename from erpnext/shopping_cart/web_template/product_category_cards/__init__.py rename to erpnext/e_commerce/doctype/website_item/__init__.py diff --git a/erpnext/e_commerce/doctype/website_item/templates/website_item.html b/erpnext/e_commerce/doctype/website_item/templates/website_item.html new file mode 100644 index 00000000000..db123090aae --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/templates/website_item.html @@ -0,0 +1,7 @@ +{% extends "templates/web.html" %} + +{% block page_content %} +

{{ title }}

+{% endblock %} + + \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html b/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html new file mode 100644 index 00000000000..d7014b453ab --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html @@ -0,0 +1,4 @@ +
+ {{ doc.title or doc.name }} +
+ diff --git a/erpnext/e_commerce/doctype/website_item/test_website_item.py b/erpnext/e_commerce/doctype/website_item/test_website_item.py new file mode 100644 index 00000000000..48dd1671953 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/test_website_item.py @@ -0,0 +1,496 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +import frappe + +from erpnext.controllers.item_variant import create_variant +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + get_shopping_cart_settings, +) +from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import ( + setup_e_commerce_settings, +) +from erpnext.e_commerce.doctype.website_item.website_item import make_website_item +from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website +from erpnext.stock.doctype.item.item import DataValidationError +from erpnext.stock.doctype.item.test_item import make_item + +WEBITEM_DESK_TESTS = ("test_website_item_desk_item_sync", "test_publish_variant_and_template") +WEBITEM_PRICE_TESTS = ('test_website_item_price_for_logged_in_user', 'test_website_item_price_for_guest_user') + +class TestWebsiteItem(unittest.TestCase): + @classmethod + def setUpClass(cls): + setup_e_commerce_settings({ + "company": "_Test Company", + "enabled": 1, + "default_customer_group": "_Test Customer Group", + "price_list": "_Test Price List India" + }) + + @classmethod + def tearDownClass(cls): + frappe.db.rollback() + + def setUp(self): + if self._testMethodName in WEBITEM_DESK_TESTS: + make_item("Test Web Item", { + "has_variant": 1, + "variant_based_on": "Item Attribute", + "attributes": [ + { + "attribute": "Test Size" + } + ] + }) + elif self._testMethodName in WEBITEM_PRICE_TESTS: + create_regular_web_item() + make_web_item_price(item_code="Test Mobile Phone") + make_web_pricing_rule( + title="Test Pricing Rule for Test Mobile Phone", + item_code="Test Mobile Phone", + selling=1) + + def test_index_creation(self): + "Check if index is getting created in db." + from erpnext.e_commerce.doctype.website_item.website_item import on_doctype_update + on_doctype_update() + + indices = frappe.db.sql("show index from `tabWebsite Item`", as_dict=1) + expected_columns = {"route", "item_group", "brand"} + for index in indices: + expected_columns.discard(index.get("Column_name")) + + if expected_columns: + self.fail(f"Expected db index on these columns: {', '.join(expected_columns)}") + + def test_website_item_desk_item_sync(self): + "Check creation/updation/deletion of Website Item and its impact on Item master." + web_item = None + item = make_item("Test Web Item") # will return item if exists + try: + web_item = make_website_item(item, save=False) + web_item.save() + except Exception: + self.fail(f"Error while creating website item for {item}") + + # check if website item was created + self.assertTrue(bool(web_item)) + self.assertTrue(bool(web_item.route)) + + item.reload() + self.assertEqual(web_item.published, 1) + self.assertEqual(item.published_in_website, 1) # check if item was back updated + self.assertEqual(web_item.item_group, item.item_group) + + # check if changing item data changes it in website item + item.item_name = "Test Web Item 1" + item.stock_uom = "Unit" + item.save() + web_item.reload() + self.assertEqual(web_item.item_name, item.item_name) + self.assertEqual(web_item.stock_uom, item.stock_uom) + + # check if disabling item unpublished website item + item.disabled = 1 + item.save() + web_item.reload() + self.assertEqual(web_item.published, 0) + + # check if website item deletion, unpublishes desk item + web_item.delete() + item.reload() + self.assertEqual(item.published_in_website, 0) + + item.delete() + + def test_publish_variant_and_template(self): + "Check if template is published on publishing variant." + # template "Test Web Item" created on setUp + variant = create_variant("Test Web Item", {"Test Size": "Large"}) + variant.save() + + # check if template is not published + self.assertIsNone(frappe.db.exists("Website Item", {"item_code": variant.variant_of})) + + variant_web_item = make_website_item(variant, save=False) + variant_web_item.save() + + # check if template is published + try: + template_web_item = frappe.get_doc("Website Item", {"item_code": variant.variant_of}) + except frappe.DoesNotExistError: + self.fail(f"Template of {variant.item_code}, {variant.variant_of} not published") + + # teardown + variant_web_item.delete() + template_web_item.delete() + variant.delete() + + def test_impact_on_merging_items(self): + "Check if merging items is blocked if old and new items both have website items" + first_item = make_item("Test First Item") + second_item = make_item("Test Second Item") + + first_web_item = make_website_item(first_item, save=False) + first_web_item.save() + second_web_item = make_website_item(second_item, save=False) + second_web_item.save() + + with self.assertRaises(DataValidationError): + frappe.rename_doc("Item", "Test First Item", "Test Second Item", merge=True) + + # tear down + second_web_item.delete() + first_web_item.delete() + second_item.delete() + first_item.delete() + + # Website Item Portal Tests Begin + + def test_website_item_breadcrumbs(self): + "Check if breadcrumbs include homepage, product listing navigation page, parent item group(s) and item group." + from erpnext.setup.doctype.item_group.item_group import get_parent_item_groups + + item_code = "Test Breadcrumb Item" + item = make_item(item_code, { + "item_group": "_Test Item Group B - 1", + }) + + if not frappe.db.exists("Website Item", {"item_code": item_code}): + web_item = make_website_item(item, save=False) + web_item.save() + else: + web_item = frappe.get_cached_doc("Website Item", {"item_code": item_code}) + + frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1) + frappe.db.set_value("Item Group", "_Test Item Group B", "show_in_website", 1) + + breadcrumbs = get_parent_item_groups(item.item_group) + + self.assertEqual(breadcrumbs[0]["name"], "Home") + self.assertEqual(breadcrumbs[1]["name"], "Shop by Category") + self.assertEqual(breadcrumbs[2]["name"], "_Test Item Group B") # parent item group + self.assertEqual(breadcrumbs[3]["name"], "_Test Item Group B - 1") + + # tear down + web_item.delete() + item.delete() + + def test_website_item_price_for_logged_in_user(self): + "Check if price details are fetched correctly while logged in." + item_code = "Test Mobile Phone" + + # show price in e commerce settings + setup_e_commerce_settings({"show_price": 1}) + + # price and pricing rule added via setUp + + # check if price and slashed price is fetched correctly + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertTrue(bool(data.product_info["price"])) + + price_object = data.product_info["price"] + self.assertEqual(price_object.get("discount_percent"), 10) + self.assertEqual(price_object.get("price_list_rate"), 900) + self.assertEqual(price_object.get("formatted_mrp"), "₹ 1,000.00") + self.assertEqual(price_object.get("formatted_price"), "₹ 900.00") + self.assertEqual(price_object.get("formatted_discount_percent"), "10%") + + # disable show price + setup_e_commerce_settings({"show_price": 0}) + + # price should not be fetched + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertFalse(bool(data.product_info["price"])) + + # tear down + frappe.set_user("Administrator") + + def test_website_item_price_for_guest_user(self): + "Check if price details are fetched correctly for guest user." + item_code = "Test Mobile Phone" + + # show price for guest user in e commerce settings + setup_e_commerce_settings({ + "show_price": 1, + "hide_price_for_guest": 0 + }) + + # price and pricing rule added via setUp + + # switch to guest user + frappe.set_user("Guest") + + # price should be fetched + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertTrue(bool(data.product_info["price"])) + + price_object = data.product_info["price"] + self.assertEqual(price_object.get("discount_percent"), 10) + self.assertEqual(price_object.get("price_list_rate"), 900) + + # hide price for guest user + frappe.set_user("Administrator") + setup_e_commerce_settings({"hide_price_for_guest": 1}) + frappe.set_user("Guest") + + # price should not be fetched + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertFalse(bool(data.product_info["price"])) + + # tear down + frappe.set_user("Administrator") + + def test_website_item_stock_when_out_of_stock(self): + """ + Check if stock details are fetched correctly for empty inventory when: + 1) Showing stock availability enabled: + - Warehouse unset + - Warehouse set + 2) Showing stock availability disabled + """ + item_code = "Test Mobile Phone" + create_regular_web_item() + setup_e_commerce_settings({"show_stock_availability": 1}) + + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + + # check if stock details are fetched and item not in stock without warehouse set + self.assertFalse(bool(data.product_info["in_stock"])) + self.assertFalse(bool(data.product_info["stock_qty"])) + + # set warehouse + frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "_Test Warehouse - _TC") + + # check if stock details are fetched and item not in stock with warehouse set + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertFalse(bool(data.product_info["in_stock"])) + self.assertEqual(data.product_info["stock_qty"][0][0], 0) + + # disable show stock availability + setup_e_commerce_settings({"show_stock_availability": 0}) + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + + # check if stock detail attributes are not fetched if stock availability is hidden + self.assertIsNone(data.product_info.get("in_stock")) + self.assertIsNone(data.product_info.get("stock_qty")) + self.assertIsNone(data.product_info.get("show_stock_qty")) + + # tear down + frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete() + + def test_website_item_stock_when_in_stock(self): + """ + Check if stock details are fetched correctly for available inventory when: + 1) Showing stock availability enabled: + - Warehouse set + - Warehouse unset + 2) Showing stock availability disabled + """ + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + + item_code = "Test Mobile Phone" + create_regular_web_item() + setup_e_commerce_settings({"show_stock_availability": 1}) + frappe.local.shopping_cart_settings = None + + # set warehouse + frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "_Test Warehouse - _TC") + + # stock up item + stock_entry = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=2, rate=100) + + # check if stock details are fetched and item is in stock with warehouse set + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertTrue(bool(data.product_info["in_stock"])) + self.assertEqual(data.product_info["stock_qty"][0][0], 2) + + # unset warehouse + frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "") + + # check if stock details are fetched and item not in stock without warehouse set + # (even though it has stock in some warehouse) + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + self.assertFalse(bool(data.product_info["in_stock"])) + self.assertFalse(bool(data.product_info["stock_qty"])) + + # disable show stock availability + setup_e_commerce_settings({"show_stock_availability": 0}) + frappe.local.shopping_cart_settings = None + data = get_product_info_for_website(item_code, skip_quotation_creation=True) + + # check if stock detail attributes are not fetched if stock availability is hidden + self.assertIsNone(data.product_info.get("in_stock")) + self.assertIsNone(data.product_info.get("stock_qty")) + self.assertIsNone(data.product_info.get("show_stock_qty")) + + # tear down + stock_entry.cancel() + frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete() + + def test_recommended_item(self): + "Check if added recommended items are fetched correctly." + item_code = "Test Mobile Phone" + web_item = create_regular_web_item(item_code) + + setup_e_commerce_settings({ + "enable_recommendations": 1, + "show_price": 1 + }) + + # create recommended web item and price for it + recommended_web_item = create_regular_web_item("Test Mobile Phone 1") + make_web_item_price(item_code="Test Mobile Phone 1") + + # add recommended item to first web item + web_item.append("recommended_items", {"website_item": recommended_web_item.name}) + web_item.save() + + frappe.local.shopping_cart_settings = None + e_commerce_settings = get_shopping_cart_settings() + recommended_items = web_item.get_recommended_items(e_commerce_settings) + + # test results if show price is enabled + self.assertEqual(len(recommended_items), 1) + recomm_item = recommended_items[0] + self.assertEqual(recomm_item.get("website_item_name"), "Test Mobile Phone 1") + self.assertTrue(bool(recomm_item.get("price_info"))) # price fetched + + price_info = recomm_item.get("price_info") + self.assertEqual(price_info.get("price_list_rate"), 1000) + self.assertEqual(price_info.get("formatted_price"), "₹ 1,000.00") + + # test results if show price is disabled + setup_e_commerce_settings({"show_price": 0}) + + frappe.local.shopping_cart_settings = None + e_commerce_settings = get_shopping_cart_settings() + recommended_items = web_item.get_recommended_items(e_commerce_settings) + + self.assertEqual(len(recommended_items), 1) + self.assertFalse(bool(recommended_items[0].get("price_info"))) # price not fetched + + # tear down + web_item.delete() + recommended_web_item.delete() + frappe.get_cached_doc("Item", "Test Mobile Phone 1").delete() + + def test_recommended_item_for_guest_user(self): + "Check if added recommended items are fetched correctly for guest user." + item_code = "Test Mobile Phone" + web_item = create_regular_web_item(item_code) + + # price visible to guests + setup_e_commerce_settings({ + "enable_recommendations": 1, + "show_price": 1, + "hide_price_for_guest": 0 + }) + + # create recommended web item and price for it + recommended_web_item = create_regular_web_item("Test Mobile Phone 1") + make_web_item_price(item_code="Test Mobile Phone 1") + + # add recommended item to first web item + web_item.append("recommended_items", {"website_item": recommended_web_item.name}) + web_item.save() + + frappe.set_user("Guest") + + frappe.local.shopping_cart_settings = None + e_commerce_settings = get_shopping_cart_settings() + recommended_items = web_item.get_recommended_items(e_commerce_settings) + + # test results if show price is enabled + self.assertEqual(len(recommended_items), 1) + self.assertTrue(bool(recommended_items[0].get("price_info"))) # price fetched + + # price hidden from guests + frappe.set_user("Administrator") + setup_e_commerce_settings({"hide_price_for_guest": 1}) + frappe.set_user("Guest") + + frappe.local.shopping_cart_settings = None + e_commerce_settings = get_shopping_cart_settings() + recommended_items = web_item.get_recommended_items(e_commerce_settings) + + # test results if show price is enabled + self.assertEqual(len(recommended_items), 1) + self.assertFalse(bool(recommended_items[0].get("price_info"))) # price fetched + + # tear down + frappe.set_user("Administrator") + web_item.delete() + recommended_web_item.delete() + frappe.get_cached_doc("Item", "Test Mobile Phone 1").delete() + +def create_regular_web_item(item_code=None, item_args=None, web_args=None): + "Create Regular Item and Website Item." + item_code = item_code or "Test Mobile Phone" + item = make_item(item_code, properties=item_args) + + if not frappe.db.exists("Website Item", {"item_code": item_code}): + web_item = make_website_item(item, save=False) + if web_args: + web_item.update(web_args) + web_item.save() + else: + web_item = frappe.get_cached_doc("Website Item", {"item_code": item_code}) + + return web_item + +def make_web_item_price(**kwargs): + item_code = kwargs.get("item_code") + if not item_code: + return + + if not frappe.db.exists("Item Price", {"item_code": item_code}): + item_price = frappe.get_doc({ + "doctype": "Item Price", + "item_code": item_code, + "price_list": kwargs.get("price_list") or "_Test Price List India", + "price_list_rate": kwargs.get("price_list_rate") or 1000 + }) + item_price.insert() + else: + item_price = frappe.get_cached_doc("Item Price", {"item_code": item_code}) + + return item_price + +def make_web_pricing_rule(**kwargs): + title = kwargs.get("title") + if not title: + return + + if not frappe.db.exists("Pricing Rule", title): + pricing_rule = frappe.get_doc({ + "doctype": "Pricing Rule", + "title": title, + "apply_on": kwargs.get("apply_on") or "Item Code", + "items": [{ + "item_code": kwargs.get("item_code") + }], + "selling": kwargs.get("selling") or 0, + "buying": kwargs.get("buying") or 0, + "rate_or_discount": kwargs.get("rate_or_discount") or "Discount Percentage", + "discount_percentage": kwargs.get("discount_percentage") or 10, + "company": kwargs.get("company") or "_Test Company", + "currency": kwargs.get("currency") or "INR", + "for_price_list": kwargs.get("price_list") or "_Test Price List India" + }) + pricing_rule.insert() + else: + pricing_rule = frappe.get_doc("Pricing Rule", {"title": title}) + + return pricing_rule \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_item/website_item.js b/erpnext/e_commerce/doctype/website_item/website_item.js new file mode 100644 index 00000000000..741e78f4a55 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/website_item.js @@ -0,0 +1,24 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Website Item', { + onload: function(frm) { + // should never check Private + frm.fields_dict["website_image"].df.is_private = 0; + }, + + image: function() { + refresh_field("image_view"); + }, + + copy_from_item_group: function(frm) { + return frm.call({ + doc: frm.doc, + method: "copy_specification_from_item_group" + }); + }, + + set_meta_tags(frm) { + frappe.utils.set_meta_tag(frm.doc.route); + } +}); diff --git a/erpnext/e_commerce/doctype/website_item/website_item.json b/erpnext/e_commerce/doctype/website_item/website_item.json new file mode 100644 index 00000000000..245042addb8 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/website_item.json @@ -0,0 +1,415 @@ +{ + "actions": [], + "allow_guest_to_view": 1, + "allow_import": 1, + "autoname": "naming_series", + "creation": "2021-02-09 21:06:14.441698", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "naming_series", + "web_item_name", + "route", + "has_variants", + "variant_of", + "published", + "column_break_3", + "item_code", + "item_name", + "item_group", + "stock_uom", + "column_break_11", + "description", + "brand", + "image", + "display_section", + "website_image", + "website_image_alt", + "column_break_13", + "slideshow", + "thumbnail", + "stock_information_section", + "website_warehouse", + "column_break_24", + "on_backorder", + "section_break_17", + "short_description", + "web_long_description", + "column_break_27", + "website_specifications", + "copy_from_item_group", + "display_additional_information_section", + "show_tabbed_section", + "tabs", + "recommended_items_section", + "recommended_items", + "offers_section", + "offers", + "section_break_6", + "ranking", + "set_meta_tags", + "column_break_22", + "website_item_groups", + "advanced_display_section", + "website_content" + ], + "fields": [ + { + "description": "Website display name", + "fetch_from": "item_code.item_name", + "fetch_if_empty": 1, + "fieldname": "web_item_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Website Item Name", + "reqd": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "item_code", + "fieldtype": "Link", + "label": "Item Code", + "options": "Item", + "read_only_depends_on": "eval:!doc.__islocal", + "reqd": 1 + }, + { + "fetch_from": "item_code.item_name", + "fieldname": "item_name", + "fieldtype": "Data", + "label": "Item Name", + "read_only": 1 + }, + { + "collapsible": 1, + "fieldname": "section_break_6", + "fieldtype": "Section Break", + "label": "Search and SEO" + }, + { + "fieldname": "route", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Route", + "no_copy": 1 + }, + { + "description": "Items with higher ranking will be shown higher", + "fieldname": "ranking", + "fieldtype": "Int", + "label": "Ranking" + }, + { + "description": "Show a slideshow at the top of the page", + "fieldname": "slideshow", + "fieldtype": "Link", + "label": "Slideshow", + "options": "Website Slideshow" + }, + { + "description": "Item Image (if not slideshow)", + "fieldname": "website_image", + "fieldtype": "Attach", + "label": "Website Image" + }, + { + "description": "Image Alternative Text", + "fieldname": "website_image_alt", + "fieldtype": "Data", + "label": "Image Description" + }, + { + "fieldname": "thumbnail", + "fieldtype": "Data", + "label": "Thumbnail", + "read_only": 1 + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "description": "Show Stock availability based on this warehouse.", + "fieldname": "website_warehouse", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Website Warehouse", + "options": "Warehouse" + }, + { + "description": "List this Item in multiple groups on the website.", + "fieldname": "website_item_groups", + "fieldtype": "Table", + "label": "Website Item Groups", + "options": "Website Item Group" + }, + { + "fieldname": "set_meta_tags", + "fieldtype": "Button", + "label": "Set Meta Tags" + }, + { + "fieldname": "section_break_17", + "fieldtype": "Section Break", + "label": "Display Information" + }, + { + "fieldname": "copy_from_item_group", + "fieldtype": "Button", + "label": "Copy From Item Group" + }, + { + "fieldname": "website_specifications", + "fieldtype": "Table", + "label": "Website Specifications", + "options": "Item Website Specification" + }, + { + "fieldname": "web_long_description", + "fieldtype": "Text Editor", + "label": "Website Description" + }, + { + "description": "You can use any valid Bootstrap 4 markup in this field. It will be shown on your Item Page.", + "fieldname": "website_content", + "fieldtype": "HTML Editor", + "label": "Website Content" + }, + { + "fetch_from": "item_code.item_group", + "fieldname": "item_group", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Group", + "options": "Item Group", + "read_only": 1 + }, + { + "fieldname": "image", + "fieldtype": "Attach Image", + "hidden": 1, + "in_preview": 1, + "label": "Image", + "print_hide": 1 + }, + { + "default": "1", + "fieldname": "published", + "fieldtype": "Check", + "label": "Published" + }, + { + "default": "0", + "depends_on": "has_variants", + "fetch_from": "item_code.has_variants", + "fieldname": "has_variants", + "fieldtype": "Check", + "in_standard_filter": 1, + "label": "Has Variants", + "no_copy": 1, + "read_only": 1 + }, + { + "depends_on": "variant_of", + "fetch_from": "item_code.variant_of", + "fieldname": "variant_of", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "in_standard_filter": 1, + "label": "Variant Of", + "options": "Item", + "read_only": 1, + "search_index": 1, + "set_only_once": 1 + }, + { + "fetch_from": "item_code.stock_uom", + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Stock UOM", + "options": "UOM", + "read_only": 1 + }, + { + "depends_on": "brand", + "fetch_from": "item_code.brand", + "fieldname": "brand", + "fieldtype": "Link", + "label": "Brand", + "options": "Brand" + }, + { + "collapsible": 1, + "fieldname": "advanced_display_section", + "fieldtype": "Section Break", + "label": "Advanced Display Content" + }, + { + "fieldname": "display_section", + "fieldtype": "Section Break", + "label": "Display Images" + }, + { + "fieldname": "column_break_27", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_22", + "fieldtype": "Column Break" + }, + { + "fetch_from": "item_code.description", + "fieldname": "description", + "fieldtype": "Text Editor", + "label": "Item Description", + "read_only": 1 + }, + { + "default": "WEB-ITM-.####", + "fieldname": "naming_series", + "fieldtype": "Select", + "hidden": 1, + "label": "Naming Series", + "no_copy": 1, + "options": "WEB-ITM-.####", + "print_hide": 1 + }, + { + "fieldname": "display_additional_information_section", + "fieldtype": "Section Break", + "label": "Display Additional Information" + }, + { + "depends_on": "show_tabbed_section", + "fieldname": "tabs", + "fieldtype": "Table", + "label": "Tabs", + "options": "Website Item Tabbed Section" + }, + { + "default": "0", + "fieldname": "show_tabbed_section", + "fieldtype": "Check", + "label": "Add Section with Tabs" + }, + { + "collapsible": 1, + "fieldname": "offers_section", + "fieldtype": "Section Break", + "label": "Offers" + }, + { + "fieldname": "offers", + "fieldtype": "Table", + "label": "Offers to Display", + "options": "Website Offer" + }, + { + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, + { + "description": "Short Description for List View", + "fieldname": "short_description", + "fieldtype": "Small Text", + "label": "Short Website Description" + }, + { + "collapsible": 1, + "fieldname": "recommended_items_section", + "fieldtype": "Section Break", + "label": "Recommended Items" + }, + { + "fieldname": "recommended_items", + "fieldtype": "Table", + "label": "Recommended/Similar Items", + "options": "Recommended Items" + }, + { + "fieldname": "stock_information_section", + "fieldtype": "Section Break", + "label": "Stock Information" + }, + { + "fieldname": "column_break_24", + "fieldtype": "Column Break" + }, + { + "default": "0", + "description": "Indicate that Item is available on backorder and not usually pre-stocked", + "fieldname": "on_backorder", + "fieldtype": "Check", + "label": "On Backorder" + } + ], + "has_web_view": 1, + "image_field": "image", + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-09-02 13:08:41.942726", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Website Item", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Website Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock Manager", + "share": 1, + "write": 1 + } + ], + "search_fields": "web_item_name, item_code, item_group", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "web_item_name", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py new file mode 100644 index 00000000000..0608486da95 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/website_item.py @@ -0,0 +1,528 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import itertools +import json + +import frappe +from frappe import _ +from frappe.utils import cint, cstr, flt, random_string +from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow +from frappe.website.website_generator import WebsiteGenerator + +from erpnext.e_commerce.doctype.item_review.item_review import get_item_reviews + +# SEARCH +from erpnext.e_commerce.redisearch import ( + delete_item_from_index, + insert_item_to_index, + update_index_for_item, +) +from erpnext.e_commerce.shopping_cart.cart import _set_price_list +from erpnext.setup.doctype.item_group.item_group import ( + get_parent_item_groups, + invalidate_cache_for, +) +from erpnext.utilities.product import get_price + + +class WebsiteItem(WebsiteGenerator): + website = frappe._dict( + page_title_field="web_item_name", + condition_field="published", + template="templates/generators/item/item.html", + no_cache=1 + ) + + def onload(self): + super(WebsiteItem, self).onload() + + def validate(self): + super(WebsiteItem, self).validate() + + if not self.item_code: + frappe.throw(_("Item Code is required"), title=_("Mandatory")) + + self.validate_duplicate_website_item() + self.validate_website_image() + self.make_thumbnail() + self.publish_unpublish_desk_item(publish=True) + + if not self.get("__islocal"): + self.old_website_item_groups = frappe.db.sql_list(""" + select + item_group + from + `tabWebsite Item Group` + where + parentfield='website_item_groups' + and parenttype='Website Item' + and parent=%s + """, self.name) + + def on_update(self): + invalidate_cache_for_web_item(self) + self.update_template_item() + + def on_trash(self): + super(WebsiteItem, self).on_trash() + delete_item_from_index(self) + self.publish_unpublish_desk_item(publish=False) + + def validate_duplicate_website_item(self): + existing_web_item = frappe.db.exists("Website Item", {"item_code": self.item_code}) + if existing_web_item and existing_web_item != self.name: + message = _("Website Item already exists against Item {0}").format(frappe.bold(self.item_code)) + frappe.throw(message, title=_("Already Published")) + + def publish_unpublish_desk_item(self, publish=True): + if frappe.db.get_value("Item", self.item_code, "published_in_website") and publish: + return # if already published don't publish again + frappe.db.set_value("Item", self.item_code, "published_in_website", publish) + + def make_route(self): + """Called from set_route in WebsiteGenerator.""" + if not self.route: + return cstr(frappe.db.get_value('Item Group', self.item_group, + 'route')) + '/' + self.scrub((self.item_name if self.item_name else self.item_code) + '-' + random_string(5)) + + def update_template_item(self): + """Publish Template Item if Variant is published.""" + if self.variant_of: + if self.published: + # show template + template_item = frappe.get_doc("Item", self.variant_of) + + if not template_item.published_in_website: + template_item.flags.ignore_permissions = True + make_website_item(template_item) + + def validate_website_image(self): + if frappe.flags.in_import: + return + + """Validate if the website image is a public file""" + auto_set_website_image = False + if not self.website_image and self.image: + auto_set_website_image = True + self.website_image = self.image + + if not self.website_image: + return + + # find if website image url exists as public + file_doc = frappe.get_all( + "File", + filters={ + "file_url": self.website_image + }, + fields=["name", "is_private"], + order_by="is_private asc", + limit_page_length=1 + ) + + if file_doc: + file_doc = file_doc[0] + + if not file_doc: + if not auto_set_website_image: + frappe.msgprint(_("Website Image {0} attached to Item {1} cannot be found").format(self.website_image, self.name)) + + self.website_image = None + + elif file_doc.is_private: + if not auto_set_website_image: + frappe.msgprint(_("Website Image should be a public file or website URL")) + + self.website_image = None + + def make_thumbnail(self): + if frappe.flags.in_import: + return + + """Make a thumbnail of `website_image`""" + import requests.exceptions + + if not self.is_new() and self.website_image != frappe.db.get_value(self.doctype, self.name, "website_image"): + self.thumbnail = None + + if self.website_image and not self.thumbnail: + file_doc = None + + try: + file_doc = frappe.get_doc("File", { + "file_url": self.website_image, + "attached_to_doctype": "Website Item", + "attached_to_name": self.name + }) + except frappe.DoesNotExistError: + pass + # cleanup + frappe.local.message_log.pop() + + except requests.exceptions.HTTPError: + frappe.msgprint(_("Warning: Invalid attachment {0}").format(self.website_image)) + self.website_image = None + + except requests.exceptions.SSLError: + frappe.msgprint( + _("Warning: Invalid SSL certificate on attachment {0}").format(self.website_image)) + self.website_image = None + + # for CSV import + if self.website_image and not file_doc: + try: + file_doc = frappe.get_doc({ + "doctype": "File", + "file_url": self.website_image, + "attached_to_doctype": "Website Item", + "attached_to_name": self.name + }).save() + + except IOError: + self.website_image = None + + if file_doc: + if not file_doc.thumbnail_url: + file_doc.make_thumbnail() + + self.thumbnail = file_doc.thumbnail_url + + def get_context(self, context): + context.show_search = True + context.search_link = "/search" + context.body_class = "product-page" + + context.parents = get_parent_item_groups(self.item_group, from_item=True) # breadcumbs + self.attributes = frappe.get_all("Item Variant Attribute", + fields=["attribute", "attribute_value"], + filters={"parent": self.item_code}) + + if self.slideshow: + context.update(get_slideshow(self)) + + self.set_variant_context(context) + self.set_attribute_context(context) + self.set_disabled_attributes(context) + self.set_metatags(context) + self.set_shopping_cart_data(context) + + settings = context.shopping_cart.cart_settings + + self.get_product_details_section(context) + + if settings.enable_reviews: + reviews_data = get_item_reviews(self.name) + context.update(reviews_data) + context.reviews = context.reviews[:4] + + context.wished = False + if frappe.db.exists("Wishlist Item", {"item_code": self.item_code, "parent": frappe.session.user}): + context.wished = True + + context.user_is_customer = check_if_user_is_customer() + + context.recommended_items = None + if settings and settings.enable_recommendations: + context.recommended_items = self.get_recommended_items(settings) + + return context + + def set_variant_context(self, context): + if not self.has_variants: + return + + context.no_cache = True + variant = frappe.form_dict.variant + + # load variants + # also used in set_attribute_context + context.variants = frappe.get_all( + "Item", + filters={ + "variant_of": self.item_code, + "published_in_website": 1 + }, + order_by="name asc") + + # the case when the item is opened for the first time from its list + if not variant and context.variants: + variant = context.variants[0] + + if variant: + context.variant = frappe.get_doc("Item", variant) + fields = ("website_image", "website_image_alt", "web_long_description", "description", + "website_specifications") + + for fieldname in fields: + if context.variant.get(fieldname): + value = context.variant.get(fieldname) + if isinstance(value, list): + value = [d.as_dict() for d in value] + + context[fieldname] = value + + if self.slideshow and context.variant and context.variant.slideshow: + context.update(get_slideshow(context.variant)) + + + def set_attribute_context(self, context): + if not self.has_variants: + return + + attribute_values_available = {} + context.attribute_values = {} + context.selected_attributes = {} + + # load attributes + self.set_selected_attributes(context.variants, context, attribute_values_available) + + # filter attributes, order based on attribute table + item = frappe.get_cached_doc("Item", self.item_code) + self.set_attribute_values(item.attributes, context, attribute_values_available) + + context.variant_info = json.dumps(context.variants) + + def set_selected_attributes(self, variants, context, attribute_values_available): + for variant in variants: + variant.attributes = frappe.get_all( + "Item Variant Attribute", + filters={"parent": variant.name}, + fields=["attribute", "attribute_value as value"]) + + # make an attribute-value map for easier access in templates + variant.attribute_map = frappe._dict( + {attr.attribute : attr.value for attr in variant.attributes} + ) + + for attr in variant.attributes: + values = attribute_values_available.setdefault(attr.attribute, []) + if attr.value not in values: + values.append(attr.value) + + if variant.name == context.variant.name: + context.selected_attributes[attr.attribute] = attr.value + + def set_attribute_values(self, attributes, context, attribute_values_available): + for attr in attributes: + values = context.attribute_values.setdefault(attr.attribute, []) + + if cint(frappe.db.get_value("Item Attribute", attr.attribute, "numeric_values")): + for val in sorted(attribute_values_available.get(attr.attribute, []), key=flt): + values.append(val) + else: + # get list of values defined (for sequence) + for attr_value in frappe.db.get_all("Item Attribute Value", + fields=["attribute_value"], + filters={"parent": attr.attribute}, order_by="idx asc"): + + if attr_value.attribute_value in attribute_values_available.get(attr.attribute, []): + values.append(attr_value.attribute_value) + + def set_disabled_attributes(self, context): + """Disable selection options of attribute combinations that do not result in a variant""" + + if not self.attributes or not self.has_variants: + return + + context.disabled_attributes = {} + attributes = [attr.attribute for attr in self.attributes] + + def find_variant(combination): + for variant in context.variants: + if len(variant.attributes) < len(attributes): + continue + + if "combination" not in variant: + ref_combination = [] + + for attr in variant.attributes: + idx = attributes.index(attr.attribute) + ref_combination.insert(idx, attr.attribute_value) + + variant["combination"] = ref_combination + + if not (set(combination) - set(variant["combination"])): + # check if the combination is a subset of a variant combination + # eg. [Blue, 0.5] is a possible combination if exists [Blue, Large, 0.5] + return True + + for i, attr in enumerate(self.attributes): + if i == 0: + continue + + combination_source = [] + + # loop through previous attributes + for prev_attr in self.attributes[:i]: + combination_source.append([context.selected_attributes.get(prev_attr.attribute)]) + + combination_source.append(context.attribute_values[attr.attribute]) + + for combination in itertools.product(*combination_source): + if not find_variant(combination): + context.disabled_attributes.setdefault(attr.attribute, []).append(combination[-1]) + + def set_metatags(self, context): + context.metatags = frappe._dict({}) + + safe_description = frappe.utils.to_markdown(self.description) + + context.metatags.url = frappe.utils.get_url() + '/' + context.route + + if context.website_image: + if context.website_image.startswith('http'): + url = context.website_image + else: + url = frappe.utils.get_url() + context.website_image + context.metatags.image = url + + context.metatags.description = safe_description[:300] + + context.metatags.title = self.web_item_name or self.item_name or self.item_code + + context.metatags['og:type'] = 'product' + context.metatags['og:site_name'] = 'ERPNext' + + def set_shopping_cart_data(self, context): + from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website + context.shopping_cart = get_product_info_for_website(self.item_code, skip_quotation_creation=True) + + @frappe.whitelist() + def copy_specification_from_item_group(self): + self.set("website_specifications", []) + if self.item_group: + for label, desc in frappe.db.get_values("Item Website Specification", + {"parent": self.item_group}, ["label", "description"]): + row = self.append("website_specifications") + row.label = label + row.description = desc + + def get_product_details_section(self, context): + """ Get section with tabs or website specifications. """ + context.show_tabs = self.show_tabbed_section + if self.show_tabbed_section and (self.tabs or self.website_specifications): + context.tabs = self.get_tabs() + else: + context.website_specifications = self.website_specifications + + def get_tabs(self): + tab_values = {} + tab_values["tab_1_title"] = "Product Details" + tab_values["tab_1_content"] = frappe.render_template( + "templates/generators/item/item_specifications.html", + { + "website_specifications": self.website_specifications, + "show_tabs": self.show_tabbed_section + }) + + for row in self.tabs: + tab_values[f"tab_{row.idx + 1}_title"] = _(row.label) + tab_values[f"tab_{row.idx + 1}_content"] = row.content + + return tab_values + + def get_recommended_items(self, settings): + items = frappe.db.sql(f""" + select + ri.website_item_thumbnail, ri.website_item_name, + ri.route, ri.item_code + from + `tabRecommended Items` ri, `tabWebsite Item` wi + where + ri.item_code = wi.item_code + and ri.parent = '{self.name}' + and wi.published = 1 + order by ri.idx + """, as_dict=1) + + if settings.show_price: + is_guest = frappe.session.user == "Guest" + # Show Price if logged in. + # If not logged in and price is hidden for guest, skip price fetch. + if is_guest and settings.hide_price_for_guest: + return items + + selling_price_list = _set_price_list(settings, None) + for item in items: + item.price_info = get_price( + item.item_code, + selling_price_list, + settings.default_customer_group, + settings.company + ) + + return items + +def invalidate_cache_for_web_item(doc): + """Invalidate Website Item Group cache and rebuild ItemVariantsCacheManager.""" + from erpnext.stock.doctype.item.item import invalidate_item_variants_cache_for_website + + invalidate_cache_for(doc, doc.item_group) + + website_item_groups = list(set((doc.get("old_website_item_groups") or []) + + [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group])) + + for item_group in website_item_groups: + invalidate_cache_for(doc, item_group) + + # Update Search Cache + update_index_for_item(doc) + + invalidate_item_variants_cache_for_website(doc) + +def on_doctype_update(): + # since route is a Text column, it needs a length for indexing + frappe.db.add_index("Website Item", ["route(500)"]) + + frappe.db.add_index("Website Item", ["item_group"]) + frappe.db.add_index("Website Item", ["brand"]) + +def check_if_user_is_customer(user=None): + from frappe.contacts.doctype.contact.contact import get_contact_name + + if not user: + user = frappe.session.user + + contact_name = get_contact_name(user) + customer = None + + if contact_name: + contact = frappe.get_doc('Contact', contact_name) + for link in contact.links: + if link.link_doctype == "Customer": + customer = link.link_name + break + + return True if customer else False + +@frappe.whitelist() +def make_website_item(doc, save=True): + if not doc: + return + + if isinstance(doc, str): + doc = json.loads(doc) + + if frappe.db.exists("Website Item", {"item_code": doc.get("item_code")}): + message = _("Website Item already exists against {0}").format(frappe.bold(doc.get("item_code"))) + frappe.throw(message, title=_("Already Published")) + + website_item = frappe.new_doc("Website Item") + website_item.web_item_name = doc.get("item_name") + + fields_to_map = ["item_code", "item_name", "item_group", "stock_uom", "brand", "image", + "has_variants", "variant_of", "description"] + for field in fields_to_map: + website_item.update({field: doc.get(field)}) + + if not save: + return website_item + + website_item.save() + + # Add to search cache + insert_item_to_index(website_item) + + return [website_item.name, website_item.web_item_name] \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_item/website_item_list.js b/erpnext/e_commerce/doctype/website_item/website_item_list.js new file mode 100644 index 00000000000..21be9428eb6 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item/website_item_list.js @@ -0,0 +1,20 @@ +frappe.listview_settings['Website Item'] = { + add_fields: ["item_name", "web_item_name", "published", "image", "has_variants", "variant_of"], + filters: [["published", "=", "1"]], + + get_indicator: function(doc) { + if (doc.has_variants && doc.published) { + return [__("Template"), "orange", "has_variants,=,Yes|published,=,1"]; + } else if (doc.has_variants && !doc.published) { + return [__("Template"), "grey", "has_variants,=,Yes|published,=,0"]; + } else if (doc.variant_of && doc.published) { + return [__("Variant"), "blue", "published,=,1|variant_of,=," + doc.variant_of]; + } else if (doc.variant_of && !doc.published) { + return [__("Variant"), "grey", "published,=,0|variant_of,=," + doc.variant_of]; + } else if (doc.published) { + return [__("Published"), "green", "published,=,1"]; + } else { + return [__("Not Published"), "grey", "published,=,0"]; + } + } +}; \ No newline at end of file diff --git a/erpnext/shopping_cart/web_template/product_card/product_card.html b/erpnext/e_commerce/doctype/website_item_tabbed_section/__init__.py similarity index 100% rename from erpnext/shopping_cart/web_template/product_card/product_card.html rename to erpnext/e_commerce/doctype/website_item_tabbed_section/__init__.py diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json new file mode 100644 index 00000000000..6601dd81f21 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json @@ -0,0 +1,37 @@ +{ + "actions": [], + "creation": "2021-03-18 20:32:15.321402", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "label", + "content" + ], + "fields": [ + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label" + }, + { + "fieldname": "content", + "fieldtype": "HTML Editor", + "in_list_view": 1, + "label": "Content" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-03-18 20:35:26.991192", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Website Item Tabbed Section", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py new file mode 100644 index 00000000000..6a1bf4d5098 --- /dev/null +++ b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, 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 WebsiteItemTabbedSection(Document): + pass diff --git a/erpnext/e_commerce/doctype/website_offer/__init__.py b/erpnext/e_commerce/doctype/website_offer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/doctype/website_offer/website_offer.json b/erpnext/e_commerce/doctype/website_offer/website_offer.json new file mode 100644 index 00000000000..627d548146b --- /dev/null +++ b/erpnext/e_commerce/doctype/website_offer/website_offer.json @@ -0,0 +1,43 @@ +{ + "actions": [], + "creation": "2021-04-21 13:37:14.162162", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "offer_title", + "offer_subtitle", + "offer_details" + ], + "fields": [ + { + "fieldname": "offer_title", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Offer Title" + }, + { + "fieldname": "offer_subtitle", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Offer Subtitle" + }, + { + "fieldname": "offer_details", + "fieldtype": "Text Editor", + "label": "Offer Details" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-04-21 13:56:04.660331", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Website Offer", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/website_offer/website_offer.py b/erpnext/e_commerce/doctype/website_offer/website_offer.py new file mode 100644 index 00000000000..2e0b84831db --- /dev/null +++ b/erpnext/e_commerce/doctype/website_offer/website_offer.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, 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 WebsiteOffer(Document): + pass + +@frappe.whitelist(allow_guest=True) +def get_offer_details(offer_id): + return frappe.db.get_value('Website Offer', {'name': offer_id}, ['offer_details']) diff --git a/erpnext/e_commerce/doctype/wishlist/__init__.py b/erpnext/e_commerce/doctype/wishlist/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py new file mode 100644 index 00000000000..504bb658113 --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +import unittest + +import frappe +from frappe.core.doctype.user_permission.test_user_permission import create_user + +from erpnext.e_commerce.doctype.website_item.website_item import make_website_item +from erpnext.e_commerce.doctype.wishlist.wishlist import add_to_wishlist, remove_from_wishlist +from erpnext.stock.doctype.item.test_item import make_item + + +class TestWishlist(unittest.TestCase): + def setUp(self): + item = make_item("Test Phone Series X") + if not frappe.db.exists("Website Item", {"item_code": "Test Phone Series X"}): + make_website_item(item, save=True) + + item = make_item("Test Phone Series Y") + if not frappe.db.exists("Website Item", {"item_code": "Test Phone Series Y"}): + make_website_item(item, save=True) + + def tearDown(self): + frappe.get_cached_doc("Website Item", {"item_code": "Test Phone Series X"}).delete() + frappe.get_cached_doc("Website Item", {"item_code": "Test Phone Series Y"}).delete() + frappe.get_cached_doc("Item", "Test Phone Series X").delete() + frappe.get_cached_doc("Item", "Test Phone Series Y").delete() + + def test_add_remove_items_in_wishlist(self): + "Check if items are added and removed from user's wishlist." + # add first item + add_to_wishlist("Test Phone Series X") + + # check if wishlist was created and item was added + self.assertTrue(frappe.db.exists("Wishlist", {"user": frappe.session.user})) + self.assertTrue(frappe.db.exists("Wishlist Item", {"item_code": "Test Phone Series X", "parent": frappe.session.user})) + + # add second item to wishlist + add_to_wishlist("Test Phone Series Y") + wishlist_length = frappe.db.get_value( + "Wishlist Item", + {"parent": frappe.session.user}, + "count(*)" + ) + self.assertEqual(wishlist_length, 2) + + remove_from_wishlist("Test Phone Series X") + remove_from_wishlist("Test Phone Series Y") + + wishlist_length = frappe.db.get_value( + "Wishlist Item", + {"parent": frappe.session.user}, + "count(*)" + ) + self.assertIsNone(frappe.db.exists("Wishlist Item", {"parent": frappe.session.user})) + self.assertEqual(wishlist_length, 0) + + # tear down + frappe.get_doc("Wishlist", {"user": frappe.session.user}).delete() + + def test_add_remove_in_wishlist_multiple_users(self): + "Check if items are added and removed from the correct user's wishlist." + test_user = create_user("test_reviewer@example.com", "Customer") + test_user_1 = create_user("test_reviewer_1@example.com", "Customer") + + # add to wishlist for first user + frappe.set_user(test_user.name) + add_to_wishlist("Test Phone Series X") + + # add to wishlist for second user + frappe.set_user(test_user_1.name) + add_to_wishlist("Test Phone Series X") + + # check wishlist and its content for users + self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user.name})) + self.assertTrue(frappe.db.exists("Wishlist Item", + {"item_code": "Test Phone Series X", "parent": test_user.name})) + + self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user_1.name})) + self.assertTrue(frappe.db.exists("Wishlist Item", + {"item_code": "Test Phone Series X", "parent": test_user_1.name})) + + # remove item for second user + remove_from_wishlist("Test Phone Series X") + + # make sure item was removed for second user and not first + self.assertFalse(frappe.db.exists("Wishlist Item", + {"item_code": "Test Phone Series X", "parent": test_user_1.name})) + self.assertTrue(frappe.db.exists("Wishlist Item", + {"item_code": "Test Phone Series X", "parent": test_user.name})) + + # remove item for first user + frappe.set_user(test_user.name) + remove_from_wishlist("Test Phone Series X") + self.assertFalse(frappe.db.exists("Wishlist Item", + {"item_code": "Test Phone Series X", "parent": test_user.name})) + + # tear down + frappe.set_user("Administrator") + frappe.get_doc("Wishlist", {"user": test_user.name}).delete() + frappe.get_doc("Wishlist", {"user": test_user_1.name}).delete() \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.js b/erpnext/e_commerce/doctype/wishlist/wishlist.js new file mode 100644 index 00000000000..d96e552ecdb --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Wishlist', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.json b/erpnext/e_commerce/doctype/wishlist/wishlist.json new file mode 100644 index 00000000000..922924e53b0 --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.json @@ -0,0 +1,65 @@ +{ + "actions": [], + "autoname": "field:user", + "creation": "2021-03-10 18:52:28.769126", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "user", + "section_break_2", + "items" + ], + "fields": [ + { + "fieldname": "user", + "fieldtype": "Link", + "in_list_view": 1, + "label": "User", + "options": "User", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "section_break_2", + "fieldtype": "Section Break" + }, + { + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "options": "Wishlist Item" + } + ], + "in_create": 1, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-07-08 13:11:21.693956", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Wishlist", + "owner": "Administrator", + "permissions": [ + { + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1 + }, + { + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Website Manager", + "share": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.py b/erpnext/e_commerce/doctype/wishlist/wishlist.py new file mode 100644 index 00000000000..0973e1ed5f3 --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, 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 Wishlist(Document): + pass + +@frappe.whitelist() +def add_to_wishlist(item_code): + """Insert Item into wishlist.""" + + if frappe.db.exists("Wishlist Item", {"item_code": item_code, "parent": frappe.session.user}): + return + + web_item_data = frappe.db.get_value( + "Website Item", + {"item_code": item_code}, + ["image", "website_warehouse", "name", "web_item_name", "item_name", "item_group", "route"], + as_dict=1) + + wished_item_dict = { + "item_code": item_code, + "item_name": web_item_data.get("item_name"), + "item_group": web_item_data.get("item_group"), + "website_item": web_item_data.get("name"), + "web_item_name": web_item_data.get("web_item_name"), + "image": web_item_data.get("image"), + "warehouse": web_item_data.get("website_warehouse"), + "route": web_item_data.get("route") + } + + if not frappe.db.exists("Wishlist", frappe.session.user): + # initialise wishlist + wishlist = frappe.get_doc({"doctype": "Wishlist"}) + wishlist.user = frappe.session.user + wishlist.append("items", wished_item_dict) + wishlist.save(ignore_permissions=True) + else: + wishlist = frappe.get_doc("Wishlist", frappe.session.user) + item = wishlist.append('items', wished_item_dict) + item.db_insert() + + if hasattr(frappe.local, "cookie_manager"): + frappe.local.cookie_manager.set_cookie("wish_count", str(len(wishlist.items))) + +@frappe.whitelist() +def remove_from_wishlist(item_code): + if frappe.db.exists("Wishlist Item", {"item_code": item_code, "parent": frappe.session.user}): + frappe.db.delete( + "Wishlist Item", + { + "item_code": item_code, + "parent": frappe.session.user + } + ) + frappe.db.commit() + + wishlist_items = frappe.db.get_values( + "Wishlist Item", + filters={"parent": frappe.session.user} + ) + + if hasattr(frappe.local, "cookie_manager"): + frappe.local.cookie_manager.set_cookie("wish_count", str(len(wishlist_items))) \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist_item/__init__.py b/erpnext/e_commerce/doctype/wishlist_item/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json new file mode 100644 index 00000000000..c0414a7f8ed --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json @@ -0,0 +1,147 @@ +{ + "actions": [], + "creation": "2021-03-10 19:03:00.662714", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_code", + "website_item", + "web_item_name", + "column_break_3", + "item_name", + "item_group", + "item_details_section", + "description", + "column_break_7", + "route", + "image", + "image_view", + "section_break_8", + "warehouse_section", + "warehouse" + ], + "fields": [ + { + "fetch_from": "website_item.item_code", + "fetch_if_empty": 1, + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1 + }, + { + "fieldname": "website_item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Website Item", + "options": "Website Item", + "read_only": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fetch_from": "item_code.item_name", + "fetch_if_empty": 1, + "fieldname": "item_name", + "fieldtype": "Data", + "label": "Item Name", + "read_only": 1 + }, + { + "collapsible": 1, + "fieldname": "item_details_section", + "fieldtype": "Section Break", + "label": "Item Details", + "read_only": 1 + }, + { + "fetch_from": "item_code.description", + "fetch_if_empty": 1, + "fieldname": "description", + "fieldtype": "Text Editor", + "label": "Description", + "read_only": 1 + }, + { + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, + { + "fetch_from": "item_code.image", + "fetch_if_empty": 1, + "fieldname": "image", + "fieldtype": "Attach", + "hidden": 1, + "label": "Image" + }, + { + "fetch_from": "item_code.image", + "fetch_if_empty": 1, + "fieldname": "image_view", + "fieldtype": "Image", + "hidden": 1, + "label": "Image View", + "options": "image", + "print_hide": 1 + }, + { + "fieldname": "warehouse_section", + "fieldtype": "Section Break", + "label": "Warehouse" + }, + { + "fieldname": "warehouse", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Warehouse", + "options": "Warehouse", + "read_only": 1 + }, + { + "fieldname": "section_break_8", + "fieldtype": "Section Break" + }, + { + "fetch_from": "item_code.item_group", + "fetch_if_empty": 1, + "fieldname": "item_group", + "fieldtype": "Link", + "label": "Item Group", + "options": "Item Group", + "read_only": 1 + }, + { + "fetch_from": "website_item.route", + "fetch_if_empty": 1, + "fieldname": "route", + "fieldtype": "Small Text", + "label": "Route", + "read_only": 1 + }, + { + "fetch_from": "website_item.web_item_name", + "fetch_if_empty": 1, + "fieldname": "web_item_name", + "fieldtype": "Data", + "label": "Website Item Name", + "read_only": 1 + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-08-09 10:30:41.964802", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Wishlist Item", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py new file mode 100644 index 00000000000..b0455808f5e --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, 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 WishlistItem(Document): + pass diff --git a/erpnext/shopping_cart/search.py b/erpnext/e_commerce/legacy_search.py similarity index 93% rename from erpnext/shopping_cart/search.py rename to erpnext/e_commerce/legacy_search.py index 9f674dcebf8..752c33e92ee 100644 --- a/erpnext/shopping_cart/search.py +++ b/erpnext/e_commerce/legacy_search.py @@ -1,11 +1,12 @@ import frappe from frappe.search.full_text_search import FullTextSearch -from whoosh.fields import TEXT, ID, KEYWORD, Schema from frappe.utils import strip_html_tags -from whoosh.qparser import MultifieldParser, FieldsPlugin, WildcardPlugin from whoosh.analysis import StemmingAnalyzer +from whoosh.fields import ID, KEYWORD, TEXT, Schema +from whoosh.qparser import FieldsPlugin, MultifieldParser, WildcardPlugin from whoosh.query import Prefix +# TODO: Make obsolete INDEX_NAME = "products" class ProductSearch(FullTextSearch): @@ -111,7 +112,7 @@ class ProductSearch(FullTextSearch): ) def get_all_published_items(): - return frappe.get_all("Item", filters={"variant_of": "", "show_in_website": 1},pluck="name") + return frappe.get_all("Website Item", filters={"variant_of": "", "published": 1}, pluck="item_code") def update_index_for_path(path): search = ProductSearch(INDEX_NAME) diff --git a/erpnext/e_commerce/product_data_engine/filters.py b/erpnext/e_commerce/product_data_engine/filters.py new file mode 100644 index 00000000000..f9e3b6ae32e --- /dev/null +++ b/erpnext/e_commerce/product_data_engine/filters.py @@ -0,0 +1,150 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt +import frappe +from frappe import _dict +from frappe.utils import floor + + +class ProductFiltersBuilder: + def __init__(self, item_group=None): + if not item_group: + self.doc = frappe.get_doc("E Commerce Settings") + else: + self.doc = frappe.get_doc("Item Group", item_group) + + self.item_group = item_group + + def get_field_filters(self): + if not self.item_group and not self.doc.enable_field_filters: + return + + fields, filter_data = [], [] + filter_fields = [row.fieldname for row in self.doc.filter_fields] # fields in settings + + # filter valid field filters i.e. those that exist in Item + item_meta = frappe.get_meta('Item', cached=True) + fields = [item_meta.get_field(field) for field in filter_fields if item_meta.has_field(field)] + + for df in fields: + item_filters, item_or_filters = {}, [] + link_doctype_values = self.get_filtered_link_doctype_records(df) + + if df.fieldtype == "Link": + if self.item_group: + item_or_filters.extend([ + ["item_group", "=", self.item_group], + ["Website Item Group", "item_group", "=", self.item_group] # consider website item groups + ]) + + # Get link field values attached to published items + item_filters['published_in_website'] = 1 + item_values = frappe.get_all( + "Item", + fields=[df.fieldname], + filters=item_filters, + or_filters=item_or_filters, + distinct="True", + pluck=df.fieldname + ) + + values = list(set(item_values) & link_doctype_values) # intersection of both + else: + # table multiselect + values = list(link_doctype_values) + + # Remove None + if None in values: + values.remove(None) + + if values: + filter_data.append([df, values]) + + return filter_data + + def get_filtered_link_doctype_records(self, field): + """ + Get valid link doctype records depending on filters. + Apply enable/disable/show_in_website filter. + Returns: + set: A set containing valid record names + """ + link_doctype = field.get_link_doctype() + meta = frappe.get_meta(link_doctype, cached=True) if link_doctype else None + if meta: + filters = self.get_link_doctype_filters(meta) + link_doctype_values = set(d.name for d in frappe.get_all(link_doctype, filters)) + + return link_doctype_values if meta else set() + + def get_link_doctype_filters(self, meta): + "Filters for Link Doctype eg. 'show_in_website'." + filters = {} + if not meta: + return filters + + if meta.has_field('enabled'): + filters['enabled'] = 1 + if meta.has_field('disabled'): + filters['disabled'] = 0 + if meta.has_field('show_in_website'): + filters['show_in_website'] = 1 + + return filters + + def get_attribute_filters(self): + if not self.item_group and not self.doc.enable_attribute_filters: + return + + attributes = [row.attribute for row in self.doc.filter_attributes] + attribute_docs = [ + frappe.get_doc('Item Attribute', attribute) for attribute in attributes + ] + + valid_attributes = [] + + for attr_doc in attribute_docs: + selected_attributes = [] + for attr in attr_doc.item_attribute_values: + or_filters = [] + filters= [ + ["Item Variant Attribute", "attribute", "=", attr.parent], + ["Item Variant Attribute", "attribute_value", "=", attr.attribute_value] + ] + if self.item_group: + or_filters.extend([ + ["item_group", "=", self.item_group], + ["Website Item Group", "item_group", "=", self.item_group] + ]) + + if frappe.db.get_all("Item", filters, or_filters=or_filters, limit=1): + selected_attributes.append(attr) + + if selected_attributes: + valid_attributes.append( + _dict( + item_attribute_values=selected_attributes, + name=attr_doc.name + ) + ) + + return valid_attributes + + def get_discount_filters(self, discounts): + discount_filters = [] + + # [25.89, 60.5] min max + min_discount, max_discount = discounts[0], discounts[1] + # [25, 60] rounded min max + min_range_absolute, max_range_absolute = floor(min_discount), floor(max_discount) + + min_range = int(min_discount - (min_range_absolute % 10)) # 20 + max_range = int(max_discount - (max_range_absolute % 10)) # 60 + + min_range = (min_range + 10) if min_range != min_range_absolute else min_range # 30 (upper limit of 25.89 in range of 10) + max_range = (max_range + 10) if max_range != max_range_absolute else max_range # 60 + + for discount in range(min_range, (max_range + 1), 10): + label = f"{discount}% and below" + discount_filters.append([discount, label]) + + return discount_filters \ No newline at end of file diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py new file mode 100644 index 00000000000..ddd9987bb92 --- /dev/null +++ b/erpnext/e_commerce/product_data_engine/query.py @@ -0,0 +1,299 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe +from frappe.utils import flt + +from erpnext.e_commerce.doctype.item_review.item_review import get_customer +from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website +from erpnext.utilities.product import get_non_stock_item_status + + +class ProductQuery: + """Query engine for product listing + + Attributes: + fields (list): Fields to fetch in query + conditions (string): Conditions for query building + or_conditions (string): Search conditions + page_length (Int): Length of page for the query + settings (Document): E Commerce Settings DocType + """ + def __init__(self): + self.settings = frappe.get_doc("E Commerce Settings") + self.page_length = self.settings.products_per_page or 20 + + self.or_filters = [] + self.filters = [["published", "=", 1]] + self.fields = [ + "web_item_name", "name", "item_name", "item_code", "website_image", + "variant_of", "has_variants", "item_group", "image", "web_long_description", + "short_description", "route", "website_warehouse", "ranking", "on_backorder" + ] + + def query(self, attributes=None, fields=None, search_term=None, start=0, item_group=None): + """ + Args: + attributes (dict, optional): Item Attribute filters + fields (dict, optional): Field level filters + search_term (str, optional): Search term to lookup + start (int, optional): Page start + + Returns: + dict: Dict containing items, item count & discount range + """ + # track if discounts included in field filters + self.filter_with_discount = bool(fields.get("discount")) + result, discount_list, website_item_groups, cart_items, count = [], [], [], [], 0 + + website_item_groups = self.get_website_item_group_results(item_group, website_item_groups) + + if fields: + self.build_fields_filters(fields) + if search_term: + self.build_search_filters(search_term) + if self.settings.hide_variants: + self.filters.append(["variant_of", "is", "not set"]) + + # query results + if attributes: + result, count = self.query_items_with_attributes(attributes, start) + else: + result, count = self.query_items(start=start) + + result = self.combine_web_item_group_results(item_group, result, website_item_groups) + + # sort combined results by ranking + result = sorted(result, key=lambda x: x.get("ranking"), reverse=True) + + if self.settings.enabled: + cart_items = self.get_cart_items() + + result, discount_list = self.add_display_details(result, discount_list, cart_items) + + discounts = [] + if discount_list: + discounts = [min(discount_list), max(discount_list)] + + result = self.filter_results_by_discount(fields, result) + + return { + "items": result, + "items_count": count, + "discounts": discounts + } + + def query_items(self, start=0): + """Build a query to fetch Website Items based on field filters.""" + # MySQL does not support offset without limit, + # frappe does not accept two parameters for limit + # https://dev.mysql.com/doc/refman/8.0/en/select.html#id4651989 + count_items = frappe.db.get_all( + "Website Item", + filters=self.filters, + or_filters=self.or_filters, + limit_page_length=184467440737095516, + limit_start=start, # get all items from this offset for total count ahead + order_by="ranking desc") + count = len(count_items) + + # If discounts included, return all rows. + # Slice after filtering rows with discount (See `filter_results_by_discount`). + # Slicing before hand will miss discounted items on the 3rd or 4th page. + # Discounts are fetched on computing Pricing Rules so we cannot query them directly. + page_length = 184467440737095516 if self.filter_with_discount else self.page_length + + items = frappe.db.get_all( + "Website Item", + fields=self.fields, + filters=self.filters, + or_filters=self.or_filters, + limit_page_length=page_length, + limit_start=start, + order_by="ranking desc") + + return items, count + + def query_items_with_attributes(self, attributes, start=0): + """Build a query to fetch Website Items based on field & attribute filters.""" + item_codes = [] + + for attribute, values in attributes.items(): + if not isinstance(values, list): + values = [values] + + # get items that have selected attribute & value + item_code_list = frappe.db.get_all( + "Item", + fields=["item_code"], + filters=[ + ["published_in_website", "=", 1], + ["Item Variant Attribute", "attribute", "=", attribute], + ["Item Variant Attribute", "attribute_value", "in", values] + ]) + item_codes.append({x.item_code for x in item_code_list}) + + if item_codes: + item_codes = list(set.intersection(*item_codes)) + self.filters.append(["item_code", "in", item_codes]) + + items, count = self.query_items(start=start) + + return items, count + + def build_fields_filters(self, filters): + """Build filters for field values + + Args: + filters (dict): Filters + """ + for field, values in filters.items(): + if not values or field == "discount": + continue + + # handle multiselect fields in filter addition + meta = frappe.get_meta('Website Item', cached=True) + df = meta.get_field(field) + + if df.fieldtype == 'Table MultiSelect': + child_doctype = df.options + child_meta = frappe.get_meta(child_doctype, cached=True) + fields = child_meta.get("fields") + if fields: + self.filters.append([child_doctype, fields[0].fieldname, 'IN', values]) + elif isinstance(values, list): + # If value is a list use `IN` query + self.filters.append([field, "in", values]) + else: + # `=` will be faster than `IN` for most cases + self.filters.append([field, "=", values]) + + def build_search_filters(self, search_term): + """Query search term in specified fields + + Args: + search_term (str): Search candidate + """ + # Default fields to search from + default_fields = {'item_code', 'item_name', 'web_long_description', 'item_group'} + + # Get meta search fields + meta = frappe.get_meta("Website Item") + meta_fields = set(meta.get_search_fields()) + + # Join the meta fields and default fields set + search_fields = default_fields.union(meta_fields) + if frappe.db.count('Website Item', cache=True) > 50000: + search_fields.discard('web_long_description') + + # Build or filters for query + search = '%{}%'.format(search_term) + for field in search_fields: + self.or_filters.append([field, "like", search]) + + def get_website_item_group_results(self, item_group, website_item_groups): + """Get Web Items for Item Group Page via Website Item Groups.""" + if item_group: + website_item_groups = frappe.db.get_all( + "Website Item", + fields=self.fields + ["`tabWebsite Item Group`.parent as wig_parent"], + filters=[["Website Item Group", "item_group", "=", item_group]] + ) + return website_item_groups + + def add_display_details(self, result, discount_list, cart_items): + """Add price and availability details in result.""" + for item in result: + product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get('product_info') + + if product_info and product_info['price']: + # update/mutate item and discount_list objects + self.get_price_discount_info(item, product_info['price'], discount_list) + + if self.settings.show_stock_availability: + self.get_stock_availability(item) + + item.in_cart = item.item_code in cart_items + + item.wished = False + if frappe.db.exists("Wishlist Item", {"item_code": item.item_code, "parent": frappe.session.user}): + item.wished = True + + return result, discount_list + + def get_price_discount_info(self, item, price_object, discount_list): + """Modify item object and add price details.""" + fields = ["formatted_mrp", "formatted_price", "price_list_rate"] + for field in fields: + item[field] = price_object.get(field) + + if price_object.get('discount_percent'): + item.discount_percent = flt(price_object.discount_percent) + discount_list.append(price_object.discount_percent) + + if item.formatted_mrp: + item.discount = price_object.get('formatted_discount_percent') or \ + price_object.get('formatted_discount_rate') + + def get_stock_availability(self, item): + """Modify item object and add stock details.""" + item.in_stock = False + warehouse = item.get("website_warehouse") + is_stock_item = frappe.get_cached_value("Item", item.item_code, "is_stock_item") + + if item.get("on_backorder"): + return + + if not is_stock_item: + if warehouse: + # product bundle case + item.in_stock = get_non_stock_item_status(item.item_code, "website_warehouse") + else: + item.in_stock = True + elif warehouse: + # stock item and has warehouse + actual_qty = frappe.db.get_value( + "Bin", + {"item_code": item.item_code,"warehouse": item.get("website_warehouse")}, + "actual_qty") + item.in_stock = bool(flt(actual_qty)) + + def get_cart_items(self): + customer = get_customer(silent=True) + if customer: + quotation = frappe.get_all("Quotation", fields=["name"], filters= + {"party_name": customer, "order_type": "Shopping Cart", "docstatus": 0}, + order_by="modified desc", limit_page_length=1) + if quotation: + items = frappe.get_all( + "Quotation Item", + fields=["item_code"], + filters={ + "parent": quotation[0].get("name") + }) + items = [row.item_code for row in items] + return items + + return [] + + def combine_web_item_group_results(self, item_group, result, website_item_groups): + """Combine results with context of website item groups into item results.""" + if item_group and website_item_groups: + items_list = {row.name for row in result} + for row in website_item_groups: + if row.wig_parent not in items_list: + result.append(row) + + return result + + def filter_results_by_discount(self, fields, result): + if fields and fields.get("discount"): + discount_percent = frappe.utils.flt(fields["discount"][0]) + result = [row for row in result if row.get("discount_percent") and row.discount_percent <= discount_percent] + + if self.filter_with_discount: + # no limit was added to results while querying + # slice results manually + result[:self.page_length] + + return result \ No newline at end of file diff --git a/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py new file mode 100644 index 00000000000..f0f7918d00e --- /dev/null +++ b/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py @@ -0,0 +1,117 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import unittest + +import frappe + +from erpnext.e_commerce.api import get_product_filter_data +from erpnext.e_commerce.doctype.website_item.test_website_item import create_regular_web_item + +test_dependencies = ["Item", "Item Group"] + +class TestItemGroupProductDataEngine(unittest.TestCase): + "Test Products & Sub-Category Querying for Product Listing on Item Group Page." + + @classmethod + def setUpClass(cls): + item_codes = [ + ("Test Mobile A", "_Test Item Group B"), + ("Test Mobile B", "_Test Item Group B"), + ("Test Mobile C", "_Test Item Group B - 1"), + ("Test Mobile D", "_Test Item Group B - 1"), + ("Test Mobile E", "_Test Item Group B - 2") + ] + for item in item_codes: + item_code = item[0] + item_args = {"item_group": item[1]} + if not frappe.db.exists("Website Item", {"item_code": item_code}): + create_regular_web_item(item_code, item_args=item_args) + + @classmethod + def tearDownClass(cls): + frappe.db.rollback() + + def test_product_listing_in_item_group(self): + "Test if only products belonging to the Item Group are fetched." + result = get_product_filter_data(query_args={ + "field_filters": {}, + "attribute_filters": {}, + "start": 0, + "item_group": "_Test Item Group B" + }) + + items = result.get("items") + item_codes = [item.get("item_code") for item in items] + + self.assertEqual(len(items), 2) + self.assertIn("Test Mobile A", item_codes) + self.assertNotIn("Test Mobile C", item_codes) + + def test_products_in_multiple_item_groups(self): + """Test if product is visible on multiple item group pages barring its own.""" + website_item = frappe.get_doc("Website Item", {"item_code": "Test Mobile E"}) + + # show item belonging to '_Test Item Group B - 2' in '_Test Item Group B - 1' as well + website_item.append("website_item_groups", { + "item_group": "_Test Item Group B - 1" + }) + website_item.save() + + result = get_product_filter_data(query_args={ + "field_filters": {}, + "attribute_filters": {}, + "start": 0, + "item_group": "_Test Item Group B - 1" + }) + + items = result.get("items") + item_codes = [item.get("item_code") for item in items] + + self.assertEqual(len(items), 3) + self.assertIn("Test Mobile E", item_codes) # visible in other item groups + self.assertIn("Test Mobile C", item_codes) + self.assertIn("Test Mobile D", item_codes) + + result = get_product_filter_data(query_args={ + "field_filters": {}, + "attribute_filters": {}, + "start": 0, + "item_group": "_Test Item Group B - 2" + }) + + items = result.get("items") + + self.assertEqual(len(items), 1) + self.assertEqual(items[0].get("item_code"), "Test Mobile E") # visible in own item group + + def test_item_group_with_sub_groups(self): + "Test Valid Sub Item Groups in Item Group Page." + frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1) + frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 0) + + result = get_product_filter_data(query_args={ + "field_filters": {}, + "attribute_filters": {}, + "start": 0, + "item_group": "_Test Item Group B" + }) + + self.assertTrue(bool(result.get("sub_categories"))) + + child_groups = [d.name for d in result.get("sub_categories")] + # check if child group is fetched if shown in website + self.assertIn("_Test Item Group B - 1", child_groups) + + frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 1) + result = get_product_filter_data(query_args={ + "field_filters": {}, + "attribute_filters": {}, + "start": 0, + "item_group": "_Test Item Group B" + }) + child_groups = [d.name for d in result.get("sub_categories")] + + # check if child group is fetched if shown in website + self.assertIn("_Test Item Group B - 1", child_groups) + self.assertIn("_Test Item Group B - 2", child_groups) \ No newline at end of file diff --git a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py new file mode 100644 index 00000000000..925e6e7be3c --- /dev/null +++ b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py @@ -0,0 +1,352 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import unittest + +import frappe + +from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import ( + setup_e_commerce_settings, +) +from erpnext.e_commerce.doctype.website_item.test_website_item import create_regular_web_item +from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder +from erpnext.e_commerce.product_data_engine.query import ProductQuery + +test_dependencies = ["Item", "Item Group"] + +class TestProductDataEngine(unittest.TestCase): + "Test Products Querying and Filters for Product Listing." + + @classmethod + def setUpClass(cls): + item_codes = [ + ("Test 11I Laptop", "Products"), # rank 1 + ("Test 12I Laptop", "Products"), # rank 2 + ("Test 13I Laptop", "Products"), # rank 3 + ("Test 14I Laptop", "Raw Material"), # rank 4 + ("Test 15I Laptop", "Raw Material"), # rank 5 + ("Test 16I Laptop", "Raw Material"), # rank 6 + ("Test 17I Laptop", "Products") # rank 7 + ] + for index, item in enumerate(item_codes, start=1): + item_code = item[0] + item_args = {"item_group": item[1]} + web_args = {"ranking": index} + if not frappe.db.exists("Website Item", {"item_code": item_code}): + create_regular_web_item(item_code, item_args=item_args, web_args=web_args) + + setup_e_commerce_settings({ + "products_per_page": 4, + "enable_field_filters": 1, + "filter_fields": [{"fieldname": "item_group"}], + "enable_attribute_filters": 1, + "filter_attributes": [{"attribute": "Test Size"}], + "company": "_Test Company", + "enabled": 1, + "default_customer_group": "_Test Customer Group", + "price_list": "_Test Price List India" + }) + frappe.local.shopping_cart_settings = None + + @classmethod + def tearDownClass(cls): + frappe.db.rollback() + + def test_product_list_ordering_and_paging(self): + "Test if website items appear by ranking on different pages." + engine = ProductQuery() + result = engine.query( + attributes={}, + fields={}, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + self.assertIsNotNone(items) + self.assertEqual(len(items), 4) + self.assertGreater(result.get("items_count"), 4) + + # check if items appear as per ranking set in setUpClass + self.assertEqual(items[0].get("item_code"), "Test 17I Laptop") + self.assertEqual(items[1].get("item_code"), "Test 16I Laptop") + self.assertEqual(items[2].get("item_code"), "Test 15I Laptop") + self.assertEqual(items[3].get("item_code"), "Test 14I Laptop") + + # check next page + result = engine.query( + attributes={}, + fields={}, + search_term=None, + start=4, + item_group=None + ) + items = result.get("items") + + # check if items appear as per ranking set in setUpClass on next page + self.assertEqual(items[0].get("item_code"), "Test 13I Laptop") + self.assertEqual(items[1].get("item_code"), "Test 12I Laptop") + self.assertEqual(items[2].get("item_code"), "Test 11I Laptop") + + def test_change_product_ranking(self): + "Test if item on second page appear on first if ranking is changed." + item_code = "Test 12I Laptop" + old_ranking = frappe.db.get_value("Website Item", {"item_code": item_code}, "ranking") + + # low rank, appears on second page + self.assertEqual(old_ranking, 2) + + # set ranking as highest rank + frappe.db.set_value("Website Item", {"item_code": item_code}, "ranking", 10) + + engine = ProductQuery() + result = engine.query( + attributes={}, + fields={}, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + # check if item is the first item on the first page + self.assertEqual(items[0].get("item_code"), item_code) + self.assertEqual(items[1].get("item_code"), "Test 17I Laptop") + + # tear down + frappe.db.set_value("Website Item", {"item_code": item_code}, "ranking", old_ranking) + + def test_product_list_field_filter_builder(self): + "Test if field filters are fetched correctly." + frappe.db.set_value("Item Group", "Raw Material", "show_in_website", 0) + + filter_engine = ProductFiltersBuilder() + field_filters = filter_engine.get_field_filters() + + # Web Items belonging to 'Products' and 'Raw Material' are available + # but only 'Products' has 'show_in_website' enabled + item_group_filters = field_filters[0] + docfield = item_group_filters[0] + valid_item_groups = item_group_filters[1] + + self.assertEqual(docfield.options, "Item Group") + self.assertIn("Products", valid_item_groups) + self.assertNotIn("Raw Material", valid_item_groups) + + frappe.db.set_value("Item Group", "Raw Material", "show_in_website", 1) + field_filters = filter_engine.get_field_filters() + + #'Products' and 'Raw Materials' both have 'show_in_website' enabled + item_group_filters = field_filters[0] + docfield = item_group_filters[0] + valid_item_groups = item_group_filters[1] + + self.assertEqual(docfield.options, "Item Group") + self.assertIn("Products", valid_item_groups) + self.assertIn("Raw Material", valid_item_groups) + + def test_product_list_with_field_filter(self): + "Test if field filters are applied correctly." + field_filters = {"item_group": "Raw Material"} + + engine = ProductQuery() + result = engine.query( + attributes={}, + fields=field_filters, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + # check if only 'Raw Material' are fetched in the right order + self.assertEqual(len(items), 3) + self.assertEqual(items[0].get("item_code"), "Test 16I Laptop") + self.assertEqual(items[1].get("item_code"), "Test 15I Laptop") + + # def test_product_list_with_field_filter_table_multiselect(self): + # TODO + # pass + + def test_product_list_attribute_filter_builder(self): + "Test if attribute filters are fetched correctly." + create_variant_web_item() + + filter_engine = ProductFiltersBuilder() + attribute_filter = filter_engine.get_attribute_filters()[0] + attributes = attribute_filter.item_attribute_values + + attribute_values = [d.attribute_value for d in attributes] + + self.assertEqual(attribute_filter.name, "Test Size") + self.assertGreater(len(attribute_values), 0) + self.assertIn("Large", attribute_values) + + def test_product_list_with_attribute_filter(self): + "Test if attribute filters are applied correctly." + create_variant_web_item() + + attribute_filters = {"Test Size": ["Large"]} + engine = ProductQuery() + result = engine.query( + attributes=attribute_filters, + fields={}, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + # check if only items with Test Size 'Large' are fetched + self.assertEqual(len(items), 1) + self.assertEqual(items[0].get("item_code"), "Test Web Item-L") + + def test_product_list_discount_filter_builder(self): + "Test if discount filters are fetched correctly." + from erpnext.e_commerce.doctype.website_item.test_website_item import ( + make_web_item_price, + make_web_pricing_rule, + ) + + item_code = "Test 12I Laptop" + make_web_item_price(item_code=item_code) + make_web_pricing_rule( + title=f"Test Pricing Rule for {item_code}", + item_code=item_code, + selling=1 + ) + + setup_e_commerce_settings({"show_price": 1}) + frappe.local.shopping_cart_settings = None + + + engine = ProductQuery() + result = engine.query( + attributes={}, + fields={}, + search_term=None, + start=4, + item_group=None + ) + self.assertTrue(bool(result.get("discounts"))) + + filter_engine = ProductFiltersBuilder() + discount_filters = filter_engine.get_discount_filters(result["discounts"]) + + self.assertEqual(len(discount_filters[0]), 2) + self.assertEqual(discount_filters[0][0], 10) + self.assertEqual(discount_filters[0][1], "10% and below") + + def test_product_list_with_discount_filters(self): + "Test if discount filters are applied correctly." + from erpnext.e_commerce.doctype.website_item.test_website_item import ( + make_web_item_price, + make_web_pricing_rule, + ) + + field_filters = {"discount": [10]} + + make_web_item_price(item_code="Test 12I Laptop") + make_web_pricing_rule( + title="Test Pricing Rule for Test 12I Laptop", # 10% discount + item_code="Test 12I Laptop", + selling=1 + ) + make_web_item_price(item_code="Test 13I Laptop") + make_web_pricing_rule( + title="Test Pricing Rule for Test 13I Laptop", # 15% discount + item_code="Test 13I Laptop", + discount_percentage=15, + selling=1 + ) + + setup_e_commerce_settings({"show_price": 1}) + frappe.local.shopping_cart_settings = None + + engine = ProductQuery() + result = engine.query( + attributes={}, + fields=field_filters, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + # check if only product with 10% and below discount are fetched + self.assertEqual(len(items), 1) + self.assertEqual(items[0].get("item_code"), "Test 12I Laptop") + + def test_product_list_with_api(self): + "Test products listing using API." + from erpnext.e_commerce.api import get_product_filter_data + + create_variant_web_item() + + result = get_product_filter_data(query_args={ + "field_filters": { + "item_group": "Products" + }, + "attribute_filters": { + "Test Size": ["Large"] + }, + "start": 0 + }) + + items = result.get("items") + + self.assertEqual(len(items), 1) + self.assertEqual(items[0].get("item_code"), "Test Web Item-L") + + def test_product_list_with_variants(self): + "Test if variants are hideen on hiding variants in settings." + create_variant_web_item() + + setup_e_commerce_settings({ + "enable_attribute_filters": 0, + "hide_variants": 1 + }) + frappe.local.shopping_cart_settings = None + + attribute_filters = {"Test Size": ["Large"]} + engine = ProductQuery() + result = engine.query( + attributes=attribute_filters, + fields={}, + search_term=None, + start=0, + item_group=None + ) + items = result.get("items") + + # check if any variants are fetched even though published variant exists + self.assertEqual(len(items), 0) + + # tear down + setup_e_commerce_settings({ + "enable_attribute_filters": 1, + "hide_variants": 0 + }) + +def create_variant_web_item(): + "Create Variant and Template Website Items." + from erpnext.controllers.item_variant import create_variant + from erpnext.e_commerce.doctype.website_item.website_item import make_website_item + from erpnext.stock.doctype.item.test_item import make_item + + make_item("Test Web Item", { + "has_variant": 1, + "variant_based_on": "Item Attribute", + "attributes": [ + { + "attribute": "Test Size" + } + ] + }) + if not frappe.db.exists("Item", "Test Web Item-L"): + variant = create_variant("Test Web Item", {"Test Size": "Large"}) + variant.save() + + if not frappe.db.exists("Website Item", {"variant_of": "Test Web Item"}): + make_website_item(variant, save=True) \ No newline at end of file diff --git a/erpnext/e_commerce/product_ui/grid.js b/erpnext/e_commerce/product_ui/grid.js new file mode 100644 index 00000000000..9eb1d45d5f5 --- /dev/null +++ b/erpnext/e_commerce/product_ui/grid.js @@ -0,0 +1,201 @@ +erpnext.ProductGrid = class { + /* Options: + - items: Items + - settings: E Commerce Settings + - products_section: Products Wrapper + - preference: If preference is not grid view, render but hide + */ + constructor(options) { + Object.assign(this, options); + + if (this.preference !== "Grid View") { + this.products_section.addClass("hidden"); + } + + this.products_section.empty(); + this.make(); + } + + make() { + let me = this; + let html = ``; + + this.items.forEach(item => { + let title = item.web_item_name || item.item_name || item.item_code || ""; + title = title.length > 90 ? title.substr(0, 90) + "..." : title; + + html += `
`; + html += me.get_image_html(item, title); + html += me.get_card_body_html(item, title, me.settings); + html += `
`; + }); + + let $product_wrapper = this.products_section; + $product_wrapper.append(html); + } + + get_image_html(item, title) { + let image = item.website_image || item.image; + + if (image) { + return ` +
+ + ${ title } + +
+ `; + } else { + return ` +
+ +
+ ${ frappe.get_abbr(title) } +
+
+
+ `; + } + } + + get_card_body_html(item, title, settings) { + let body_html = ` +
+
+ `; + body_html += this.get_title(item, title); + + // get floating elements + if (!item.has_variants) { + if (settings.enable_wishlist) { + body_html += this.get_wishlist_icon(item); + } + if (settings.enabled) { + body_html += this.get_cart_indicator(item); + } + + } + + body_html += `
`; + body_html += `
${ item.item_group || '' }
`; + + if (item.formatted_price) { + body_html += this.get_price_html(item); + } + + body_html += this.get_stock_availability(item, settings); + body_html += this.get_primary_button(item, settings); + body_html += `
`; // close div on line 49 + + return body_html; + } + + get_title(item, title) { + let title_html = ` + +
+ ${ title || '' } +
+
+ `; + return title_html; + } + + get_wishlist_icon(item) { + let icon_class = item.wished ? "wished" : "not-wished"; + return ` +
+ + + +
+ `; + } + + get_cart_indicator(item) { + return ` +
+ 1 +
+ `; + } + + get_price_html(item) { + let price_html = ` +
+ ${ item.formatted_price || '' } + `; + + if (item.formatted_mrp) { + price_html += ` + + ${ item.formatted_mrp ? item.formatted_mrp.replace(/ +/g, "") : "" } + + + ${ item.discount } OFF + + `; + } + price_html += `
`; + return price_html; + } + + get_stock_availability(item, settings) { + if (settings.show_stock_availability && !item.has_variants) { + if (item.on_backorder) { + return ` + + ${ __("Available on backorder") } + + `; + } else if (!item.in_stock) { + return ` + + ${ __("Out of stock") } + + `; + } + } + + return ``; + } + + get_primary_button(item, settings) { + if (item.has_variants) { + return ` + +
+ ${ __('Explore') } +
+
+ `; + } else if (settings.enabled && (settings.allow_items_not_in_stock || item.in_stock)) { + return ` +
+ + + + + + ${ settings.enable_checkout ? __('Add to Cart') : __('Add to Quote') } +
+ + +
+ ${ settings.enable_checkout ? __('Go to Cart') : __('Go to Quote') } +
+
+ `; + } else { + return ``; + } + } +}; \ No newline at end of file diff --git a/erpnext/e_commerce/product_ui/list.js b/erpnext/e_commerce/product_ui/list.js new file mode 100644 index 00000000000..691cd4d9de1 --- /dev/null +++ b/erpnext/e_commerce/product_ui/list.js @@ -0,0 +1,204 @@ +erpnext.ProductList = class { + /* Options: + - items: Items + - settings: E Commerce Settings + - products_section: Products Wrapper + - preference: If preference is not list view, render but hide + */ + constructor(options) { + Object.assign(this, options); + + if (this.preference !== "List View") { + this.products_section.addClass("hidden"); + } + + this.products_section.empty(); + this.make(); + } + + make() { + let me = this; + let html = `

`; + + this.items.forEach(item => { + let title = item.web_item_name || item.item_name || item.item_code || ""; + title = title.length > 200 ? title.substr(0, 200) + "..." : title; + + html += `
`; + html += me.get_image_html(item, title, me.settings); + html += me.get_row_body_html(item, title, me.settings); + html += `
`; + }); + + let $product_wrapper = this.products_section; + $product_wrapper.append(html); + } + + get_image_html(item, title, settings) { + let image = item.website_image || item.image; + let wishlist_enabled = !item.has_variants && settings.enable_wishlist; + let image_html = ``; + + if (image) { + image_html += ` +
+ + ${ title } + + ${ wishlist_enabled ? this.get_wishlist_icon(item): '' } +
+ `; + } else { + image_html += ` +
+ +
+ ${ frappe.get_abbr(title) } +
+
+ ${ wishlist_enabled ? this.get_wishlist_icon(item): '' } +
+ `; + } + + return image_html; + } + + get_row_body_html(item, title, settings) { + let body_html = `
`; + body_html += this.get_title_html(item, title, settings); + body_html += this.get_item_details(item, settings); + body_html += `
`; + return body_html; + } + + get_title_html(item, title, settings) { + let title_html = `
`; + title_html += ` +
+ + ${ title } + +
+ `; + + if (settings.enabled) { + title_html += `
`; + title_html += this.get_primary_button(item, settings); + title_html += `
`; + } + title_html += `
`; + + return title_html; + } + + get_item_details(item, settings) { + let details = ` +

+ ${ item.item_group } | Item Code : ${ item.item_code } +

+
+ ${ item.short_description || '' } +
+
+ ${ item.formatted_price || '' } + `; + + if (item.formatted_mrp) { + details += ` + + ${ item.formatted_mrp ? item.formatted_mrp.replace(/ +/g, "") : "" } + + + ${ item.discount } OFF + + `; + } + + details += this.get_stock_availability(item, settings); + details += `
`; + + return details; + } + + get_stock_availability(item, settings) { + if (settings.show_stock_availability && !item.has_variants) { + if (item.on_backorder) { + return ` +
+ + ${ __("Available on backorder") } + + `; + } else if (!item.in_stock) { + return ` +
+ ${ __("Out of stock") } + `; + } + } + return ``; + } + + get_wishlist_icon(item) { + let icon_class = item.wished ? "wished" : "not-wished"; + + return ` +
+ + + +
+ `; + } + + get_primary_button(item, settings) { + if (item.has_variants) { + return ` + +
+ ${ __('Explore') } +
+
+ `; + } else if (settings.enabled && (settings.allow_items_not_in_stock || item.in_stock)) { + return ` +
+ + + + + + ${ settings.enable_checkout ? __('Add to Cart') : __('Add to Quote') } +
+ +
+ 1 +
+ + +
+ ${ settings.enable_checkout ? __('Go to Cart') : __('Go to Quote') } +
+
+ `; + } else { + return ``; + } + } + +}; \ No newline at end of file diff --git a/erpnext/e_commerce/product_ui/search.js b/erpnext/e_commerce/product_ui/search.js new file mode 100644 index 00000000000..9bae1c10bc4 --- /dev/null +++ b/erpnext/e_commerce/product_ui/search.js @@ -0,0 +1,241 @@ +erpnext.ProductSearch = class { + constructor() { + this.MAX_RECENT_SEARCHES = 4; + this.searchBox = $("#search-box"); + + this.setupSearchDropDown(); + this.bindSearchAction(); + } + + setupSearchDropDown() { + this.search_area = $("#dropdownMenuSearch"); + this.setupSearchResultContainer(); + this.populateRecentSearches(); + } + + bindSearchAction() { + let me = this; + + // Show Search dropdown + this.searchBox.on("focus", () => { + this.search_dropdown.removeClass("hidden"); + }); + + // If click occurs outside search input/results, hide results. + // Click can happen anywhere on the page + $("body").on("click", (e) => { + let searchEvent = $(e.target).closest('#search-box').length; + let resultsEvent = $(e.target).closest('#search-results-container').length; + let isResultHidden = this.search_dropdown.hasClass("hidden"); + + if (!searchEvent && !resultsEvent && !isResultHidden) { + this.search_dropdown.addClass("hidden"); + } + }); + + // Process search input + this.searchBox.on("input", (e) => { + let query = e.target.value; + + if (query.length == 0) { + me.populateResults(null); + me.populateCategoriesList(null); + } + + if (query.length < 3 || !query.length) return; + + frappe.call({ + method: "erpnext.templates.pages.product_search.search", + args: { + query: query + }, + callback: (data) => { + let product_results = null, category_results = null; + + // Populate product results + product_results = data.message ? data.message.product_results : null; + me.populateResults(product_results); + + // Populate categories + if (me.category_container) { + category_results = data.message ? data.message.category_results : null; + me.populateCategoriesList(category_results); + } + + // Populate recent search chips only on successful queries + if (!$.isEmptyObject(product_results) || !$.isEmptyObject(category_results)) { + me.setRecentSearches(query); + } + } + }); + + this.search_dropdown.removeClass("hidden"); + }); + } + + setupSearchResultContainer() { + this.search_dropdown = this.search_area.append(` + + `).find("#search-results-container"); + + this.setupCategoryContainer(); + this.setupProductsContainer(); + this.setupRecentsContainer(); + } + + setupProductsContainer() { + this.products_container = this.search_dropdown.append(` +
+
+
+
+ `).find("#product-scroll"); + } + + setupCategoryContainer() { + this.category_container = this.search_dropdown.append(` +
+
+
+
+ `).find(".category-chips"); + } + + setupRecentsContainer() { + let $recents_section = this.search_dropdown.append(` +
+
+ ${ __("Recent") } +
+
+ `).find(".recent-searches"); + + this.recents_container = $recents_section.append(` +
+
+ `).find("#recents"); + } + + getRecentSearches() { + return JSON.parse(localStorage.getItem("recent_searches") || "[]"); + } + + attachEventListenersToChips() { + let me = this; + const chips = $(".recent-search"); + window.chips = chips; + + for (let chip of chips) { + chip.addEventListener("click", () => { + me.searchBox[0].value = chip.innerText.trim(); + + // Start search with `recent query` + me.searchBox.trigger("input"); + me.searchBox.focus(); + }); + } + } + + setRecentSearches(query) { + let recents = this.getRecentSearches(); + if (recents.length >= this.MAX_RECENT_SEARCHES) { + // Remove the `first` query + recents.splice(0, 1); + } + + if (recents.indexOf(query) >= 0) { + return; + } + + recents.push(query); + localStorage.setItem("recent_searches", JSON.stringify(recents)); + + this.populateRecentSearches(); + } + + populateRecentSearches() { + let recents = this.getRecentSearches(); + + if (!recents.length) { + this.recents_container.html(`No searches yet.`); + return; + } + + let html = ""; + recents.forEach((key) => { + html += ` + + `; + }); + + this.recents_container.html(html); + this.attachEventListenersToChips(); + } + + populateResults(product_results) { + if (!product_results || product_results.length === 0) { + let empty_html = ``; + this.products_container.html(empty_html); + return; + } + + let html = ""; + + product_results.forEach((res) => { + let thumbnail = res.thumbnail || '/assets/erpnext/images/ui-states/cart-empty-state.png'; + html += ` + + `; + }); + + this.products_container.html(html); + } + + populateCategoriesList(category_results) { + if (!category_results || category_results.length === 0) { + let empty_html = ` +
+
+
+
+ `; + this.category_container.html(empty_html); + return; + } + + let html = ` +
+ ${ __("Categories") } +
+ `; + + category_results.forEach((category) => { + html += ` + + ${ category.name } + + `; + }); + + this.category_container.html(html); + } +}; \ No newline at end of file diff --git a/erpnext/e_commerce/product_ui/views.js b/erpnext/e_commerce/product_ui/views.js new file mode 100644 index 00000000000..99b91afac17 --- /dev/null +++ b/erpnext/e_commerce/product_ui/views.js @@ -0,0 +1,538 @@ +erpnext.ProductView = class { + /* Options: + - View Type + - Products Section Wrapper, + - Item Group: If its an Item Group page + */ + constructor(options) { + Object.assign(this, options); + this.preference = this.view_type; + this.make(); + } + + make(from_filters=false) { + this.products_section.empty(); + this.prepare_toolbar(); + this.get_item_filter_data(from_filters); + } + + prepare_toolbar() { + this.products_section.append(` +
+
+ `); + this.prepare_search(); + this.prepare_view_toggler(); + + frappe.require('/assets/js/e-commerce.min.js', function() { + new erpnext.ProductSearch(); + }); + } + + prepare_view_toggler() { + + if (!$("#list").length || !$("#image-view").length) { + this.render_view_toggler(); + this.bind_view_toggler_actions(); + this.set_view_state(); + } + } + + get_item_filter_data(from_filters=false) { + // Get and render all Product related views + let me = this; + this.from_filters = from_filters; + let args = this.get_query_filters(); + + this.disable_view_toggler(true); + + frappe.call({ + method: "erpnext.e_commerce.api.get_product_filter_data", + args: { + query_args: args + }, + callback: function(result) { + if (!result || result.exc || !result.message || result.message.exc) { + me.render_no_products_section(true); + } else { + // Sub Category results are independent of Items + if (me.item_group && result.message["sub_categories"].length) { + me.render_item_sub_categories(result.message["sub_categories"]); + } + + if (!result.message["items"].length) { + // if result has no items or result is empty + me.render_no_products_section(); + } else { + // Add discount filters + me.re_render_discount_filters(result.message["filters"].discount_filters); + + // Render views + me.render_list_view(result.message["items"], result.message["settings"]); + me.render_grid_view(result.message["items"], result.message["settings"]); + + me.products = result.message["items"]; + me.product_count = result.message["items_count"]; + } + + // Bind filter actions + if (!from_filters) { + // If `get_product_filter_data` was triggered after checking a filter, + // don't touch filters unnecessarily, only data must change + // filter persistence is handle on filter change event + me.bind_filters(); + me.restore_filters_state(); + } + + // Bottom paging + me.add_paging_section(result.message["settings"]); + } + + me.disable_view_toggler(false); + } + }); + } + + disable_view_toggler(disable=false) { + $('#list').prop('disabled', disable); + $('#image-view').prop('disabled', disable); + } + + render_grid_view(items, settings) { + // loop over data and add grid html to it + let me = this; + this.prepare_product_area_wrapper("grid"); + + frappe.require('/assets/js/e-commerce.min.js', function() { + new erpnext.ProductGrid({ + items: items, + products_section: $("#products-grid-area"), + settings: settings, + preference: me.preference + }); + }); + } + + render_list_view(items, settings) { + let me = this; + this.prepare_product_area_wrapper("list"); + + frappe.require('/assets/js/e-commerce.min.js', function() { + new erpnext.ProductList({ + items: items, + products_section: $("#products-list-area"), + settings: settings, + preference: me.preference + }); + }); + } + + prepare_product_area_wrapper(view) { + let left_margin = view == "list" ? "ml-2" : ""; + let top_margin = view == "list" ? "mt-6" : "mt-minus-1"; + return this.products_section.append(` +
+
+ `); + } + + get_query_filters() { + const filters = frappe.utils.get_query_params(); + let {field_filters, attribute_filters} = filters; + + field_filters = field_filters ? JSON.parse(field_filters) : {}; + attribute_filters = attribute_filters ? JSON.parse(attribute_filters) : {}; + + return { + field_filters: field_filters, + attribute_filters: attribute_filters, + item_group: this.item_group, + start: filters.start || null, + from_filters: this.from_filters || false + }; + } + + add_paging_section(settings) { + $(".product-paging-area").remove(); + + if (this.products) { + let paging_html = ` +
+
+
+
+ `; + let query_params = frappe.utils.get_query_params(); + let start = query_params.start ? cint(JSON.parse(query_params.start)) : 0; + let page_length = settings.products_per_page || 0; + + let prev_disable = start > 0 ? "" : "disabled"; + let next_disable = (this.product_count > page_length) ? "" : "disabled"; + + paging_html += ` + `; + + paging_html += ` + + `; + + paging_html += `
`; + + $(".page_content").append(paging_html); + this.bind_paging_action(); + } + } + + prepare_search() { + $(".toolbar").append(` +
+ +
+ `); + } + + render_view_toggler() { + $(".toolbar").append(`
`); + + ["btn-list-view", "btn-grid-view"].forEach(view => { + let icon = view === "btn-list-view" ? "list" : "image-view"; + $(".toggle-container").append(` +
+ +
+ `); + }); + } + + bind_view_toggler_actions() { + $("#list").click(function() { + let $btn = $(this); + $btn.removeClass('btn-primary'); + $btn.addClass('btn-primary'); + $(".btn-grid-view").removeClass('btn-primary'); + + $("#products-grid-area").addClass("hidden"); + $("#products-list-area").removeClass("hidden"); + localStorage.setItem("product_view", "List View"); + }); + + $("#image-view").click(function() { + let $btn = $(this); + $btn.removeClass('btn-primary'); + $btn.addClass('btn-primary'); + $(".btn-list-view").removeClass('btn-primary'); + + $("#products-list-area").addClass("hidden"); + $("#products-grid-area").removeClass("hidden"); + localStorage.setItem("product_view", "Grid View"); + }); + } + + set_view_state() { + if (this.preference === "List View") { + $("#list").addClass('btn-primary'); + $("#image-view").removeClass('btn-primary'); + } else { + $("#image-view").addClass('btn-primary'); + $("#list").removeClass('btn-primary'); + } + } + + bind_paging_action() { + let me = this; + $('.btn-prev, .btn-next').click((e) => { + const $btn = $(e.target); + me.from_filters = false; + + $btn.prop('disabled', true); + const start = $btn.data('start'); + + let query_params = frappe.utils.get_query_params(); + query_params.start = start; + let path = window.location.pathname + '?' + frappe.utils.get_url_from_dict(query_params); + window.location.href = path; + }); + } + + re_render_discount_filters(filter_data) { + this.get_discount_filter_html(filter_data); + if (this.from_filters) { + // Bind filter action if triggered via filters + // if not from filter action, page load will bind actions + this.bind_discount_filter_action(); + } + // discount filters are rendered with Items (later) + // unlike the other filters + this.restore_discount_filter(); + } + + get_discount_filter_html(filter_data) { + $("#discount-filters").remove(); + if (filter_data) { + $("#product-filters").append(` +
+
${ __("Discounts") }
+
+ `); + + let html = `
`; + filter_data.forEach(filter => { + html += ` +
+ +
+ `; + }); + html += `
`; + + $("#discount-filters").append(html); + } + } + + restore_discount_filter() { + const filters = frappe.utils.get_query_params(); + let field_filters = filters.field_filters; + if (!field_filters) return; + + field_filters = JSON.parse(field_filters); + + if (field_filters && field_filters["discount"]) { + const values = field_filters["discount"]; + const selector = values.map(value => { + return `input[data-filter-name="discount"][data-filter-value="${value}"]`; + }).join(','); + $(selector).prop('checked', true); + this.field_filters = field_filters; + } + } + + bind_discount_filter_action() { + let me = this; + $('.discount-filter').on('change', (e) => { + const $checkbox = $(e.target); + const is_checked = $checkbox.is(':checked'); + + const { + filterValue: filter_value + } = $checkbox.data(); + + delete this.field_filters["discount"]; + + if (is_checked) { + this.field_filters["discount"] = []; + this.field_filters["discount"].push(filter_value); + } + + if (this.field_filters["discount"].length === 0) { + delete this.field_filters["discount"]; + } + + me.change_route_with_filters(); + }); + } + + bind_filters() { + let me = this; + this.field_filters = {}; + this.attribute_filters = {}; + + $('.product-filter').on('change', (e) => { + me.from_filters = true; + + const $checkbox = $(e.target); + const is_checked = $checkbox.is(':checked'); + + if ($checkbox.is('.attribute-filter')) { + const { + attributeName: attribute_name, + attributeValue: attribute_value + } = $checkbox.data(); + + if (is_checked) { + this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || []; + this.attribute_filters[attribute_name].push(attribute_value); + } else { + this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || []; + this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name].filter(v => v !== attribute_value); + } + + if (this.attribute_filters[attribute_name].length === 0) { + delete this.attribute_filters[attribute_name]; + } + } else if ($checkbox.is('.field-filter') || $checkbox.is('.discount-filter')) { + const { + filterName: filter_name, + filterValue: filter_value + } = $checkbox.data(); + + if ($checkbox.is('.discount-filter')) { + // clear previous discount filter to accomodate new + delete this.field_filters["discount"]; + } + if (is_checked) { + this.field_filters[filter_name] = this.field_filters[filter_name] || []; + if (!in_list(this.field_filters[filter_name], filter_value)) { + this.field_filters[filter_name].push(filter_value); + } + } else { + this.field_filters[filter_name] = this.field_filters[filter_name] || []; + this.field_filters[filter_name] = this.field_filters[filter_name].filter(v => v !== filter_value); + } + + if (this.field_filters[filter_name].length === 0) { + delete this.field_filters[filter_name]; + } + } + + me.change_route_with_filters(); + }); + } + + change_route_with_filters() { + let route_params = frappe.utils.get_query_params(); + + let start = this.if_key_exists(route_params.start) || 0; + if (this.from_filters) { + start = 0; // show items from first page if new filters are triggered + } + + const query_string = this.get_query_string({ + start: start, + field_filters: JSON.stringify(this.if_key_exists(this.field_filters)), + attribute_filters: JSON.stringify(this.if_key_exists(this.attribute_filters)), + }); + window.history.pushState('filters', '', `${location.pathname}?` + query_string); + + $('.page_content input').prop('disabled', true); + + this.make(true); + $('.page_content input').prop('disabled', false); + } + + restore_filters_state() { + const filters = frappe.utils.get_query_params(); + let {field_filters, attribute_filters} = filters; + + if (field_filters) { + field_filters = JSON.parse(field_filters); + for (let fieldname in field_filters) { + const values = field_filters[fieldname]; + const selector = values.map(value => { + return `input[data-filter-name="${fieldname}"][data-filter-value="${value}"]`; + }).join(','); + $(selector).prop('checked', true); + } + this.field_filters = field_filters; + } + if (attribute_filters) { + attribute_filters = JSON.parse(attribute_filters); + for (let attribute in attribute_filters) { + const values = attribute_filters[attribute]; + const selector = values.map(value => { + return `input[data-attribute-name="${attribute}"][data-attribute-value="${value}"]`; + }).join(','); + $(selector).prop('checked', true); + } + this.attribute_filters = attribute_filters; + } + } + + render_no_products_section(error=false) { + let error_section = ` +
+ Something went wrong. Please refresh or contact us. +
+ `; + let no_results_section = ` +
+
+ Empty Cart +
+
${ __('No products found') }

+
+ `; + + this.products_section.append(error ? error_section : no_results_section); + } + + render_item_sub_categories(categories) { + if (categories && categories.length) { + let sub_group_html = ` +
+ `; + + categories.forEach(category => { + sub_group_html += ` + +
+ ${ category.name } +
+
+ `; + }); + sub_group_html += `
`; + + $("#product-listing").prepend(sub_group_html); + } + } + + get_query_string(object) { + const url = new URLSearchParams(); + for (let key in object) { + const value = object[key]; + if (value) { + url.append(key, value); + } + } + return url.toString(); + } + + if_key_exists(obj) { + let exists = false; + for (let key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key]) { + exists = true; + break; + } + } + return exists ? obj : undefined; + } +}; \ No newline at end of file diff --git a/erpnext/e_commerce/redisearch.py b/erpnext/e_commerce/redisearch.py new file mode 100644 index 00000000000..5cfb5ae2920 --- /dev/null +++ b/erpnext/e_commerce/redisearch.py @@ -0,0 +1,208 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe +from frappe.utils.redis_wrapper import RedisWrapper +from redisearch import AutoCompleter, Client, IndexDefinition, Suggestion, TagField, TextField + +WEBSITE_ITEM_INDEX = 'website_items_index' +WEBSITE_ITEM_KEY_PREFIX = 'website_item:' +WEBSITE_ITEM_NAME_AUTOCOMPLETE = 'website_items_name_dict' +WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE = 'website_items_category_dict' + +def get_indexable_web_fields(): + "Return valid fields from Website Item that can be searched for." + web_item_meta = frappe.get_meta("Website Item", cached=True) + valid_fields = filter( + lambda df: df.fieldtype in ("Link", "Table MultiSelect", "Data", "Small Text", "Text Editor"), + web_item_meta.fields) + + return [df.fieldname for df in valid_fields] + +def is_search_module_loaded(): + cache = frappe.cache() + out = cache.execute_command('MODULE LIST') + + parsed_output = " ".join( + (" ".join([s.decode() for s in o if not isinstance(s, int)]) for o in out) + ) + + return "search" in parsed_output + +def if_redisearch_loaded(function): + "Decorator to check if Redisearch is loaded." + def wrapper(*args, **kwargs): + if is_search_module_loaded(): + func = function(*args, **kwargs) + return func + return + + return wrapper + +def make_key(key): + return "{0}|{1}".format(frappe.conf.db_name, key).encode('utf-8') + +@if_redisearch_loaded +def create_website_items_index(): + "Creates Index Definition." + + # CREATE index + client = Client(make_key(WEBSITE_ITEM_INDEX), conn=frappe.cache()) + + # DROP if already exists + try: + client.drop_index() + except Exception: + pass + + idx_def = IndexDefinition([make_key(WEBSITE_ITEM_KEY_PREFIX)]) + + # Based on e-commerce settings + idx_fields = frappe.db.get_single_value( + 'E Commerce Settings', + 'search_index_fields' + ) + idx_fields = idx_fields.split(',') if idx_fields else [] + + if 'web_item_name' in idx_fields: + idx_fields.remove('web_item_name') + + idx_fields = list(map(to_search_field, idx_fields)) + + client.create_index( + [TextField("web_item_name", sortable=True)] + idx_fields, + definition=idx_def, + ) + + reindex_all_web_items() + define_autocomplete_dictionary() + +def to_search_field(field): + if field == "tags": + return TagField("tags", separator=",") + + return TextField(field) + +@if_redisearch_loaded +def insert_item_to_index(website_item_doc): + # Insert item to index + key = get_cache_key(website_item_doc.name) + cache = frappe.cache() + web_item = create_web_item_map(website_item_doc) + + for k, v in web_item.items(): + super(RedisWrapper, cache).hset(make_key(key), k, v) + + insert_to_name_ac(website_item_doc.web_item_name, website_item_doc.name) + +@if_redisearch_loaded +def insert_to_name_ac(web_name, doc_name): + ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=frappe.cache()) + ac.add_suggestions(Suggestion(web_name, payload=doc_name)) + +def create_web_item_map(website_item_doc): + fields_to_index = get_fields_indexed() + web_item = {} + + for f in fields_to_index: + web_item[f] = website_item_doc.get(f) or '' + + return web_item + +@if_redisearch_loaded +def update_index_for_item(website_item_doc): + # Reinsert to Cache + insert_item_to_index(website_item_doc) + define_autocomplete_dictionary() + +@if_redisearch_loaded +def delete_item_from_index(website_item_doc): + cache = frappe.cache() + key = get_cache_key(website_item_doc.name) + + try: + cache.delete(key) + except Exception: + return False + + delete_from_ac_dict(website_item_doc) + return True + +@if_redisearch_loaded +def delete_from_ac_dict(website_item_doc): + '''Removes this items's name from autocomplete dictionary''' + cache = frappe.cache() + name_ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=cache) + name_ac.delete(website_item_doc.web_item_name) + +@if_redisearch_loaded +def define_autocomplete_dictionary(): + """Creates an autocomplete search dictionary for `name`. + Also creats autocomplete dictionary for `categories` if + checked in E Commerce Settings""" + + cache = frappe.cache() + name_ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=cache) + cat_ac = AutoCompleter(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE), conn=cache) + + ac_categories = frappe.db.get_single_value( + 'E Commerce Settings', + 'show_categories_in_search_autocomplete' + ) + + # Delete both autocomplete dicts + try: + cache.delete(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE)) + cache.delete(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE)) + except Exception: + return False + + items = frappe.get_all( + 'Website Item', + fields=['web_item_name', 'item_group'], + filters={"published": 1} + ) + + for item in items: + name_ac.add_suggestions(Suggestion(item.web_item_name)) + if ac_categories and item.item_group: + cat_ac.add_suggestions(Suggestion(item.item_group)) + + return True + +@if_redisearch_loaded +def reindex_all_web_items(): + items = frappe.get_all( + 'Website Item', + fields=get_fields_indexed(), + filters={"published": True} + ) + + cache = frappe.cache() + for item in items: + web_item = create_web_item_map(item) + key = make_key(get_cache_key(item.name)) + + for k, v in web_item.items(): + super(RedisWrapper, cache).hset(key, k, v) + +def get_cache_key(name): + name = frappe.scrub(name) + return f"{WEBSITE_ITEM_KEY_PREFIX}{name}" + +def get_fields_indexed(): + fields_to_index = frappe.db.get_single_value( + 'E Commerce Settings', + 'search_index_fields' + ) + fields_to_index = fields_to_index.split(',') if fields_to_index else [] + + mandatory_fields = ['name', 'web_item_name', 'route', 'thumbnail', 'ranking'] + fields_to_index = fields_to_index + mandatory_fields + + return fields_to_index + +# TODO: Remove later +# # Figure out a way to run this at startup +define_autocomplete_dictionary() +create_website_items_index() diff --git a/erpnext/e_commerce/shopping_cart/__init__.py b/erpnext/e_commerce/shopping_cart/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py similarity index 93% rename from erpnext/shopping_cart/cart.py rename to erpnext/e_commerce/shopping_cart/cart.py index e9f4bd57a6a..b4295d2105b 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/e_commerce/shopping_cart/cart.py @@ -2,23 +2,27 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe import throw, _ import frappe.defaults -from frappe.utils import cint, flt, get_fullname, cstr +from frappe import _, throw from frappe.contacts.doctype.address.address import get_address_display -from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings -from frappe.utils.nestedset import get_root_of -from erpnext.accounts.utils import get_account_name -from erpnext.utilities.product import get_qty_in_stock from frappe.contacts.doctype.contact.contact import get_contact_name +from frappe.utils import cint, cstr, flt, get_fullname +from frappe.utils.nestedset import get_root_of + +from erpnext.accounts.utils import get_account_name +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + get_shopping_cart_settings, +) +from erpnext.utilities.product import get_web_item_qty_in_stock class WebsitePriceListMissingError(frappe.ValidationError): pass def set_cart_count(quotation=None): - if cint(frappe.db.get_singles_value("Shopping Cart Settings", "enabled")): + if cint(frappe.db.get_singles_value("E Commerce Settings", "enabled")): if not quotation: quotation = _get_cart_quotation() cart_count = cstr(len(quotation.get("items"))) @@ -45,7 +49,7 @@ def get_cart_quotation(doc=None): "shipping_addresses": get_shipping_addresses(party), "billing_addresses": get_billing_addresses(party), "shipping_rules": get_applicable_shipping_rules(party), - "cart_settings": frappe.get_cached_doc("Shopping Cart Settings") + "cart_settings": frappe.get_cached_doc("E Commerce Settings") } @frappe.whitelist() @@ -69,7 +73,7 @@ def get_billing_addresses(party=None): @frappe.whitelist() def place_order(): quotation = _get_cart_quotation() - cart_settings = frappe.db.get_value("Shopping Cart Settings", None, + cart_settings = frappe.db.get_value("E Commerce Settings", None, ["company", "allow_items_not_in_stock"], as_dict=1) quotation.company = cart_settings.company @@ -89,11 +93,17 @@ def place_order(): if not cint(cart_settings.allow_items_not_in_stock): for item in sales_order.get("items"): - item.reserved_warehouse, is_stock_item = frappe.db.get_value("Item", - item.item_code, ["website_warehouse", "is_stock_item"]) + item.warehouse = frappe.db.get_value( + "Website Item", + { + "item_code": item.item_code + }, + "website_warehouse" + ) + is_stock_item = frappe.db.get_value("Item", item.item_code, "is_stock_item") if is_stock_item: - item_stock = get_qty_in_stock(item.item_code, "website_warehouse") + item_stock = get_web_item_qty_in_stock(item.item_code, "website_warehouse") if not cint(item_stock.in_stock): throw(_("{1} Not in Stock").format(item.item_code)) if item.qty > item_stock.stock_qty[0][0]: @@ -153,9 +163,8 @@ def update_cart(item_code, qty, additional_notes=None, with_items=False): set_cart_count(quotation) - context = get_cart_quotation(quotation) - if cint(with_items): + context = get_cart_quotation(quotation) return { "items": frappe.render_template("templates/includes/cart/cart_items.html", context), @@ -164,8 +173,7 @@ def update_cart(item_code, qty, additional_notes=None, with_items=False): } else: return { - 'name': quotation.name, - 'shopping_cart_menu': get_shopping_cart_menu(context) + 'name': quotation.name } @frappe.whitelist() @@ -259,13 +267,17 @@ def guess_territory(): territory = frappe.db.get_value("Territory", geoip_country) return territory or \ - frappe.db.get_value("Shopping Cart Settings", None, "territory") or \ + frappe.db.get_value("E Commerce Settings", None, "territory") or \ get_root_of("Territory") def decorate_quotation_doc(doc): for d in doc.get("items", []): - d.update(frappe.db.get_value("Item", d.item_code, - ["thumbnail", "website_image", "description", "route"], as_dict=True)) + d.update(frappe.db.get_value( + "Website Item", + {"item_code": d.item_code}, + ["web_item_name", "thumbnail", "website_image", "description", "route"], + as_dict=True) + ) return doc @@ -282,7 +294,7 @@ def _get_cart_quotation(party=None): if quotation: qdoc = frappe.get_doc("Quotation", quotation[0].name) else: - company = frappe.db.get_value("Shopping Cart Settings", None, ["company"]) + company = frappe.db.get_value("E Commerce Settings", None, ["company"]) qdoc = frappe.get_doc({ "doctype": "Quotation", "naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-", @@ -337,7 +349,7 @@ def apply_cart_settings(party=None, quotation=None): if not quotation: quotation = _get_cart_quotation(party) - cart_settings = frappe.get_doc("Shopping Cart Settings") + cart_settings = frappe.get_doc("E Commerce Settings") set_price_list_and_rate(quotation, cart_settings) @@ -414,7 +426,7 @@ def get_party(user=None): party_doctype = contact.links[0].link_doctype party = contact.links[0].link_name - cart_settings = frappe.get_doc("Shopping Cart Settings") + cart_settings = frappe.get_doc("E Commerce Settings") debtors_account = '' diff --git a/erpnext/shopping_cart/product_info.py b/erpnext/e_commerce/shopping_cart/product_info.py similarity index 55% rename from erpnext/shopping_cart/product_info.py rename to erpnext/e_commerce/shopping_cart/product_info.py index 6c9e531a4d1..5e3bdc5c362 100644 --- a/erpnext/shopping_cart/product_info.py +++ b/erpnext/e_commerce/shopping_cart/product_info.py @@ -4,10 +4,18 @@ from __future__ import unicode_literals import frappe -from erpnext.shopping_cart.cart import _get_cart_quotation, _set_price_list -from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings \ - import get_shopping_cart_settings, show_quantity_in_website -from erpnext.utilities.product import get_price, get_qty_in_stock, get_non_stock_item_status + +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + get_shopping_cart_settings, + show_quantity_in_website, +) +from erpnext.e_commerce.shopping_cart.cart import _get_cart_quotation, _set_price_list +from erpnext.utilities.product import ( + get_non_stock_item_status, + get_price, + get_web_item_qty_in_stock, +) + @frappe.whitelist(allow_guest=True) def get_product_info_for_website(item_code, skip_quotation_creation=False): @@ -23,25 +31,43 @@ def get_product_info_for_website(item_code, skip_quotation_creation=False): selling_price_list = cart_quotation.get("selling_price_list") if cart_quotation else _set_price_list(cart_settings, None) - price = get_price( - item_code, - selling_price_list, - cart_settings.default_customer_group, - cart_settings.company - ) + price = {} + if cart_settings.show_price: + is_guest = frappe.session.user == "Guest" + # Show Price if logged in. + # If not logged in, check if price is hidden for guest. + if not is_guest or not cart_settings.hide_price_for_guest: + price = get_price( + item_code, + selling_price_list, + cart_settings.default_customer_group, + cart_settings.company + ) - stock_status = get_qty_in_stock(item_code, "website_warehouse") + stock_status = None + + if cart_settings.show_stock_availability: + on_backorder = frappe.get_cached_value("Website Item", {"item_code": item_code}, "on_backorder") + if on_backorder: + stock_status = frappe._dict({"on_backorder": True}) + else: + stock_status = get_web_item_qty_in_stock(item_code, "website_warehouse") product_info = { "price": price, - "stock_qty": stock_status.stock_qty, - "in_stock": stock_status.in_stock if stock_status.is_stock_item else get_non_stock_item_status(item_code, "website_warehouse"), "qty": 0, "uom": frappe.db.get_value("Item", item_code, "stock_uom"), - "show_stock_qty": show_quantity_in_website(), "sales_uom": frappe.db.get_value("Item", item_code, "sales_uom") } + if stock_status: + if stock_status.on_backorder: + product_info["on_backorder"] = True + else: + product_info["stock_qty"] = stock_status.stock_qty + product_info["in_stock"] = stock_status.in_stock if stock_status.is_stock_item else get_non_stock_item_status(item_code, "website_warehouse") + product_info["show_stock_qty"] = show_quantity_in_website() + if product_info["price"]: if frappe.session.user != "Guest": item = cart_quotation.get({"item_code": item_code}) if cart_quotation else None diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py similarity index 90% rename from erpnext/shopping_cart/test_shopping_cart.py rename to erpnext/e_commerce/shopping_cart/test_shopping_cart.py index ac61aebc564..96614d0cb64 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py @@ -2,14 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest -import frappe -from frappe.utils import nowdate, add_months -from erpnext.shopping_cart.cart import _get_cart_quotation, update_cart, get_party -from erpnext.tests.utils import create_test_contact_and_address -from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule -# test_dependencies = ['Payment Terms Template'] +import unittest + +import frappe +from frappe.utils import add_months, nowdate + +from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule +from erpnext.e_commerce.doctype.website_item.website_item import make_website_item +from erpnext.e_commerce.shopping_cart.cart import _get_cart_quotation, get_party, update_cart +from erpnext.tests.utils import create_test_contact_and_address + class TestShoppingCart(unittest.TestCase): """ @@ -25,6 +28,11 @@ class TestShoppingCart(unittest.TestCase): frappe.set_user("Administrator") create_test_contact_and_address() self.enable_shopping_cart() + if not frappe.db.exists("Website Item", {"item_code": "_Test Item"}): + make_website_item(frappe.get_cached_doc("Item", "_Test Item")) + + if not frappe.db.exists("Website Item", {"item_code": "_Test Item 2"}): + make_website_item(frappe.get_cached_doc("Item", "_Test Item 2")) def tearDown(self): frappe.set_user("Administrator") @@ -164,7 +172,7 @@ class TestShoppingCart(unittest.TestCase): # helper functions def enable_shopping_cart(self): - settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings") + settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings") settings.update({ "enabled": 1, @@ -194,7 +202,7 @@ class TestShoppingCart(unittest.TestCase): frappe.local.shopping_cart_settings = None def disable_shopping_cart(self): - settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings") + settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings") settings.enabled = 0 settings.save() frappe.local.shopping_cart_settings = None diff --git a/erpnext/shopping_cart/utils.py b/erpnext/e_commerce/shopping_cart/utils.py similarity index 87% rename from erpnext/shopping_cart/utils.py rename to erpnext/e_commerce/shopping_cart/utils.py index 0e1466fd1fa..51398596fd8 100644 --- a/erpnext/shopping_cart/utils.py +++ b/erpnext/e_commerce/shopping_cart/utils.py @@ -5,7 +5,9 @@ from __future__ import unicode_literals import frappe import frappe.defaults -from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import is_cart_enabled + +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import is_cart_enabled + def show_cart_count(): if (is_cart_enabled() and @@ -18,7 +20,7 @@ def set_cart_count(login_manager): role, parties = check_customer_or_supplier() if role == 'Supplier': return if show_cart_count(): - from erpnext.shopping_cart.cart import set_cart_count + from erpnext.e_commerce.shopping_cart.cart import set_cart_count set_cart_count() def clear_cart_count(login_manager): diff --git a/erpnext/e_commerce/variant_selector/__init__.py b/erpnext/e_commerce/variant_selector/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/portal/product_configurator/item_variants_cache.py b/erpnext/e_commerce/variant_selector/item_variants_cache.py similarity index 99% rename from erpnext/portal/product_configurator/item_variants_cache.py rename to erpnext/e_commerce/variant_selector/item_variants_cache.py index fc294ce58bb..636ae8d4917 100644 --- a/erpnext/portal/product_configurator/item_variants_cache.py +++ b/erpnext/e_commerce/variant_selector/item_variants_cache.py @@ -1,5 +1,6 @@ import frappe + class ItemVariantsCacheManager: def __init__(self, item_code): self.item_code = item_code diff --git a/erpnext/e_commerce/variant_selector/test_variant_selector.py b/erpnext/e_commerce/variant_selector/test_variant_selector.py new file mode 100644 index 00000000000..c70fee5fff5 --- /dev/null +++ b/erpnext/e_commerce/variant_selector/test_variant_selector.py @@ -0,0 +1,11 @@ +# import frappe +import unittest + +# from erpnext.e_commerce.product_data_engine.query import ProductQuery +# from erpnext.e_commerce.doctype.website_item.website_item import make_website_item + +test_dependencies = ["Item"] + +class TestVariantSelector(unittest.TestCase): + # TODO: Variant Selector Tests + pass \ No newline at end of file diff --git a/erpnext/e_commerce/variant_selector/utils.py b/erpnext/e_commerce/variant_selector/utils.py new file mode 100644 index 00000000000..61df3adca58 --- /dev/null +++ b/erpnext/e_commerce/variant_selector/utils.py @@ -0,0 +1,197 @@ +import frappe +from frappe.utils import cint + +from erpnext.e_commerce.variant_selector.item_variants_cache import ItemVariantsCacheManager + + +def get_item_codes_by_attributes(attribute_filters, template_item_code=None): + items = [] + + for attribute, values in attribute_filters.items(): + attribute_values = values + + if not isinstance(attribute_values, list): + attribute_values = [attribute_values] + + if not attribute_values: + continue + + wheres = [] + query_values = [] + for attribute_value in attribute_values: + wheres.append('( attribute = %s and attribute_value = %s )') + query_values += [attribute, attribute_value] + + attribute_query = ' or '.join(wheres) + + if template_item_code: + variant_of_query = 'AND t2.variant_of = %s' + query_values.append(template_item_code) + else: + variant_of_query = '' + + query = ''' + SELECT + t1.parent + FROM + `tabItem Variant Attribute` t1 + WHERE + 1 = 1 + AND ( + {attribute_query} + ) + AND EXISTS ( + SELECT + 1 + FROM + `tabItem` t2 + WHERE + t2.name = t1.parent + {variant_of_query} + ) + GROUP BY + t1.parent + ORDER BY + NULL + '''.format(attribute_query=attribute_query, variant_of_query=variant_of_query) + + item_codes = set([r[0] for r in frappe.db.sql(query, query_values)]) + items.append(item_codes) + + res = list(set.intersection(*items)) + + return res + +@frappe.whitelist(allow_guest=True) +def get_attributes_and_values(item_code): + '''Build a list of attributes and their possible values. + This will ignore the values upon selection of which there cannot exist one item. + ''' + item_cache = ItemVariantsCacheManager(item_code) + item_variants_data = item_cache.get_item_variants_data() + + attributes = get_item_attributes(item_code) + attribute_list = [a.attribute for a in attributes] + + valid_options = {} + for item_code, attribute, attribute_value in item_variants_data: + if attribute in attribute_list: + valid_options.setdefault(attribute, set()).add(attribute_value) + + item_attribute_values = frappe.db.get_all('Item Attribute Value', + ['parent', 'attribute_value', 'idx'], order_by='parent asc, idx asc') + ordered_attribute_value_map = frappe._dict() + for iv in item_attribute_values: + ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value) + + # build attribute values in idx order + for attr in attributes: + valid_attribute_values = valid_options.get(attr.attribute, []) + ordered_values = ordered_attribute_value_map.get(attr.attribute, []) + attr['values'] = [v for v in ordered_values if v in valid_attribute_values] + + return attributes + + +@frappe.whitelist(allow_guest=True) +def get_next_attribute_and_values(item_code, selected_attributes): + '''Find the count of Items that match the selected attributes. + Also, find the attribute values that are not applicable for further searching. + If less than equal to 10 items are found, return item_codes of those items. + If one item is matched exactly, return item_code of that item. + ''' + selected_attributes = frappe.parse_json(selected_attributes) + + item_cache = ItemVariantsCacheManager(item_code) + item_variants_data = item_cache.get_item_variants_data() + + attributes = get_item_attributes(item_code) + attribute_list = [a.attribute for a in attributes] + filtered_items = get_items_with_selected_attributes(item_code, selected_attributes) + + next_attribute = None + + for attribute in attribute_list: + if attribute not in selected_attributes: + next_attribute = attribute + break + + valid_options_for_attributes = frappe._dict() + + for a in attribute_list: + valid_options_for_attributes[a] = set() + + selected_attribute = selected_attributes.get(a, None) + if selected_attribute: + # already selected attribute values are valid options + valid_options_for_attributes[a].add(selected_attribute) + + for row in item_variants_data: + item_code, attribute, attribute_value = row + if item_code in filtered_items and attribute not in selected_attributes and attribute in attribute_list: + valid_options_for_attributes[attribute].add(attribute_value) + + optional_attributes = item_cache.get_optional_attributes() + exact_match = [] + # search for exact match if all selected attributes are required attributes + if len(selected_attributes.keys()) >= (len(attribute_list) - len(optional_attributes)): + item_attribute_value_map = item_cache.get_item_attribute_value_map() + for item_code, attr_dict in item_attribute_value_map.items(): + if item_code in filtered_items and set(attr_dict.keys()) == set(selected_attributes.keys()): + exact_match.append(item_code) + + filtered_items_count = len(filtered_items) + + # get product info if exact match + from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website + if exact_match: + data = get_product_info_for_website(exact_match[0]) + product_info = data.product_info + if product_info: + product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock) + if not data.cart_settings.show_price: + product_info = None + else: + product_info = None + + return { + 'next_attribute': next_attribute, + 'valid_options_for_attributes': valid_options_for_attributes, + 'filtered_items_count': filtered_items_count, + 'filtered_items': filtered_items if filtered_items_count < 10 else [], + 'exact_match': exact_match, + 'product_info': product_info + } + + +def get_items_with_selected_attributes(item_code, selected_attributes): + item_cache = ItemVariantsCacheManager(item_code) + attribute_value_item_map = item_cache.get_attribute_value_item_map() + + items = [] + for attribute, value in selected_attributes.items(): + filtered_items = attribute_value_item_map.get((attribute, value), []) + items.append(set(filtered_items)) + + return set.intersection(*items) + +# utilities + +def get_item_attributes(item_code): + attributes = frappe.db.get_all('Item Variant Attribute', + fields=['attribute'], + filters={ + 'parenttype': 'Item', + 'parent': item_code + }, + order_by='idx asc' + ) + + optional_attributes = ItemVariantsCacheManager(item_code).get_optional_attributes() + + for a in attributes: + if a.attribute in optional_attributes: + a.optional = True + + return attributes + diff --git a/erpnext/e_commerce/web_template/__init__.py b/erpnext/e_commerce/web_template/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/web_template/hero_slider/__init__.py b/erpnext/e_commerce/web_template/hero_slider/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/shopping_cart/web_template/hero_slider/hero_slider.html b/erpnext/e_commerce/web_template/hero_slider/hero_slider.html similarity index 100% rename from erpnext/shopping_cart/web_template/hero_slider/hero_slider.html rename to erpnext/e_commerce/web_template/hero_slider/hero_slider.html diff --git a/erpnext/shopping_cart/web_template/hero_slider/hero_slider.json b/erpnext/e_commerce/web_template/hero_slider/hero_slider.json similarity index 98% rename from erpnext/shopping_cart/web_template/hero_slider/hero_slider.json rename to erpnext/e_commerce/web_template/hero_slider/hero_slider.json index 04fb1d27059..2b1807c9651 100644 --- a/erpnext/shopping_cart/web_template/hero_slider/hero_slider.json +++ b/erpnext/e_commerce/web_template/hero_slider/hero_slider.json @@ -1,4 +1,5 @@ { + "__unsaved": 1, "creation": "2020-11-17 15:21:51.207221", "docstatus": 0, "doctype": "Web Template", @@ -273,9 +274,9 @@ } ], "idx": 2, - "modified": "2020-12-29 12:30:02.794994", + "modified": "2021-02-24 15:57:05.889709", "modified_by": "Administrator", - "module": "Shopping Cart", + "module": "E-commerce", "name": "Hero Slider", "owner": "Administrator", "standard": 1, diff --git a/erpnext/e_commerce/web_template/item_card_group/__init__.py b/erpnext/e_commerce/web_template/item_card_group/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/shopping_cart/web_template/item_card_group/item_card_group.html b/erpnext/e_commerce/web_template/item_card_group/item_card_group.html similarity index 86% rename from erpnext/shopping_cart/web_template/item_card_group/item_card_group.html rename to erpnext/e_commerce/web_template/item_card_group/item_card_group.html index fe061d5f5f5..33d7bccc23a 100644 --- a/erpnext/shopping_cart/web_template/item_card_group/item_card_group.html +++ b/erpnext/e_commerce/web_template/item_card_group/item_card_group.html @@ -25,9 +25,8 @@ {%- if item -%} {%- set item = frappe.get_doc("Item", item) -%} {{ item_card( - item.item_name, item.image, item.route, item.description, - None, item.item_group, values['card_' + index + '_featured'], - True, "Center" + item, is_featured=values['card_' + index + '_featured'], + is_full_width=True, align="Center" ) }} {%- endif -%} {%- endfor -%} diff --git a/erpnext/shopping_cart/web_template/item_card_group/item_card_group.json b/erpnext/e_commerce/web_template/item_card_group/item_card_group.json similarity index 97% rename from erpnext/shopping_cart/web_template/item_card_group/item_card_group.json rename to erpnext/e_commerce/web_template/item_card_group/item_card_group.json index ad087b04704..724c4379121 100644 --- a/erpnext/shopping_cart/web_template/item_card_group/item_card_group.json +++ b/erpnext/e_commerce/web_template/item_card_group/item_card_group.json @@ -17,15 +17,12 @@ "reqd": 0 }, { - "__unsaved": 1, "fieldname": "primary_action_label", "fieldtype": "Data", "label": "Primary Action Label", "reqd": 0 }, { - "__islocal": 1, - "__unsaved": 1, "fieldname": "primary_action", "fieldtype": "Data", "label": "Primary Action", @@ -262,9 +259,9 @@ } ], "idx": 0, - "modified": "2020-11-19 18:48:52.633045", + "modified": "2021-02-24 16:05:31.242342", "modified_by": "Administrator", - "module": "Shopping Cart", + "module": "E-commerce", "name": "Item Card Group", "owner": "Administrator", "standard": 1, diff --git a/erpnext/e_commerce/web_template/product_card/__init__.py b/erpnext/e_commerce/web_template/product_card/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/web_template/product_card/product_card.html b/erpnext/e_commerce/web_template/product_card/product_card.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/shopping_cart/web_template/product_card/product_card.json b/erpnext/e_commerce/web_template/product_card/product_card.json similarity index 82% rename from erpnext/shopping_cart/web_template/product_card/product_card.json rename to erpnext/e_commerce/web_template/product_card/product_card.json index 1059c1b2519..2eb73741efb 100644 --- a/erpnext/shopping_cart/web_template/product_card/product_card.json +++ b/erpnext/e_commerce/web_template/product_card/product_card.json @@ -5,7 +5,6 @@ "doctype": "Web Template", "fields": [ { - "__unsaved": 1, "fieldname": "item", "fieldtype": "Link", "label": "Item", @@ -13,7 +12,6 @@ "reqd": 0 }, { - "__unsaved": 1, "fieldname": "featured", "fieldtype": "Check", "label": "Featured", @@ -22,9 +20,9 @@ } ], "idx": 0, - "modified": "2020-11-17 15:33:34.982515", + "modified": "2021-02-24 16:05:17.926610", "modified_by": "Administrator", - "module": "Shopping Cart", + "module": "E-commerce", "name": "Product Card", "owner": "Administrator", "standard": 1, diff --git a/erpnext/e_commerce/web_template/product_category_cards/__init__.py b/erpnext/e_commerce/web_template/product_category_cards/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.html b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html similarity index 81% rename from erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.html rename to erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html index 06b76af9018..6d75a8b1d5e 100644 --- a/erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.html +++ b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html @@ -6,8 +6,15 @@ }) -%}
{% if image %} - {{ title }} + {{ title }} + {% else %} +
+ + {{ frappe.utils.get_abbr(title or '') }} + +
{% endif %} +
{{ title or '' }}
diff --git a/erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.json b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json similarity index 95% rename from erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.json rename to erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json index ba5f63b48b2..0202165d08e 100644 --- a/erpnext/shopping_cart/web_template/product_category_cards/product_category_cards.json +++ b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json @@ -74,9 +74,9 @@ } ], "idx": 0, - "modified": "2020-11-18 17:26:28.726260", + "modified": "2021-02-24 16:03:33.835635", "modified_by": "Administrator", - "module": "Shopping Cart", + "module": "E-commerce", "name": "Product Category Cards", "owner": "Administrator", "standard": 1, diff --git a/erpnext/education/__init__.py b/erpnext/education/__init__.py index c0589bb489b..a3164b25970 100644 --- a/erpnext/education/__init__.py +++ b/erpnext/education/__init__.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe import _ + class StudentNotInGroupError(frappe.ValidationError): pass def validate_student_belongs_to_group(student, student_group): diff --git a/erpnext/education/api.py b/erpnext/education/api.py index 4493a3fef17..d2a8805c897 100644 --- a/erpnext/education/api.py +++ b/erpnext/education/api.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ -from frappe.model.mapper import get_mapped_doc -from frappe.utils import flt, cstr, getdate from frappe.email.doctype.email_group.email_group import add_subscribers +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cstr, flt, getdate + def get_course(program): '''Return list of courses for a particular program diff --git a/erpnext/education/doctype/academic_term/academic_term.py b/erpnext/education/doctype/academic_term/academic_term.py index fa7f2899dcb..b8e22b68c62 100644 --- a/erpnext/education/doctype/academic_term/academic_term.py +++ b/erpnext/education/doctype/academic_term/academic_term.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate from frappe.model.document import Document +from frappe.utils import getdate + class AcademicTerm(Document): def autoname(self): diff --git a/erpnext/education/doctype/academic_term/academic_term_dashboard.py b/erpnext/education/doctype/academic_term/academic_term_dashboard.py index eb2f90742ce..a1087b8fc42 100644 --- a/erpnext/education/doctype/academic_term/academic_term_dashboard.py +++ b/erpnext/education/doctype/academic_term/academic_term_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'academic_term', diff --git a/erpnext/education/doctype/academic_term/test_academic_term.py b/erpnext/education/doctype/academic_term/test_academic_term.py index 0964a56454b..6329103870f 100644 --- a/erpnext/education/doctype/academic_term/test_academic_term.py +++ b/erpnext/education/doctype/academic_term/test_academic_term.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Academic Term') diff --git a/erpnext/education/doctype/academic_year/academic_year.py b/erpnext/education/doctype/academic_year/academic_year.py index f2858a42d4b..77b67d8a5d7 100644 --- a/erpnext/education/doctype/academic_year/academic_year.py +++ b/erpnext/education/doctype/academic_year/academic_year.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _ from frappe.model.document import Document + class AcademicYear(Document): def validate(self): #Check that start of academic year is earlier than end of academic year diff --git a/erpnext/education/doctype/academic_year/academic_year_dashboard.py b/erpnext/education/doctype/academic_year/academic_year_dashboard.py index d3734df8036..49d68c3af28 100644 --- a/erpnext/education/doctype/academic_year/academic_year_dashboard.py +++ b/erpnext/education/doctype/academic_year/academic_year_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'academic_year', diff --git a/erpnext/education/doctype/academic_year/test_academic_year.py b/erpnext/education/doctype/academic_year/test_academic_year.py index 9da75a72143..31135c40f38 100644 --- a/erpnext/education/doctype/academic_year/test_academic_year.py +++ b/erpnext/education/doctype/academic_year/test_academic_year.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Academic Year') diff --git a/erpnext/education/doctype/article/article.py b/erpnext/education/doctype/article/article.py index b5cc5cbc7a6..f3c77880fc1 100644 --- a/erpnext/education/doctype/article/article.py +++ b/erpnext/education/doctype/article/article.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class Article(Document): def get_article(self): pass diff --git a/erpnext/education/doctype/article/test_article.py b/erpnext/education/doctype/article/test_article.py index 2fce07f82c1..cda79ad4579 100644 --- a/erpnext/education/doctype/article/test_article.py +++ b/erpnext/education/doctype/article/test_article.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestArticle(unittest.TestCase): pass diff --git a/erpnext/education/doctype/assessment_criteria/assessment_criteria.py b/erpnext/education/doctype/assessment_criteria/assessment_criteria.py index bfbf26cf6c1..f8f04bf5135 100644 --- a/erpnext/education/doctype/assessment_criteria/assessment_criteria.py +++ b/erpnext/education/doctype/assessment_criteria/assessment_criteria.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document diff --git a/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.py b/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.py index fc0d7451108..1098d0369fb 100644 --- a/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.py +++ b/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Assessment Criteria') diff --git a/erpnext/education/doctype/assessment_criteria_group/assessment_criteria_group.py b/erpnext/education/doctype/assessment_criteria_group/assessment_criteria_group.py index 75381e1d0bf..e62c0305520 100644 --- a/erpnext/education/doctype/assessment_criteria_group/assessment_criteria_group.py +++ b/erpnext/education/doctype/assessment_criteria_group/assessment_criteria_group.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssessmentCriteriaGroup(Document): pass diff --git a/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.py b/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.py index 5b293371bb8..d65f1e78d1d 100644 --- a/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.py +++ b/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Assessment Criteria Group') diff --git a/erpnext/education/doctype/assessment_group/assessment_group.py b/erpnext/education/doctype/assessment_group/assessment_group.py index 88acc124d31..3425109331f 100644 --- a/erpnext/education/doctype/assessment_group/assessment_group.py +++ b/erpnext/education/doctype/assessment_group/assessment_group.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssessmentGroup(Document): pass diff --git a/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py b/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py index 1a23606a61d..83438c0ed74 100644 --- a/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py +++ b/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'assessment_group', diff --git a/erpnext/education/doctype/assessment_group/test_assessment_group.py b/erpnext/education/doctype/assessment_group/test_assessment_group.py index 2fd98b6d02f..822d65c9bb7 100644 --- a/erpnext/education/doctype/assessment_group/test_assessment_group.py +++ b/erpnext/education/doctype/assessment_group/test_assessment_group.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Assessment Group') diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan.py b/erpnext/education/doctype/assessment_plan/assessment_plan.py index 16136c19f71..2a58a313cdd 100644 --- a/erpnext/education/doctype/assessment_plan/assessment_plan.py +++ b/erpnext/education/doctype/assessment_plan/assessment_plan.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + import frappe from frappe import _ +from frappe.model.document import Document + class AssessmentPlan(Document): def validate(self): diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py index 8ac3faf6dde..672953852ed 100644 --- a/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py +++ b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'assessment_plan', diff --git a/erpnext/education/doctype/assessment_plan/test_assessment_plan.py b/erpnext/education/doctype/assessment_plan/test_assessment_plan.py index 2de4f23f5b9..9a6b8860358 100644 --- a/erpnext/education/doctype/assessment_plan/test_assessment_plan.py +++ b/erpnext/education/doctype/assessment_plan/test_assessment_plan.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Assessment Plan') diff --git a/erpnext/education/doctype/assessment_plan_criteria/assessment_plan_criteria.py b/erpnext/education/doctype/assessment_plan_criteria/assessment_plan_criteria.py index 53b477f700a..795462d6308 100644 --- a/erpnext/education/doctype/assessment_plan_criteria/assessment_plan_criteria.py +++ b/erpnext/education/doctype/assessment_plan_criteria/assessment_plan_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssessmentPlanCriteria(Document): pass diff --git a/erpnext/education/doctype/assessment_result/assessment_result.py b/erpnext/education/doctype/assessment_result/assessment_result.py index 7dfe0cf6c27..01f483f8b0b 100644 --- a/erpnext/education/doctype/assessment_result/assessment_result.py +++ b/erpnext/education/doctype/assessment_result/assessment_result.py @@ -3,14 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt from frappe.model.document import Document -from erpnext.education.api import get_grade -from erpnext.education.api import get_assessment_details +from frappe.utils import flt from frappe.utils.csvutils import getlink + import erpnext.education +from erpnext.education.api import get_assessment_details, get_grade + class AssessmentResult(Document): def validate(self): diff --git a/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py b/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py index 2526076d308..f9e2008ebc7 100644 --- a/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py +++ b/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'reports': [ diff --git a/erpnext/education/doctype/assessment_result/test_assessment_result.py b/erpnext/education/doctype/assessment_result/test_assessment_result.py index adce57769dd..fa0ad1f692c 100644 --- a/erpnext/education/doctype/assessment_result/test_assessment_result.py +++ b/erpnext/education/doctype/assessment_result/test_assessment_result.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + from erpnext.education.api import get_grade # test_records = frappe.get_test_records('Assessment Result') diff --git a/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.py b/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.py index d0515931590..234dff044f5 100644 --- a/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.py +++ b/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssessmentResultDetail(Document): pass diff --git a/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.py b/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.py index a0d286ccbe9..83b4f5634e9 100644 --- a/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.py +++ b/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class AssessmentResultTool(Document): pass diff --git a/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.py b/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.py index f784ccb256b..bcc57220e78 100644 --- a/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.py +++ b/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestAssessmentResultTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/content_activity/content_activity.py b/erpnext/education/doctype/content_activity/content_activity.py index 2ae7a5c94c9..076e2d37c00 100644 --- a/erpnext/education/doctype/content_activity/content_activity.py +++ b/erpnext/education/doctype/content_activity/content_activity.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ContentActivity(Document): pass diff --git a/erpnext/education/doctype/content_question/content_question.py b/erpnext/education/doctype/content_question/content_question.py index b239d211a3f..9c2491697de 100644 --- a/erpnext/education/doctype/content_question/content_question.py +++ b/erpnext/education/doctype/content_question/content_question.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ContentQuestion(Document): pass diff --git a/erpnext/education/doctype/content_question/test_content_question.py b/erpnext/education/doctype/content_question/test_content_question.py index 268b9be2e7a..f6bd49bb802 100644 --- a/erpnext/education/doctype/content_question/test_content_question.py +++ b/erpnext/education/doctype/content_question/test_content_question.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestContentQuestion(unittest.TestCase): pass diff --git a/erpnext/education/doctype/course/course.py b/erpnext/education/doctype/course/course.py index 92f92ed9f3e..9cc373a5fe2 100644 --- a/erpnext/education/doctype/course/course.py +++ b/erpnext/education/doctype/course/course.py @@ -3,10 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json -from frappe.model.document import Document + +import frappe from frappe import _ +from frappe.model.document import Document + class Course(Document): def validate(self): diff --git a/erpnext/education/doctype/course/course_dashboard.py b/erpnext/education/doctype/course/course_dashboard.py index 8de91b1c092..8eca2a13509 100644 --- a/erpnext/education/doctype/course/course_dashboard.py +++ b/erpnext/education/doctype/course/course_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'course', diff --git a/erpnext/education/doctype/course/test_course.py b/erpnext/education/doctype/course/test_course.py index 4667ac45a23..dd43ef447c2 100644 --- a/erpnext/education/doctype/course/test_course.py +++ b/erpnext/education/doctype/course/test_course.py @@ -2,11 +2,12 @@ # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt from __future__ import unicode_literals -from erpnext.education.doctype.topic.test_topic import make_topic -from erpnext.education.doctype.topic.test_topic import make_topic_and_linked_content + +import unittest import frappe -import unittest + +from erpnext.education.doctype.topic.test_topic import make_topic, make_topic_and_linked_content # test_records = frappe.get_test_records('Course') diff --git a/erpnext/education/doctype/course_activity/course_activity.py b/erpnext/education/doctype/course_activity/course_activity.py index 3aa1ea0c5b3..61b51a05a16 100644 --- a/erpnext/education/doctype/course_activity/course_activity.py +++ b/erpnext/education/doctype/course_activity/course_activity.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class CourseActivity(Document): def validate(self): self.check_if_enrolled() diff --git a/erpnext/education/doctype/course_activity/test_course_activity.py b/erpnext/education/doctype/course_activity/test_course_activity.py index 5269a6b71a3..778cefecab1 100644 --- a/erpnext/education/doctype/course_activity/test_course_activity.py +++ b/erpnext/education/doctype/course_activity/test_course_activity.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestCourseActivity(unittest.TestCase): pass diff --git a/erpnext/education/doctype/course_assessment_criteria/course_assessment_criteria.py b/erpnext/education/doctype/course_assessment_criteria/course_assessment_criteria.py index ade2a390a27..df384c53143 100644 --- a/erpnext/education/doctype/course_assessment_criteria/course_assessment_criteria.py +++ b/erpnext/education/doctype/course_assessment_criteria/course_assessment_criteria.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CourseAssessmentCriteria(Document): pass diff --git a/erpnext/education/doctype/course_content/course_content.py b/erpnext/education/doctype/course_content/course_content.py index 0d2f85ab500..1dd08adbb01 100644 --- a/erpnext/education/doctype/course_content/course_content.py +++ b/erpnext/education/doctype/course_content/course_content.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CourseContent(Document): pass diff --git a/erpnext/education/doctype/course_content/test_course_content.py b/erpnext/education/doctype/course_content/test_course_content.py index 9be4b1f5ce3..320fa111f7e 100644 --- a/erpnext/education/doctype/course_content/test_course_content.py +++ b/erpnext/education/doctype/course_content/test_course_content.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCourseContent(unittest.TestCase): pass diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py index ce88990a70d..21e74516f89 100644 --- a/erpnext/education/doctype/course_enrollment/course_enrollment.py +++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from functools import reduce + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import get_link_to_form -from functools import reduce + class CourseEnrollment(Document): def validate(self): diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py b/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py index 37972fe354c..253325c586e 100644 --- a/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py +++ b/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'enrollment', diff --git a/erpnext/education/doctype/course_enrollment/test_course_enrollment.py b/erpnext/education/doctype/course_enrollment/test_course_enrollment.py index 874bf121f47..e5feb1b7f7c 100644 --- a/erpnext/education/doctype/course_enrollment/test_course_enrollment.py +++ b/erpnext/education/doctype/course_enrollment/test_course_enrollment.py @@ -3,14 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe -from erpnext.education.doctype.student.test_student import create_student -from erpnext.education.doctype.student.test_student import get_student -from erpnext.education.doctype.program.test_program import setup_program from erpnext.education.doctype.course_activity.test_course_activity import make_course_activity +from erpnext.education.doctype.program.test_program import setup_program +from erpnext.education.doctype.student.test_student import create_student, get_student + class TestCourseEnrollment(unittest.TestCase): def setUp(self): diff --git a/erpnext/education/doctype/course_schedule/course_schedule.py b/erpnext/education/doctype/course_schedule/course_schedule.py index 748728d104e..38379e4c778 100644 --- a/erpnext/education/doctype/course_schedule/course_schedule.py +++ b/erpnext/education/doctype/course_schedule/course_schedule.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class CourseSchedule(Document): def validate(self): self.instructor_name = frappe.db.get_value("Instructor", self.instructor, "instructor_name") diff --git a/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py b/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py index 22ce7e1ec24..12a1735f4ea 100644 --- a/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py +++ b/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'course_schedule', diff --git a/erpnext/education/doctype/course_schedule/test_course_schedule.py b/erpnext/education/doctype/course_schedule/test_course_schedule.py index 5bb4de85846..1b45ceda484 100644 --- a/erpnext/education/doctype/course_schedule/test_course_schedule.py +++ b/erpnext/education/doctype/course_schedule/test_course_schedule.py @@ -3,13 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe +import datetime import unittest -import datetime -from frappe.utils import today, to_timedelta +import frappe +from frappe.utils import to_timedelta, today + from erpnext.education.utils import OverlapError -from frappe.utils.make_random import get_random # test_records = frappe.get_test_records('Course Schedule') diff --git a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py index 0f2ea96a583..4f7ed368211 100644 --- a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py +++ b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import calendar + +import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import add_days, getdate + from erpnext.education.utils import OverlapError @@ -95,7 +98,7 @@ class CourseSchedulingTool(Document): if self.day == calendar.day_name[getdate(d.schedule_date).weekday()]: frappe.delete_doc("Course Schedule", d.name) rescheduled.append(d.name) - except: + except Exception: reschedule_errors.append(d.name) return rescheduled, reschedule_errors diff --git a/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.py b/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.py index d921f8e0e15..27379b70e1c 100644 --- a/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.py +++ b/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCourseSchedulingTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/course_topic/course_topic.py b/erpnext/education/doctype/course_topic/course_topic.py index 2364f17a49c..11eb457b7c3 100644 --- a/erpnext/education/doctype/course_topic/course_topic.py +++ b/erpnext/education/doctype/course_topic/course_topic.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CourseTopic(Document): pass diff --git a/erpnext/education/doctype/course_topic/test_course_topic.py b/erpnext/education/doctype/course_topic/test_course_topic.py index 7ce46d28adf..0bba7f54788 100644 --- a/erpnext/education/doctype/course_topic/test_course_topic.py +++ b/erpnext/education/doctype/course_topic/test_course_topic.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCourseTopic(unittest.TestCase): pass diff --git a/erpnext/education/doctype/education_settings/education_settings.py b/erpnext/education/doctype/education_settings/education_settings.py index 6c7e95c80da..71d13f733bd 100644 --- a/erpnext/education/doctype/education_settings/education_settings.py +++ b/erpnext/education/doctype/education_settings/education_settings.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe import frappe.defaults from frappe.model.document import Document diff --git a/erpnext/education/doctype/education_settings/test_education_settings.py b/erpnext/education/doctype/education_settings/test_education_settings.py index 038fb6e57e1..3611cbef21a 100644 --- a/erpnext/education/doctype/education_settings/test_education_settings.py +++ b/erpnext/education/doctype/education_settings/test_education_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEducationSettings(unittest.TestCase): pass diff --git a/erpnext/education/doctype/fee_category/fee_category.py b/erpnext/education/doctype/fee_category/fee_category.py index 55234442bae..f531f8af6ee 100644 --- a/erpnext/education/doctype/fee_category/fee_category.py +++ b/erpnext/education/doctype/fee_category/fee_category.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class FeeCategory(Document): pass diff --git a/erpnext/education/doctype/fee_category/test_fee_category.py b/erpnext/education/doctype/fee_category/test_fee_category.py index 48e7589a0c0..875568416f5 100644 --- a/erpnext/education/doctype/fee_category/test_fee_category.py +++ b/erpnext/education/doctype/fee_category/test_fee_category.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Fee Category') diff --git a/erpnext/education/doctype/fee_component/fee_component.py b/erpnext/education/doctype/fee_component/fee_component.py index 8694610927b..dba39af5948 100644 --- a/erpnext/education/doctype/fee_component/fee_component.py +++ b/erpnext/education/doctype/fee_component/fee_component.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class FeeComponent(Document): pass diff --git a/erpnext/education/doctype/fee_schedule/fee_schedule.py b/erpnext/education/doctype/fee_schedule/fee_schedule.py index 0b025c75347..6bf46671790 100644 --- a/erpnext/education/doctype/fee_schedule/fee_schedule.py +++ b/erpnext/education/doctype/fee_schedule/fee_schedule.py @@ -3,13 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc -from frappe.utils import money_in_words -from frappe.utils import cint, flt, cstr +from frappe.utils import cint, cstr, flt, money_in_words from frappe.utils.background_jobs import enqueue -from frappe import _ + +import erpnext class FeeSchedule(Document): diff --git a/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py b/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py index 4d7da21ea17..34f870578fd 100644 --- a/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py +++ b/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'fee_schedule', diff --git a/erpnext/education/doctype/fee_schedule/test_fee_schedule.py b/erpnext/education/doctype/fee_schedule/test_fee_schedule.py index 44e0756d64d..86b74de3421 100644 --- a/erpnext/education/doctype/fee_schedule/test_fee_schedule.py +++ b/erpnext/education/doctype/fee_schedule/test_fee_schedule.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestFeeSchedule(unittest.TestCase): pass diff --git a/erpnext/education/doctype/fee_schedule_program/fee_schedule_program.py b/erpnext/education/doctype/fee_schedule_program/fee_schedule_program.py index 11d56973808..5e9ed61ba82 100644 --- a/erpnext/education/doctype/fee_schedule_program/fee_schedule_program.py +++ b/erpnext/education/doctype/fee_schedule_program/fee_schedule_program.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class FeeScheduleProgram(Document): pass diff --git a/erpnext/education/doctype/fee_schedule_student_group/fee_schedule_student_group.py b/erpnext/education/doctype/fee_schedule_student_group/fee_schedule_student_group.py index 776534d6faf..ba30a91516f 100644 --- a/erpnext/education/doctype/fee_schedule_student_group/fee_schedule_student_group.py +++ b/erpnext/education/doctype/fee_schedule_student_group/fee_schedule_student_group.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class FeeScheduleStudentGroup(Document): pass diff --git a/erpnext/education/doctype/fee_structure/fee_structure.py b/erpnext/education/doctype/fee_structure/fee_structure.py index 9755717ee94..a6cc7019215 100644 --- a/erpnext/education/doctype/fee_structure/fee_structure.py +++ b/erpnext/education/doctype/fee_structure/fee_structure.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc diff --git a/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py b/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py index fdf7df7aa26..c053b4ea4ba 100644 --- a/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py +++ b/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'fee_structure', diff --git a/erpnext/education/doctype/fee_structure/test_fee_structure.py b/erpnext/education/doctype/fee_structure/test_fee_structure.py index 785ae4e7d37..1311f13997e 100644 --- a/erpnext/education/doctype/fee_structure/test_fee_structure.py +++ b/erpnext/education/doctype/fee_structure/test_fee_structure.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Fee Structure') diff --git a/erpnext/education/doctype/fees/fees.py b/erpnext/education/doctype/fees/fees.py index 7e867049047..a5dc0dca31c 100644 --- a/erpnext/education/doctype/fees/fees.py +++ b/erpnext/education/doctype/fees/fees.py @@ -3,14 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document -import frappe, erpnext + +import frappe from frappe import _ from frappe.utils import money_in_words -from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request from frappe.utils.csvutils import getlink -from erpnext.controllers.accounts_controller import AccountsController + +import erpnext +from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request from erpnext.accounts.general_ledger import make_reverse_gl_entries +from erpnext.controllers.accounts_controller import AccountsController class Fees(AccountsController): diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py index c6bb704b412..fbf7a571fe8 100644 --- a/erpnext/education/doctype/fees/test_fees.py +++ b/erpnext/education/doctype/fees/test_fees.py @@ -3,10 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import nowdate from frappe.utils.make_random import get_random + from erpnext.education.doctype.program.test_program import make_program_and_linked_courses test_dependencies = ['Company'] diff --git a/erpnext/education/doctype/grading_scale/grading_scale.py b/erpnext/education/doctype/grading_scale/grading_scale.py index 0e732971619..ed75f31d841 100644 --- a/erpnext/education/doctype/grading_scale/grading_scale.py +++ b/erpnext/education/doctype/grading_scale/grading_scale.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cint from frappe.model.document import Document +from frappe.utils import cint + class GradingScale(Document): def validate(self): diff --git a/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py b/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py index 2a3f13b156d..268871a04e8 100644 --- a/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py +++ b/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'grading_scale', diff --git a/erpnext/education/doctype/grading_scale/test_grading_scale.py b/erpnext/education/doctype/grading_scale/test_grading_scale.py index 5364d7c8879..e5d83c20c12 100644 --- a/erpnext/education/doctype/grading_scale/test_grading_scale.py +++ b/erpnext/education/doctype/grading_scale/test_grading_scale.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Grading Scale') diff --git a/erpnext/education/doctype/grading_scale_interval/grading_scale_interval.py b/erpnext/education/doctype/grading_scale_interval/grading_scale_interval.py index 41ac5ffd5c0..6e55aac40ba 100644 --- a/erpnext/education/doctype/grading_scale_interval/grading_scale_interval.py +++ b/erpnext/education/doctype/grading_scale_interval/grading_scale_interval.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class GradingScaleInterval(Document): pass diff --git a/erpnext/education/doctype/guardian/guardian.py b/erpnext/education/doctype/guardian/guardian.py index e82cc546af4..f79e1310345 100644 --- a/erpnext/education/doctype/guardian/guardian.py +++ b/erpnext/education/doctype/guardian/guardian.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils.csvutils import getlink + class Guardian(Document): def __setup__(self): self.onload() diff --git a/erpnext/education/doctype/guardian/test_guardian.py b/erpnext/education/doctype/guardian/test_guardian.py index 61420f6cec5..446e2612215 100644 --- a/erpnext/education/doctype/guardian/test_guardian.py +++ b/erpnext/education/doctype/guardian/test_guardian.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Guardian') diff --git a/erpnext/education/doctype/guardian_interest/guardian_interest.py b/erpnext/education/doctype/guardian_interest/guardian_interest.py index f5c4cf1d49c..4a3040f0600 100644 --- a/erpnext/education/doctype/guardian_interest/guardian_interest.py +++ b/erpnext/education/doctype/guardian_interest/guardian_interest.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class GuardianInterest(Document): pass diff --git a/erpnext/education/doctype/guardian_student/guardian_student.py b/erpnext/education/doctype/guardian_student/guardian_student.py index bf6f5c13730..62867d89089 100644 --- a/erpnext/education/doctype/guardian_student/guardian_student.py +++ b/erpnext/education/doctype/guardian_student/guardian_student.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class GuardianStudent(Document): pass diff --git a/erpnext/education/doctype/instructor/instructor.py b/erpnext/education/doctype/instructor/instructor.py index b1bfcbb2f10..92fb8b04b90 100644 --- a/erpnext/education/doctype/instructor/instructor.py +++ b/erpnext/education/doctype/instructor/instructor.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.model.naming import set_name_by_naming_series + class Instructor(Document): def autoname(self): naming_method = frappe.db.get_value("Education Settings", None, "instructor_created_by") diff --git a/erpnext/education/doctype/instructor/instructor_dashboard.py b/erpnext/education/doctype/instructor/instructor_dashboard.py index c19c85947d6..bb08a54903c 100644 --- a/erpnext/education/doctype/instructor/instructor_dashboard.py +++ b/erpnext/education/doctype/instructor/instructor_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/education/doctype/instructor/test_instructor.py b/erpnext/education/doctype/instructor/test_instructor.py index 4061422a74d..b698a20e111 100644 --- a/erpnext/education/doctype/instructor/test_instructor.py +++ b/erpnext/education/doctype/instructor/test_instructor.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Instructor') diff --git a/erpnext/education/doctype/instructor_log/instructor_log.py b/erpnext/education/doctype/instructor_log/instructor_log.py index 75217b22f67..68ab7a639e9 100644 --- a/erpnext/education/doctype/instructor_log/instructor_log.py +++ b/erpnext/education/doctype/instructor_log/instructor_log.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class InstructorLog(Document): pass diff --git a/erpnext/education/doctype/options/options.py b/erpnext/education/doctype/options/options.py index a11d77afb23..a064384129b 100644 --- a/erpnext/education/doctype/options/options.py +++ b/erpnext/education/doctype/options/options.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class Options(Document): pass diff --git a/erpnext/education/doctype/program/program.py b/erpnext/education/doctype/program/program.py index 9d886b7b9e6..7de34cf30fb 100644 --- a/erpnext/education/doctype/program/program.py +++ b/erpnext/education/doctype/program/program.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class Program(Document): def get_course_list(self): diff --git a/erpnext/education/doctype/program/program_dashboard.py b/erpnext/education/doctype/program/program_dashboard.py index 6c503e1bf1f..66960767f16 100644 --- a/erpnext/education/doctype/program/program_dashboard.py +++ b/erpnext/education/doctype/program/program_dashboard.py @@ -1,5 +1,6 @@ from frappe import _ + def get_data(): return { 'fieldname': 'program', diff --git a/erpnext/education/doctype/program/test_program.py b/erpnext/education/doctype/program/test_program.py index 204f2961e7f..3222aa6004b 100644 --- a/erpnext/education/doctype/program/test_program.py +++ b/erpnext/education/doctype/program/test_program.py @@ -2,12 +2,13 @@ # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt from __future__ import unicode_literals -from erpnext.education.doctype.course.test_course import make_course -from erpnext.education.doctype.topic.test_topic import make_topic_and_linked_content -from erpnext.education.doctype.course.test_course import make_course_and_linked_topic + +import unittest import frappe -import unittest + +from erpnext.education.doctype.course.test_course import make_course, make_course_and_linked_topic +from erpnext.education.doctype.topic.test_topic import make_topic_and_linked_content test_data = { "program_name": "_Test Program", diff --git a/erpnext/education/doctype/program_course/program_course.py b/erpnext/education/doctype/program_course/program_course.py index 684b6fade76..d5236a109a4 100644 --- a/erpnext/education/doctype/program_course/program_course.py +++ b/erpnext/education/doctype/program_course/program_course.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProgramCourse(Document): pass diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py index dd4aa576ac0..79c5a14d8c8 100644 --- a/erpnext/education/doctype/program_enrollment/program_enrollment.py +++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py @@ -3,12 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _, msgprint +from frappe.desk.reportview import get_match_cond from frappe.model.document import Document -from frappe.desk.reportview import get_match_cond, get_filters_cond from frappe.utils import comma_and, get_link_to_form, getdate -import erpnext.www.lms as lms + class ProgramEnrollment(Document): def validate(self): diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py b/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py index c47f8666898..f829276dac9 100644 --- a/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py +++ b/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'program_enrollment', diff --git a/erpnext/education/doctype/program_enrollment/test_program_enrollment.py b/erpnext/education/doctype/program_enrollment/test_program_enrollment.py index 497ee288aac..65de38af2dd 100644 --- a/erpnext/education/doctype/program_enrollment/test_program_enrollment.py +++ b/erpnext/education/doctype/program_enrollment/test_program_enrollment.py @@ -3,13 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.education.doctype.student.test_student import create_student -from erpnext.education.doctype.student.test_student import get_student +import frappe + from erpnext.education.doctype.program.test_program import make_program_and_linked_courses -from erpnext.education.doctype.course_activity.test_course_activity import make_course_activity +from erpnext.education.doctype.student.test_student import create_student, get_student + class TestProgramEnrollment(unittest.TestCase): diff --git a/erpnext/education/doctype/program_enrollment_course/program_enrollment_course.py b/erpnext/education/doctype/program_enrollment_course/program_enrollment_course.py index e1f564eff0f..5c0706dbce1 100644 --- a/erpnext/education/doctype/program_enrollment_course/program_enrollment_course.py +++ b/erpnext/education/doctype/program_enrollment_course/program_enrollment_course.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProgramEnrollmentCourse(Document): pass diff --git a/erpnext/education/doctype/program_enrollment_fee/program_enrollment_fee.py b/erpnext/education/doctype/program_enrollment_fee/program_enrollment_fee.py index 03a311e1640..53bae7c1504 100644 --- a/erpnext/education/doctype/program_enrollment_fee/program_enrollment_fee.py +++ b/erpnext/education/doctype/program_enrollment_fee/program_enrollment_fee.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProgramEnrollmentFee(Document): pass diff --git a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py index 5833b67f9bb..69fa66558d3 100644 --- a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py +++ b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from erpnext.education.api import enroll_student from frappe.utils import cint +from erpnext.education.api import enroll_student + + class ProgramEnrollmentTool(Document): def onload(self): academic_term_reqd = cint(frappe.db.get_single_value('Education Settings', 'academic_term_reqd')) diff --git a/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.py b/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.py index f22b3b1c8d4..55734cbc94b 100644 --- a/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.py +++ b/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestProgramEnrollmentTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/program_enrollment_tool_student/program_enrollment_tool_student.py b/erpnext/education/doctype/program_enrollment_tool_student/program_enrollment_tool_student.py index 38dc1c8437a..67653458f5f 100644 --- a/erpnext/education/doctype/program_enrollment_tool_student/program_enrollment_tool_student.py +++ b/erpnext/education/doctype/program_enrollment_tool_student/program_enrollment_tool_student.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProgramEnrollmentToolStudent(Document): pass diff --git a/erpnext/education/doctype/program_fee/program_fee.py b/erpnext/education/doctype/program_fee/program_fee.py index cadcc4eeb80..70105ee6be9 100644 --- a/erpnext/education/doctype/program_fee/program_fee.py +++ b/erpnext/education/doctype/program_fee/program_fee.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProgramFee(Document): pass diff --git a/erpnext/education/doctype/question/question.py b/erpnext/education/doctype/question/question.py index fb3b50478c8..e74aa93ad8e 100644 --- a/erpnext/education/doctype/question/question.py +++ b/erpnext/education/doctype/question/question.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class Question(Document): def validate(self): diff --git a/erpnext/education/doctype/question/test_question.py b/erpnext/education/doctype/question/test_question.py index 552872e15fb..1ce10c0cb83 100644 --- a/erpnext/education/doctype/question/test_question.py +++ b/erpnext/education/doctype/question/test_question.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQuestion(unittest.TestCase): pass diff --git a/erpnext/education/doctype/quiz/quiz.py b/erpnext/education/doctype/quiz/quiz.py index a128e1f3427..474bea111b9 100644 --- a/erpnext/education/doctype/quiz/quiz.py +++ b/erpnext/education/doctype/quiz/quiz.py @@ -3,11 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import json from frappe import _ from frappe.model.document import Document + class Quiz(Document): def validate(self): if self.passing_score > 100: diff --git a/erpnext/education/doctype/quiz/test_quiz.py b/erpnext/education/doctype/quiz/test_quiz.py index 344fd544ee8..22eb23d4fda 100644 --- a/erpnext/education/doctype/quiz/test_quiz.py +++ b/erpnext/education/doctype/quiz/test_quiz.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQuiz(unittest.TestCase): pass diff --git a/erpnext/education/doctype/quiz_activity/quiz_activity.py b/erpnext/education/doctype/quiz_activity/quiz_activity.py index 24c7175397d..0fc76032283 100644 --- a/erpnext/education/doctype/quiz_activity/quiz_activity.py +++ b/erpnext/education/doctype/quiz_activity/quiz_activity.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class QuizActivity(Document): pass diff --git a/erpnext/education/doctype/quiz_activity/test_quiz_activity.py b/erpnext/education/doctype/quiz_activity/test_quiz_activity.py index fb0425d8096..44e3a3f92ba 100644 --- a/erpnext/education/doctype/quiz_activity/test_quiz_activity.py +++ b/erpnext/education/doctype/quiz_activity/test_quiz_activity.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQuizActivity(unittest.TestCase): pass diff --git a/erpnext/education/doctype/quiz_question/quiz_question.py b/erpnext/education/doctype/quiz_question/quiz_question.py index 317e75b2cb2..20cb9f7b38c 100644 --- a/erpnext/education/doctype/quiz_question/quiz_question.py +++ b/erpnext/education/doctype/quiz_question/quiz_question.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class QuizQuestion(Document): pass diff --git a/erpnext/education/doctype/quiz_result/quiz_result.py b/erpnext/education/doctype/quiz_result/quiz_result.py index a4fd9f062f3..059d294cff6 100644 --- a/erpnext/education/doctype/quiz_result/quiz_result.py +++ b/erpnext/education/doctype/quiz_result/quiz_result.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class QuizResult(Document): pass diff --git a/erpnext/education/doctype/quiz_result/test_quiz_result.py b/erpnext/education/doctype/quiz_result/test_quiz_result.py index 86ee52d87d3..08ac4811bca 100644 --- a/erpnext/education/doctype/quiz_result/test_quiz_result.py +++ b/erpnext/education/doctype/quiz_result/test_quiz_result.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQuizResult(unittest.TestCase): pass diff --git a/erpnext/education/doctype/room/room.py b/erpnext/education/doctype/room/room.py index f26e9c4b45b..dc68a0dd0cf 100644 --- a/erpnext/education/doctype/room/room.py +++ b/erpnext/education/doctype/room/room.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class Room(Document): pass diff --git a/erpnext/education/doctype/room/room_dashboard.py b/erpnext/education/doctype/room/room_dashboard.py index 7bcb97f709f..6a43b6037f8 100644 --- a/erpnext/education/doctype/room/room_dashboard.py +++ b/erpnext/education/doctype/room/room_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'room', diff --git a/erpnext/education/doctype/room/test_room.py b/erpnext/education/doctype/room/test_room.py index 33ffd9173e1..5718d51d658 100644 --- a/erpnext/education/doctype/room/test_room.py +++ b/erpnext/education/doctype/room/test_room.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Room') diff --git a/erpnext/education/doctype/school_house/school_house.py b/erpnext/education/doctype/school_house/school_house.py index 8751e5c646c..2f9c5f46a80 100644 --- a/erpnext/education/doctype/school_house/school_house.py +++ b/erpnext/education/doctype/school_house/school_house.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SchoolHouse(Document): pass diff --git a/erpnext/education/doctype/school_house/test_school_house.py b/erpnext/education/doctype/school_house/test_school_house.py index 5cf96d5daa2..b58b7d49ce1 100644 --- a/erpnext/education/doctype/school_house/test_school_house.py +++ b/erpnext/education/doctype/school_house/test_school_house.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestSchoolHouse(unittest.TestCase): pass diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py index 6be9e7104b2..ae498ba57db 100644 --- a/erpnext/education/doctype/student/student.py +++ b/erpnext/education/doctype/student/student.py @@ -3,12 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document -from frappe.utils import getdate,today from frappe import _ from frappe.desk.form.linked_with import get_linked_doctypes +from frappe.model.document import Document +from frappe.utils import getdate, today + from erpnext.education.utils import check_content_completion, check_quiz_completion + + class Student(Document): def validate(self): self.title = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name])) diff --git a/erpnext/education/doctype/student/student_dashboard.py b/erpnext/education/doctype/student/student_dashboard.py index d2614628b10..efff2e64907 100644 --- a/erpnext/education/doctype/student/student_dashboard.py +++ b/erpnext/education/doctype/student/student_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/education/doctype/student/test_student.py b/erpnext/education/doctype/student/test_student.py index fcb2b5fb930..ec6abb56efb 100644 --- a/erpnext/education/doctype/student/test_student.py +++ b/erpnext/education/doctype/student/test_student.py @@ -2,12 +2,12 @@ # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt from __future__ import unicode_literals -from frappe.test_runner import make_test_records -from erpnext.education.doctype.program.test_program import make_program_and_linked_courses -from erpnext.education.doctype.course.test_course import make_course + +import unittest import frappe -import unittest + +from erpnext.education.doctype.program.test_program import make_program_and_linked_courses test_records = frappe.get_test_records('Student') class TestStudent(unittest.TestCase): diff --git a/erpnext/education/doctype/student_admission/student_admission.py b/erpnext/education/doctype/student_admission/student_admission.py index 0febb96aebb..67ef67b4aa2 100644 --- a/erpnext/education/doctype/student_admission/student_admission.py +++ b/erpnext/education/doctype/student_admission/student_admission.py @@ -3,6 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import nowdate diff --git a/erpnext/education/doctype/student_admission/test_student_admission.py b/erpnext/education/doctype/student_admission/test_student_admission.py index 748c7ae1b39..c9cfbca14a7 100644 --- a/erpnext/education/doctype/student_admission/test_student_admission.py +++ b/erpnext/education/doctype/student_admission/test_student_admission.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Admission') diff --git a/erpnext/education/doctype/student_admission_program/student_admission_program.py b/erpnext/education/doctype/student_admission_program/student_admission_program.py index 406027ca2cb..2377d2648da 100644 --- a/erpnext/education/doctype/student_admission_program/student_admission_program.py +++ b/erpnext/education/doctype/student_admission_program/student_admission_program.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class StudentAdmissionProgram(Document): pass diff --git a/erpnext/education/doctype/student_applicant/student_applicant.py b/erpnext/education/doctype/student_applicant/student_applicant.py index 193b6d32977..36a0757531b 100644 --- a/erpnext/education/doctype/student_applicant/student_applicant.py +++ b/erpnext/education/doctype/student_applicant/student_applicant.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import print_function, unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import getdate, add_years, nowdate, date_diff +from frappe.utils import add_years, date_diff, getdate, nowdate + class StudentApplicant(Document): def autoname(self): diff --git a/erpnext/education/doctype/student_applicant/test_student_applicant.py b/erpnext/education/doctype/student_applicant/test_student_applicant.py index 9734a88b935..b7258a4ae1d 100644 --- a/erpnext/education/doctype/student_applicant/test_student_applicant.py +++ b/erpnext/education/doctype/student_applicant/test_student_applicant.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Applicant') diff --git a/erpnext/education/doctype/student_attendance/student_attendance.py b/erpnext/education/doctype/student_attendance/student_attendance.py index 2e9e6cf8d65..3826afb0492 100644 --- a/erpnext/education/doctype/student_attendance/student_attendance.py +++ b/erpnext/education/doctype/student_attendance/student_attendance.py @@ -3,14 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import get_link_to_form, getdate, formatdate +from frappe.model.document import Document +from frappe.utils import formatdate, get_link_to_form, getdate + from erpnext import get_default_company from erpnext.education.api import get_student_group_students from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday + class StudentAttendance(Document): def validate(self): self.validate_mandatory() diff --git a/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py b/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py index e405b8aed9d..489f64d6804 100644 --- a/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py +++ b/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'reports': [ diff --git a/erpnext/education/doctype/student_attendance/test_student_attendance.py b/erpnext/education/doctype/student_attendance/test_student_attendance.py index 9f4153845b5..d453aeda1c6 100644 --- a/erpnext/education/doctype/student_attendance/test_student_attendance.py +++ b/erpnext/education/doctype/student_attendance/test_student_attendance.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Attendance') diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py index 972973fbadb..96767deb6d2 100644 --- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py +++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class StudentAttendanceTool(Document): pass diff --git a/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.py b/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.py index ffc42af4749..a94a3f235df 100644 --- a/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.py +++ b/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestStudentAttendanceTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/student_batch_name/student_batch_name.py b/erpnext/education/doctype/student_batch_name/student_batch_name.py index e6d38ea2545..ce507160e05 100644 --- a/erpnext/education/doctype/student_batch_name/student_batch_name.py +++ b/erpnext/education/doctype/student_batch_name/student_batch_name.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentBatchName(Document): pass diff --git a/erpnext/education/doctype/student_batch_name/test_student_batch_name.py b/erpnext/education/doctype/student_batch_name/test_student_batch_name.py index 09534f355c9..75ebeb29b80 100644 --- a/erpnext/education/doctype/student_batch_name/test_student_batch_name.py +++ b/erpnext/education/doctype/student_batch_name/test_student_batch_name.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Batch Name') diff --git a/erpnext/education/doctype/student_category/student_category.py b/erpnext/education/doctype/student_category/student_category.py index bd3a8358898..bb362d5834a 100644 --- a/erpnext/education/doctype/student_category/student_category.py +++ b/erpnext/education/doctype/student_category/student_category.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentCategory(Document): pass diff --git a/erpnext/education/doctype/student_category/student_category_dashboard.py b/erpnext/education/doctype/student_category/student_category_dashboard.py index f31c34bd941..92386237883 100644 --- a/erpnext/education/doctype/student_category/student_category_dashboard.py +++ b/erpnext/education/doctype/student_category/student_category_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'student_category', diff --git a/erpnext/education/doctype/student_category/test_student_category.py b/erpnext/education/doctype/student_category/test_student_category.py index 756cab87eb8..0893769045e 100644 --- a/erpnext/education/doctype/student_category/test_student_category.py +++ b/erpnext/education/doctype/student_category/test_student_category.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Category') diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py index 3d4572abf70..2347d317317 100644 --- a/erpnext/education/doctype/student_group/student_group.py +++ b/erpnext/education/doctype/student_group/student_group.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from erpnext.education.utils import validate_duplicate_student +from frappe.model.document import Document from frappe.utils import cint +from erpnext.education.utils import validate_duplicate_student + + class StudentGroup(Document): def validate(self): self.validate_mandatory_fields() diff --git a/erpnext/education/doctype/student_group/student_group_dashboard.py b/erpnext/education/doctype/student_group/student_group_dashboard.py index d37445f7b98..36329bd8d85 100644 --- a/erpnext/education/doctype/student_group/student_group_dashboard.py +++ b/erpnext/education/doctype/student_group/student_group_dashboard.py @@ -1,8 +1,10 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'student_group', diff --git a/erpnext/education/doctype/student_group/test_student_group.py b/erpnext/education/doctype/student_group/test_student_group.py index 8b9b47d9ceb..06022511e5b 100644 --- a/erpnext/education/doctype/student_group/test_student_group.py +++ b/erpnext/education/doctype/student_group/test_student_group.py @@ -3,10 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + import erpnext.education + def get_random_group(): doc = frappe.get_doc({ "doctype": "Student Group", diff --git a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py index 28ff7d618c1..2007f8aa7cc 100644 --- a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py +++ b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + from erpnext.education.doctype.student_group.student_group import get_students + class StudentGroupCreationTool(Document): @frappe.whitelist() def get_courses(self): diff --git a/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.py b/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.py index 9ca56588f2c..432da090134 100644 --- a/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.py +++ b/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestStudentGroupCreationTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/student_group_creation_tool_course/student_group_creation_tool_course.py b/erpnext/education/doctype/student_group_creation_tool_course/student_group_creation_tool_course.py index b3411ea7c55..b9d1e0d7fe7 100644 --- a/erpnext/education/doctype/student_group_creation_tool_course/student_group_creation_tool_course.py +++ b/erpnext/education/doctype/student_group_creation_tool_course/student_group_creation_tool_course.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentGroupCreationToolCourse(Document): pass diff --git a/erpnext/education/doctype/student_group_instructor/student_group_instructor.py b/erpnext/education/doctype/student_group_instructor/student_group_instructor.py index b6cc588b673..81a7ed25af5 100644 --- a/erpnext/education/doctype/student_group_instructor/student_group_instructor.py +++ b/erpnext/education/doctype/student_group_instructor/student_group_instructor.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentGroupInstructor(Document): pass diff --git a/erpnext/education/doctype/student_group_student/student_group_student.py b/erpnext/education/doctype/student_group_student/student_group_student.py index 1fe4ea1dc35..7ee4caec5e3 100644 --- a/erpnext/education/doctype/student_group_student/student_group_student.py +++ b/erpnext/education/doctype/student_group_student/student_group_student.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentGroupStudent(Document): pass diff --git a/erpnext/education/doctype/student_guardian/student_guardian.py b/erpnext/education/doctype/student_guardian/student_guardian.py index 04445bcc594..56d7df7d0a8 100644 --- a/erpnext/education/doctype/student_guardian/student_guardian.py +++ b/erpnext/education/doctype/student_guardian/student_guardian.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentGuardian(Document): pass diff --git a/erpnext/education/doctype/student_language/student_language.py b/erpnext/education/doctype/student_language/student_language.py index be6d5debe4b..6ec0b1fc6e1 100644 --- a/erpnext/education/doctype/student_language/student_language.py +++ b/erpnext/education/doctype/student_language/student_language.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentLanguage(Document): pass diff --git a/erpnext/education/doctype/student_language/test_student_language.py b/erpnext/education/doctype/student_language/test_student_language.py index 592b94a4fc2..1d7c003ae5e 100644 --- a/erpnext/education/doctype/student_language/test_student_language.py +++ b/erpnext/education/doctype/student_language/test_student_language.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Language') diff --git a/erpnext/education/doctype/student_leave_application/student_leave_application.py b/erpnext/education/doctype/student_leave_application/student_leave_application.py index ef670124c31..50c14aae22b 100644 --- a/erpnext/education/doctype/student_leave_application/student_leave_application.py +++ b/erpnext/education/doctype/student_leave_application/student_leave_application.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from datetime import timedelta + import frappe from frappe import _ -from datetime import timedelta -from frappe.utils import get_link_to_form, getdate, date_diff, flt -from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday -from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list from frappe.model.document import Document +from frappe.utils import date_diff, flt, get_link_to_form, getdate + +from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list +from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday + class StudentLeaveApplication(Document): def validate(self): diff --git a/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py b/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py index 0ff6d1a76ea..2674f5415d9 100644 --- a/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py +++ b/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'leave_application', diff --git a/erpnext/education/doctype/student_leave_application/test_student_leave_application.py b/erpnext/education/doctype/student_leave_application/test_student_leave_application.py index 9cae2577481..506dc738d88 100644 --- a/erpnext/education/doctype/student_leave_application/test_student_leave_application.py +++ b/erpnext/education/doctype/student_leave_application/test_student_leave_application.py @@ -3,12 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import getdate, add_days, add_months + +import frappe +from frappe.utils import add_days, add_months, getdate + from erpnext import get_default_company -from erpnext.education.doctype.student_group.test_student_group import get_random_group from erpnext.education.doctype.student.test_student import create_student +from erpnext.education.doctype.student_group.test_student_group import get_random_group + class TestStudentLeaveApplication(unittest.TestCase): def setUp(self): diff --git a/erpnext/education/doctype/student_log/student_log.py b/erpnext/education/doctype/student_log/student_log.py index 8b12886863c..2ca49ca12d3 100644 --- a/erpnext/education/doctype/student_log/student_log.py +++ b/erpnext/education/doctype/student_log/student_log.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentLog(Document): pass diff --git a/erpnext/education/doctype/student_log/test_student_log.py b/erpnext/education/doctype/student_log/test_student_log.py index 1fe191fe955..533191f3b47 100644 --- a/erpnext/education/doctype/student_log/test_student_log.py +++ b/erpnext/education/doctype/student_log/test_student_log.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Student Log') diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py index 17bc3678266..1cf79213150 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py @@ -3,13 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json + +import json + +import frappe from frappe import _ from frappe.model.document import Document -from erpnext.education.api import get_grade from frappe.utils.pdf import get_pdf -from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_formatted_result -from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_child_assessment_groups + +from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import ( + get_child_assessment_groups, + get_formatted_result, +) class StudentReportGenerationTool(Document): diff --git a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py index 417816642ec..f6227136d9d 100644 --- a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py +++ b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestStudentReportGenerationTool(unittest.TestCase): pass diff --git a/erpnext/education/doctype/student_sibling/student_sibling.py b/erpnext/education/doctype/student_sibling/student_sibling.py index 4adc3f35bae..b36cf59dbb3 100644 --- a/erpnext/education/doctype/student_sibling/student_sibling.py +++ b/erpnext/education/doctype/student_sibling/student_sibling.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentSibling(Document): pass diff --git a/erpnext/education/doctype/student_siblings/student_siblings.py b/erpnext/education/doctype/student_siblings/student_siblings.py index 4e20d84ae71..412cf050c16 100644 --- a/erpnext/education/doctype/student_siblings/student_siblings.py +++ b/erpnext/education/doctype/student_siblings/student_siblings.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StudentSiblings(Document): pass diff --git a/erpnext/education/doctype/topic/test_topic.py b/erpnext/education/doctype/topic/test_topic.py index d03db1cb93a..b6c6c7516fa 100644 --- a/erpnext/education/doctype/topic/test_topic.py +++ b/erpnext/education/doctype/topic/test_topic.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestTopic(unittest.TestCase): def setUp(self): make_topic_and_linked_content("_Test Topic 1", [{"type":"Article", "name": "_Test Article 1"}]) diff --git a/erpnext/education/doctype/topic/topic.py b/erpnext/education/doctype/topic/topic.py index fb680d725b0..1834b2e060c 100644 --- a/erpnext/education/doctype/topic/topic.py +++ b/erpnext/education/doctype/topic/topic.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ from frappe.model.document import Document + class Topic(Document): def get_contents(self): try: diff --git a/erpnext/education/doctype/topic_content/test_topic_content.py b/erpnext/education/doctype/topic_content/test_topic_content.py index cf304f60bc3..6fdcbdae717 100644 --- a/erpnext/education/doctype/topic_content/test_topic_content.py +++ b/erpnext/education/doctype/topic_content/test_topic_content.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestTopicContent(unittest.TestCase): pass diff --git a/erpnext/education/doctype/topic_content/topic_content.py b/erpnext/education/doctype/topic_content/topic_content.py index 9b2c90bb4f2..9339bbde5aa 100644 --- a/erpnext/education/doctype/topic_content/topic_content.py +++ b/erpnext/education/doctype/topic_content/topic_content.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TopicContent(Document): pass diff --git a/erpnext/education/report/absent_student_report/absent_student_report.py b/erpnext/education/report/absent_student_report/absent_student_report.py index c3487ccaffb..d5b66757fcd 100644 --- a/erpnext/education/report/absent_student_report/absent_student_report.py +++ b/erpnext/education/report/absent_student_report/absent_student_report.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _, msgprint from frappe.utils import formatdate -from frappe import msgprint, _ + from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/education/report/assessment_plan_status/assessment_plan_status.py b/erpnext/education/report/assessment_plan_status/assessment_plan_status.py index 21184a637ca..64ceb42731a 100644 --- a/erpnext/education/report/assessment_plan_status/assessment_plan_status.py +++ b/erpnext/education/report/assessment_plan_status/assessment_plan_status.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from itertools import groupby + import frappe from frappe import _ -from itertools import groupby from frappe.utils import cint DOCSTATUS = { diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py index 1043e5bd45b..ad07ee1949c 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from collections import OrderedDict, defaultdict + import frappe from frappe import _ -from frappe.utils import flt -from collections import defaultdict, OrderedDict + from erpnext.education.api import get_grade diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.py b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py index e6e0ba2ebc2..ae7f34b5e1c 100644 --- a/erpnext/education/report/final_assessment_grades/final_assessment_grades.py +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py @@ -2,12 +2,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import _ + from collections import defaultdict -from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_formatted_result -from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_chart_data +import frappe +from frappe import _ + +from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import ( + get_chart_data, + get_formatted_result, +) def execute(filters=None): diff --git a/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py index c0ec0357cc6..1717ed55aec 100644 --- a/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py +++ b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py index 5bebd4385c6..a21a93686ef 100644 --- a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py +++ b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py @@ -2,6 +2,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ diff --git a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py index e2576a0c710..b65350f1b22 100644 --- a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py +++ b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _, msgprint from frappe.utils import formatdate -from frappe import msgprint, _ + from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py index 04dc8c0e563..f6d9c5a012e 100644 --- a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py +++ b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py @@ -2,14 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cstr, cint, getdate, get_first_day, get_last_day, date_diff, add_days -from frappe import msgprint, _ -from calendar import monthrange +from frappe import _ +from frappe.utils import add_days, cstr, date_diff, get_first_day, get_last_day, getdate + from erpnext.education.api import get_student_group_students from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list from erpnext.support.doctype.issue.issue import get_holidays + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/education/setup.py b/erpnext/education/setup.py index 5c4092849a7..faa4e39b400 100644 --- a/erpnext/education/setup.py +++ b/erpnext/education/setup.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + from erpnext.setup.utils import insert_record diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py index 3070e6a3e8a..33394e17963 100644 --- a/erpnext/education/utils.py +++ b/erpnext/education/utils.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -from __future__ import unicode_literals, division +from __future__ import division, unicode_literals + import frappe from frappe import _ + class OverlapError(frappe.ValidationError): pass def validate_overlap_for(doc, doctype, fieldname, value=None): @@ -219,7 +221,7 @@ def get_quiz(quiz_name, course): try: quiz = frappe.get_doc("Quiz", quiz_name) questions = quiz.get_questions() - except: + except Exception: frappe.throw(_("Quiz {0} does not exist").format(quiz_name), frappe.DoesNotExistError) return None diff --git a/erpnext/education/web_form/student_applicant/student_applicant.py b/erpnext/education/web_form/student_applicant/student_applicant.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/education/web_form/student_applicant/student_applicant.py +++ b/erpnext/education/web_form/student_applicant/student_applicant.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/erpnext_integrations/connectors/github_connection.py b/erpnext/erpnext_integrations/connectors/github_connection.py index ab7708df305..1d3fced1201 100644 --- a/erpnext/erpnext_integrations/connectors/github_connection.py +++ b/erpnext/erpnext_integrations/connectors/github_connection.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals + import frappe from frappe.data_migration.doctype.data_migration_connector.connectors.base import BaseConnection from github import Github + class GithubConnection(BaseConnection): def __init__(self, connector): self.connector = connector diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py index 912674ff1a2..ff91b09f18e 100644 --- a/erpnext/erpnext_integrations/connectors/shopify_connection.py +++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py @@ -1,14 +1,26 @@ from __future__ import unicode_literals + +import json + import frappe from frappe import _ -import json -from frappe.utils import cstr, cint, nowdate, getdate, flt, get_request_session, get_datetime +from frappe.utils import cint, cstr, flt, get_datetime, get_request_session, getdate, nowdate + +from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import ( + dump_request_data, + make_shopify_log, +) +from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import ( + get_header, + get_shopify_url, +) +from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer +from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import ( + sync_item_from_shopify, +) from erpnext.erpnext_integrations.utils import validate_webhooks_request from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import sync_item_from_shopify -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer -from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log, dump_request_data -from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import get_shopify_url, get_header + @frappe.whitelist(allow_guest=True) @validate_webhooks_request("Shopify Settings", 'X-Shopify-Hmac-Sha256', secret_key='shared_secret') diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index a505ee09d28..192ec147e36 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -1,8 +1,15 @@ from __future__ import unicode_literals -import frappe, base64, hashlib, hmac, json -from frappe.utils import cstr + +import base64 +import hashlib +import hmac +import json + +import frappe from frappe import _ +from frappe.utils import cstr + def verify_request(): woocommerce_settings = frappe.get_doc("Woocommerce Settings") diff --git a/erpnext/erpnext_integrations/data_migration_mapping/issue_to_task/__init__.py b/erpnext/erpnext_integrations/data_migration_mapping/issue_to_task/__init__.py index aeb5352a220..5a4a57c2e25 100644 --- a/erpnext/erpnext_integrations/data_migration_mapping/issue_to_task/__init__.py +++ b/erpnext/erpnext_integrations/data_migration_mapping/issue_to_task/__init__.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def pre_process(issue): project = frappe.db.get_value('Project', filters={'project_name': issue.milestone}) diff --git a/erpnext/erpnext_integrations/data_migration_mapping/milestone_to_project/__init__.py b/erpnext/erpnext_integrations/data_migration_mapping/milestone_to_project/__init__.py index 9d3f02eaaf6..bab8031e024 100644 --- a/erpnext/erpnext_integrations/data_migration_mapping/milestone_to_project/__init__.py +++ b/erpnext/erpnext_integrations/data_migration_mapping/milestone_to_project/__init__.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def pre_process(milestone): return { 'title': milestone.title, diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index 148c1a6a166..c21453a5c53 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -3,10 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, time, dateutil, math, csv -from six import StringIO -import erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_api as mws + +import csv +import math +import time + +import dateutil +import frappe from frappe import _ +from six import StringIO + +import erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_api as mws + #Get and Create Products def get_products_details(): @@ -143,7 +151,6 @@ def create_item_code(amazon_item_json, sku): item.description = amazon_item_json.Product.AttributeSets.ItemAttributes.Title item.brand = new_brand item.manufacturer = new_manufacturer - item.web_long_description = amazon_item_json.Product.AttributeSets.ItemAttributes.Title item.image = amazon_item_json.Product.AttributeSets.ItemAttributes.SmallImage.URL diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py index 7fd3b34fd5d..652fa9200d9 100755 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py @@ -6,24 +6,24 @@ # Extended to include finances object from __future__ import unicode_literals -import urllib -from urllib.parse import quote +import base64 import hashlib import hmac -import base64 -import six -from erpnext.erpnext_integrations.doctype.amazon_mws_settings import xml_utils import re +from urllib.parse import quote + +from erpnext.erpnext_integrations.doctype.amazon_mws_settings import xml_utils + try: from xml.etree.ElementTree import ParseError as XMLError except ImportError: from xml.parsers.expat import ExpatError as XMLError -from time import strftime, gmtime + +from time import gmtime, strftime from requests import request from requests.exceptions import HTTPError - __all__ = [ 'Feeds', 'Inventory', diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py index 9c598401492..ac59eb7925c 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document + import dateutil +import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from frappe.model.document import Document + from erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods import get_orders + class AmazonMWSSettings(Document): def validate(self): if self.enable_amazon == 1: diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py index 7b40014c521..844df59576a 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestAmazonMWSSettings(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py index 99ede8f31de..88ef64d307c 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py @@ -8,8 +8,8 @@ Borrowed from https://github.com/timotheus/ebaysdk-python """ from __future__ import unicode_literals -import xml.etree.ElementTree as ET import re +import xml.etree.ElementTree as ET class object_dict(dict): @@ -88,7 +88,7 @@ class xml2dict(object): ns = http://cs.sfsu.edu/csc867/myscheduler name = patients """ - result = re.compile("\{(.*)\}(.*)").search(tag) + result = re.compile(r"\{(.*)\}(.*)").search(tag) if result: value.namespace, tag = result.groups() diff --git a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py index bff928c1c96..f1314fc122f 100644 --- a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py +++ b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document -import requests + import frappe +import requests from frappe import _ +from frappe.model.document import Document + class ExotelSettings(Document): def validate(self): diff --git a/erpnext/erpnext_integrations/doctype/gocardless_mandate/gocardless_mandate.py b/erpnext/erpnext_integrations/doctype/gocardless_mandate/gocardless_mandate.py index 9c9df653145..b416ce8808f 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_mandate/gocardless_mandate.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_mandate/gocardless_mandate.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class GoCardlessMandate(Document): pass diff --git a/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.py b/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.py index d77a352cdb1..1b76ee5afc7 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestGoCardlessMandate(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py index 25784a5620a..d003edb9b0e 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py @@ -3,10 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -import json -import hmac + import hashlib +import hmac +import json + +import frappe + @frappe.whitelist(allow_guest=True) def webhooks(): diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py index c65e3cefeeb..6484973106a 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py @@ -3,13 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document import gocardless_pro from frappe import _ +from frappe.integrations.utils import create_payment_gateway, create_request_log +from frappe.model.document import Document +from frappe.utils import call_hook_method, cint, flt, get_url from six.moves.urllib.parse import urlencode -from frappe.utils import get_url, call_hook_method, flt, cint -from frappe.integrations.utils import create_request_log, create_payment_gateway + class GoCardlessSettings(Document): supported_currencies = ["EUR", "DKK", "GBP", "SEK"] diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py index e377f3482cb..b17aef50986 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestGoCardlessSettings(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py index d1adeeee072..6d46a1c884a 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py @@ -1,7 +1,9 @@ import base64 +import datetime + import requests from requests.auth import HTTPBasicAuth -import datetime + class MpesaConnector(): def __init__(self, env="sandbox", app_key=None, app_secret=None, sandbox_url="https://sandbox.safaricom.co.ke", diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_custom_fields.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_custom_fields.py index 139e2fb192b..368139b872f 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_custom_fields.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_custom_fields.py @@ -1,6 +1,7 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def create_custom_pos_fields(): """Create custom fields corresponding to POS Settings and POS Invoice.""" pos_field = { diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py index de933578613..4ce85e58a61 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py @@ -4,17 +4,21 @@ from __future__ import unicode_literals -from json import loads, dumps + +from json import dumps, loads import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import call_hook_method, fmt_money -from frappe.integrations.utils import create_request_log, create_payment_gateway -from frappe.utils import get_request_site_address -from erpnext.erpnext_integrations.utils import create_mode_of_payment +from frappe.integrations.utils import create_payment_gateway, create_request_log +from frappe.model.document import Document +from frappe.utils import call_hook_method, fmt_money, get_request_site_address + from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_connector import MpesaConnector -from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_custom_fields import create_custom_pos_fields +from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_custom_fields import ( + create_custom_pos_fields, +) +from erpnext.erpnext_integrations.utils import create_mode_of_payment + class MpesaSettings(Document): supported_currencies = ["KES"] @@ -39,7 +43,9 @@ class MpesaSettings(Document): for i, amount in enumerate(request_amounts): args.request_amount = amount if frappe.flags.in_test: - from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import get_payment_request_response_payload + from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import ( + get_payment_request_response_payload, + ) response = frappe._dict(get_payment_request_response_payload(amount)) else: response = frappe._dict(generate_stk_push(**args)) @@ -71,7 +77,9 @@ class MpesaSettings(Document): ) if frappe.flags.in_test: - from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import get_test_account_balance_response + from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import ( + get_test_account_balance_response, + ) response = frappe._dict(get_test_account_balance_response()) else: response = frappe._dict(get_account_balance(payload)) diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py index d4cb6b982bb..de81b821321 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py @@ -2,13 +2,20 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -from json import dumps -import frappe + import unittest -from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_settings import process_balance_info, verify_transaction +from json import dumps + +import frappe + from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice +from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_settings import ( + process_balance_info, + verify_transaction, +) from erpnext.erpnext_integrations.utils import create_mode_of_payment + class TestMpesaSettings(unittest.TestCase): def setUp(self): # create payment gateway in setup diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py index 73f5927df40..d4cf56af6b2 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py @@ -2,12 +2,11 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +import frappe import plaid import requests -from plaid.errors import APIError, ItemError, InvalidRequestError - -import frappe from frappe import _ +from plaid.errors import APIError, InvalidRequestError, ItemError class PlaidConnector(): diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index eddcb3401f6..d2748c2faad 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -5,15 +5,16 @@ import json import frappe -from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account -from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector from frappe import _ from frappe.desk.doctype.tag.tag import add_tag from frappe.model.document import Document from frappe.utils import add_months, formatdate, getdate, today - from plaid.errors import ItemError +from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account +from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector + + class PlaidSettings(Document): @staticmethod @frappe.whitelist() diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py index e2243eabde0..32b5b8f2657 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py @@ -6,11 +6,16 @@ import json import unittest import frappe +from frappe.utils.response import json_handler + from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings import ( - add_account_subtype, add_account_type, add_bank_accounts, - new_bank_transaction, get_plaid_configuration) -from frappe.utils.response import json_handler + add_account_subtype, + add_account_type, + add_bank_accounts, + get_plaid_configuration, + new_bank_transaction, +) class TestPlaidSettings(unittest.TestCase): diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py index 866ea662788..39b9bb232e0 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py @@ -3,15 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import json +import traceback + import frappe +import requests from frappe import _ from frappe.model.document import Document from requests_oauthlib import OAuth2Session -import json -import requests -import traceback + from erpnext import encode_company_abbr + # QuickBooks requires a redirect URL, User will be redirect to this URL # This will be a GET request # Request parameters will have two parameters `code` and `realmId` @@ -253,8 +257,9 @@ class QuickBooksMigrator(Document): try: # Assumes that exactly one fiscal year has been created so far # Creates fiscal years till oldest ledger entry date is covered - from frappe.utils.data import add_years, getdate from itertools import chain + + from frappe.utils.data import add_years, getdate smallest_ledger_entry_date = getdate(min(entry["date"] for entry in chain(*self.gl_entries.values()) if entry["date"])) oldest_fiscal_year = frappe.get_all("Fiscal Year", fields=["year_start_date", "year_end_date"], diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.py b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.py index 6ce7c92ae8e..5604b40d140 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.py +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQuickBooksMigrator(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py index a2b6af99b21..b000c831947 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py +++ b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe.model.document import Document + from erpnext.erpnext_integrations.utils import get_webhook_address + class ShopifyLog(Document): pass diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py b/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py index 5892e1d6c4e..53d37224452 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py +++ b/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Shopify Log') diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py index 381c5e5dec4..8844148ee71 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py @@ -3,15 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.model.document import Document from frappe.utils import get_request_session from requests.exceptions import HTTPError -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields -from erpnext.erpnext_integrations.utils import get_webhook_address + from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log +from erpnext.erpnext_integrations.utils import get_webhook_address + class ShopifySettings(Document): def validate(self): diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py index 2af57f4c891..8b188516c22 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe import _ + def create_customer(shopify_customer, shopify_settings): import frappe.utils.nestedset diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py index 16efb6caee1..86054634014 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py @@ -1,9 +1,14 @@ from __future__ import unicode_literals + import frappe from frappe import _ +from frappe.utils import cint, cstr, get_request_session + from erpnext import get_default_company -from frappe.utils import cstr, cint, get_request_session -from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import get_shopify_url, get_header +from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import ( + get_header, + get_shopify_url, +) shopify_variants_attr_list = ["option1", "option2", "option3"] diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py index 6bec301b8e7..0e0fa6a7270 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py @@ -2,14 +2,18 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe -import unittest, os, json -from frappe.utils import cstr, cint -from erpnext.erpnext_integrations.connectors.shopify_connection import create_order -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import make_item -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer +import json +import os +import unittest + +import frappe from frappe.core.doctype.data_import.data_import import import_doc +from frappe.utils import cint, cstr + +from erpnext.erpnext_integrations.connectors.shopify_connection import create_order +from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer +from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import make_item class ShopifySettings(unittest.TestCase): diff --git a/erpnext/erpnext_integrations/doctype/shopify_tax_account/shopify_tax_account.py b/erpnext/erpnext_integrations/doctype/shopify_tax_account/shopify_tax_account.py index 74c13c0f6cc..fc7e49b1715 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_tax_account/shopify_tax_account.py +++ b/erpnext/erpnext_integrations/doctype/shopify_tax_account/shopify_tax_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ShopifyTaxAccount(Document): pass diff --git a/erpnext/erpnext_integrations/doctype/shopify_webhook_detail/shopify_webhook_detail.py b/erpnext/erpnext_integrations/doctype/shopify_webhook_detail/shopify_webhook_detail.py index e127989ce34..881f45b1be9 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_webhook_detail/shopify_webhook_detail.py +++ b/erpnext/erpnext_integrations/doctype/shopify_webhook_detail/shopify_webhook_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ShopifyWebhookDetail(Document): pass diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py index 907a22333b7..e1e7f62df4e 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py @@ -11,19 +11,19 @@ import traceback import zipfile from decimal import Decimal -from bs4 import BeautifulSoup as bs - import frappe -from erpnext import encode_company_abbr -from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts -from erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer import unset_existing_data - +from bs4 import BeautifulSoup as bs from frappe import _ from frappe.custom.doctype.custom_field.custom_field import create_custom_field from frappe.model.document import Document -from frappe.model.naming import getseries, revert_series_if_last from frappe.utils.data import format_datetime +from erpnext import encode_company_abbr +from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts +from erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer import ( + unset_existing_data, +) + PRIMARY_ACCOUNT = "Primary" VOUCHER_CHUNK_SIZE = 500 @@ -266,7 +266,7 @@ class TallyMigration(Document): self.is_master_data_processed = 1 - except: + except Exception: self.publish("Process Master Data", _("Process Failed"), -1, 5) self.log() @@ -302,14 +302,14 @@ class TallyMigration(Document): try: party_doc = frappe.get_doc(party) party_doc.insert() - except: + except Exception: self.log(party_doc) addresses_file = frappe.get_doc("File", {"file_url": addresses_file_url}) for address in json.loads(addresses_file.get_content()): try: address_doc = frappe.get_doc(address) address_doc.insert(ignore_mandatory=True) - except: + except Exception: self.log(address_doc) def create_items_uoms(items_file_url, uoms_file_url): @@ -319,7 +319,7 @@ class TallyMigration(Document): try: uom_doc = frappe.get_doc(uom) uom_doc.insert() - except: + except Exception: self.log(uom_doc) items_file = frappe.get_doc("File", {"file_url": items_file_url}) @@ -327,7 +327,7 @@ class TallyMigration(Document): try: item_doc = frappe.get_doc(item) item_doc.insert() - except: + except Exception: self.log(item_doc) try: @@ -346,7 +346,7 @@ class TallyMigration(Document): self.is_master_data_imported = 1 frappe.db.commit() - except: + except Exception: self.publish("Import Master Data", _("Process Failed"), -1, 5) frappe.db.rollback() self.log() @@ -370,7 +370,7 @@ class TallyMigration(Document): if processed_voucher: vouchers.append(processed_voucher) frappe.db.commit() - except: + except Exception: frappe.db.rollback() self.log(voucher) return vouchers @@ -494,7 +494,7 @@ class TallyMigration(Document): self.is_day_book_data_processed = 1 - except: + except Exception: self.publish("Process Day Book Data", _("Process Failed"), -1, 5) self.log() @@ -564,7 +564,7 @@ class TallyMigration(Document): is_last = True frappe.enqueue_doc(self.doctype, self.name, "_import_vouchers", queue="long", timeout=3600, start=index+1, total=total, is_last=is_last) - except: + except Exception: self.log() finally: @@ -583,7 +583,7 @@ class TallyMigration(Document): voucher_doc.submit() self.publish("Importing Vouchers", _("{} of {}").format(index, total), index, total) frappe.db.commit() - except: + except Exception: frappe.db.rollback() self.log(voucher_doc) diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.py index 9f67e55ca16..aae8f6d4db0 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestTallyMigration(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py index 7f5f0f0e7a8..9dd481747ec 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TaxJarSettings(Document): pass diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py index 7cdfd009561..c871b05642b 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestTaxJarSettings(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py index 458a23fae29..3d184584361 100644 --- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py +++ b/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestWoocommerceSettings(unittest.TestCase): pass diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py index 45f261007f8..2e15fab0d3f 100644 --- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py +++ b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py @@ -3,12 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils.nestedset import get_root_of -from frappe.model.document import Document -from six.moves.urllib.parse import urlparse from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.model.document import Document +from frappe.utils.nestedset import get_root_of +from six.moves.urllib.parse import urlparse + class WoocommerceSettings(Document): def validate(self): diff --git a/erpnext/erpnext_integrations/stripe_integration.py b/erpnext/erpnext_integrations/stripe_integration.py index 820c7405328..f0315eb7eef 100644 --- a/erpnext/erpnext_integrations/stripe_integration.py +++ b/erpnext/erpnext_integrations/stripe_integration.py @@ -2,9 +2,8 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -import stripe - import frappe +import stripe from frappe import _ from frappe.integrations.utils import create_request_log diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 83764ae50d8..3af4ff4c08d 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -1,11 +1,13 @@ import traceback + import frappe import taxjar -from erpnext import get_default_company from frappe import _ from frappe.contacts.doctype.address.address import get_company_address from frappe.utils import cint +from erpnext import get_default_company + TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head") TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") diff --git a/erpnext/erpnext_integrations/utils.py b/erpnext/erpnext_integrations/utils.py index caafc0821e1..bb5c0c2dd10 100644 --- a/erpnext/erpnext_integrations/utils.py +++ b/erpnext/erpnext_integrations/utils.py @@ -1,10 +1,16 @@ from __future__ import unicode_literals + +import base64 +import hashlib +import hmac + import frappe from frappe import _ -import base64, hashlib, hmac from six.moves.urllib.parse import urlparse + from erpnext import get_default_company + def validate_webhooks_request(doctype, hmac_key, secret_key='secret'): def innerfn(fn): settings = frappe.get_doc(doctype) diff --git a/erpnext/exceptions.py b/erpnext/exceptions.py index 04291cd5bd1..9c6b13f8035 100644 --- a/erpnext/exceptions.py +++ b/erpnext/exceptions.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + # accounts class PartyFrozen(frappe.ValidationError): pass class InvalidAccountCurrency(frappe.ValidationError): pass diff --git a/erpnext/healthcare/dashboard_chart_source/department_wise_patient_appointments/department_wise_patient_appointments.py b/erpnext/healthcare/dashboard_chart_source/department_wise_patient_appointments/department_wise_patient_appointments.py index eca7143e689..9c71ce86ac4 100644 --- a/erpnext/healthcare/dashboard_chart_source/department_wise_patient_appointments/department_wise_patient_appointments.py +++ b/erpnext/healthcare/dashboard_chart_source/department_wise_patient_appointments/department_wise_patient_appointments.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils.dashboard import cache_source + @frappe.whitelist() @cache_source def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, diff --git a/erpnext/healthcare/doctype/antibiotic/antibiotic.py b/erpnext/healthcare/doctype/antibiotic/antibiotic.py index 8236c8ab73a..6a4b7648b96 100644 --- a/erpnext/healthcare/doctype/antibiotic/antibiotic.py +++ b/erpnext/healthcare/doctype/antibiotic/antibiotic.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Antibiotic(Document): pass diff --git a/erpnext/healthcare/doctype/antibiotic/test_antibiotic.py b/erpnext/healthcare/doctype/antibiotic/test_antibiotic.py index 6ac4f4f9fc0..b6ec79f7ff4 100644 --- a/erpnext/healthcare/doctype/antibiotic/test_antibiotic.py +++ b/erpnext/healthcare/doctype/antibiotic/test_antibiotic.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestAntibiotic(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/appointment_type/appointment_type.py b/erpnext/healthcare/doctype/appointment_type/appointment_type.py index 67a24f31e03..94d023f2c3d 100644 --- a/erpnext/healthcare/doctype/appointment_type/appointment_type.py +++ b/erpnext/healthcare/doctype/appointment_type/appointment_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + import frappe +from frappe.model.document import Document + class AppointmentType(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py b/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py index 845e4466c11..b9c6edbb19c 100644 --- a/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py +++ b/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'appointment_type', diff --git a/erpnext/healthcare/doctype/appointment_type_service_item/appointment_type_service_item.py b/erpnext/healthcare/doctype/appointment_type_service_item/appointment_type_service_item.py index b2e0e82bad0..026d5d79fd9 100644 --- a/erpnext/healthcare/doctype/appointment_type_service_item/appointment_type_service_item.py +++ b/erpnext/healthcare/doctype/appointment_type_service_item/appointment_type_service_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AppointmentTypeServiceItem(Document): pass diff --git a/erpnext/healthcare/doctype/body_part/body_part.py b/erpnext/healthcare/doctype/body_part/body_part.py index 300493a52b6..77e8dd90a07 100644 --- a/erpnext/healthcare/doctype/body_part/body_part.py +++ b/erpnext/healthcare/doctype/body_part/body_part.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class BodyPart(Document): pass diff --git a/erpnext/healthcare/doctype/body_part/test_body_part.py b/erpnext/healthcare/doctype/body_part/test_body_part.py index cb3a61150ef..a81ba179bfe 100644 --- a/erpnext/healthcare/doctype/body_part/test_body_part.py +++ b/erpnext/healthcare/doctype/body_part/test_body_part.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestBodyPart(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/body_part_link/body_part_link.py b/erpnext/healthcare/doctype/body_part_link/body_part_link.py index 03715297692..07488f01177 100644 --- a/erpnext/healthcare/doctype/body_part_link/body_part_link.py +++ b/erpnext/healthcare/doctype/body_part_link/body_part_link.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class BodyPartLink(Document): pass diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py index cbf89ee3bde..df4c2ef9055 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py @@ -3,15 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt, nowdate, nowtime, cstr +from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, nowdate, nowtime + from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account from erpnext.healthcare.doctype.lab_test.lab_test import create_sample_doc -from erpnext.stock.stock_ledger import get_previous_sle from erpnext.stock.get_item_details import get_item_details -from frappe.model.mapper import get_mapped_doc +from erpnext.stock.stock_ledger import get_previous_sle + class ClinicalProcedure(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py index 0326e5e9da7..b5c3744204a 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py +++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py @@ -4,8 +4,13 @@ from __future__ import unicode_literals import unittest + import frappe -from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_clinical_procedure_template + +from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import ( + create_clinical_procedure_template, + create_healthcare_docs, +) test_dependencies = ['Item'] diff --git a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py index d59e5175972..16c5369cfe5 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py +++ b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class ClinicalProcedureItem(Document): pass diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py index 58194f10a8c..16e0969ae40 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json + +import json + +import frappe from frappe import _ from frappe.model.document import Document from frappe.model.rename_doc import rename_doc + class ClinicalProcedureTemplate(Document): def validate(self): self.enable_disable_item() diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py index 9aab5216e1e..a69899d3ead 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'procedure_template', diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py index 62e138b8ed2..f754c76341f 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, earthians and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestClinicalProcedureTemplate(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/codification_table/codification_table.py b/erpnext/healthcare/doctype/codification_table/codification_table.py index ae29c03bbbd..232d92ca9df 100644 --- a/erpnext/healthcare/doctype/codification_table/codification_table.py +++ b/erpnext/healthcare/doctype/codification_table/codification_table.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class CodificationTable(Document): pass diff --git a/erpnext/healthcare/doctype/complaint/complaint.py b/erpnext/healthcare/doctype/complaint/complaint.py index 717f9dbb4ae..20e00f6b029 100644 --- a/erpnext/healthcare/doctype/complaint/complaint.py +++ b/erpnext/healthcare/doctype/complaint/complaint.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Complaint(Document): pass diff --git a/erpnext/healthcare/doctype/complaint/test_complaint.py b/erpnext/healthcare/doctype/complaint/test_complaint.py index 2b9273a9675..d3e10692b03 100644 --- a/erpnext/healthcare/doctype/complaint/test_complaint.py +++ b/erpnext/healthcare/doctype/complaint/test_complaint.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestComplaint(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py index 7ccf6b57aa5..c08604694ab 100644 --- a/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py +++ b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DescriptiveTestResult(Document): pass diff --git a/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py index 281f32db7ff..84184fbcca5 100644 --- a/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py +++ b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DescriptiveTestTemplate(Document): pass diff --git a/erpnext/healthcare/doctype/diagnosis/diagnosis.py b/erpnext/healthcare/doctype/diagnosis/diagnosis.py index f56e79062a5..05add1b5300 100644 --- a/erpnext/healthcare/doctype/diagnosis/diagnosis.py +++ b/erpnext/healthcare/doctype/diagnosis/diagnosis.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Diagnosis(Document): pass diff --git a/erpnext/healthcare/doctype/dosage_form/dosage_form.py b/erpnext/healthcare/doctype/dosage_form/dosage_form.py index 046af08094c..6b2d88b61b8 100644 --- a/erpnext/healthcare/doctype/dosage_form/dosage_form.py +++ b/erpnext/healthcare/doctype/dosage_form/dosage_form.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DosageForm(Document): pass diff --git a/erpnext/healthcare/doctype/dosage_form/test_dosage_form.py b/erpnext/healthcare/doctype/dosage_form/test_dosage_form.py index 81cfcf6f7de..0161b82ba3b 100644 --- a/erpnext/healthcare/doctype/dosage_form/test_dosage_form.py +++ b/erpnext/healthcare/doctype/dosage_form/test_dosage_form.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestDosageForm(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/dosage_strength/dosage_strength.py b/erpnext/healthcare/doctype/dosage_strength/dosage_strength.py index e36a0160cf3..9e74743a7c6 100644 --- a/erpnext/healthcare/doctype/dosage_strength/dosage_strength.py +++ b/erpnext/healthcare/doctype/dosage_strength/dosage_strength.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DosageStrength(Document): pass diff --git a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py index 68a2dc5d3c3..744bdb03ef5 100755 --- a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py +++ b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class DrugPrescription(Document): def get_quantity(self): quantity = 0 diff --git a/erpnext/healthcare/doctype/exercise/exercise.py b/erpnext/healthcare/doctype/exercise/exercise.py index efd89997fec..5d2b1f1a96d 100644 --- a/erpnext/healthcare/doctype/exercise/exercise.py +++ b/erpnext/healthcare/doctype/exercise/exercise.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class Exercise(Document): pass diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py index 17e97b89609..bbb297275f9 100644 --- a/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py +++ b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ExerciseDifficultyLevel(Document): pass diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py b/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py index 80ef3a7de89..dcaea08aba3 100644 --- a/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py +++ b/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestExerciseDifficultyLevel(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.py b/erpnext/healthcare/doctype/exercise_type/exercise_type.py index ae44a2b77b5..48eb6ba2d81 100644 --- a/erpnext/healthcare/doctype/exercise_type/exercise_type.py +++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ExerciseType(Document): def autoname(self): if self.difficulty_level: diff --git a/erpnext/healthcare/doctype/exercise_type/test_exercise_type.py b/erpnext/healthcare/doctype/exercise_type/test_exercise_type.py index bf217e893a6..583aea911ae 100644 --- a/erpnext/healthcare/doctype/exercise_type/test_exercise_type.py +++ b/erpnext/healthcare/doctype/exercise_type/test_exercise_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestExerciseType(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/exercise_type_step/exercise_type_step.py b/erpnext/healthcare/doctype/exercise_type_step/exercise_type_step.py index 13d7e5732f6..412ef3225ed 100644 --- a/erpnext/healthcare/doctype/exercise_type_step/exercise_type_step.py +++ b/erpnext/healthcare/doctype/exercise_type_step/exercise_type_step.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ExerciseTypeStep(Document): pass diff --git a/erpnext/healthcare/doctype/fee_validity/fee_validity.py b/erpnext/healthcare/doctype/fee_validity/fee_validity.py index 59586e0c31b..aa30becd337 100644 --- a/erpnext/healthcare/doctype/fee_validity/fee_validity.py +++ b/erpnext/healthcare/doctype/fee_validity/fee_validity.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document -import frappe -from frappe.utils import getdate + import datetime +import frappe +from frappe.model.document import Document +from frappe.utils import getdate + + class FeeValidity(Document): def validate(self): self.update_status() diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py index 957f85211de..ce1947f5bad 100644 --- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py +++ b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py @@ -3,11 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, add_days -from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_appointment, create_healthcare_service_items + +import frappe +from frappe.utils import add_days, nowdate + from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import ( + create_appointment, + create_healthcare_docs, + create_healthcare_service_items, +) test_dependencies = ["Company"] diff --git a/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py index c8192808320..c03978aad11 100644 --- a/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py +++ b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class FeeValidityReference(Document): pass diff --git a/erpnext/healthcare/doctype/healthcare.py b/erpnext/healthcare/doctype/healthcare.py index 6fd2015fa2e..f8e008e7d38 100644 --- a/erpnext/healthcare/doctype/healthcare.py +++ b/erpnext/healthcare/doctype/healthcare.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return [] diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py index 5da5a0657c6..4550e7ab4c2 100644 --- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py +++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py @@ -3,13 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from erpnext.accounts.party import validate_party_accounts -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) +from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists -from frappe.desk.reportview import build_match_conditions, get_filters_cond + +from erpnext.accounts.party import validate_party_accounts + class HealthcarePractitioner(Document): def onload(self): diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py index bcee44430ac..8e0292e97c2 100644 --- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py +++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.py index de8201b1517..214bcd287aa 100644 --- a/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.py +++ b/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.py @@ -2,7 +2,9 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestHealthcarePractitioner(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/healthcare_schedule_time_slot/healthcare_schedule_time_slot.py b/erpnext/healthcare/doctype/healthcare_schedule_time_slot/healthcare_schedule_time_slot.py index e58ea53c2cd..721da24adc5 100644 --- a/erpnext/healthcare/doctype/healthcare_schedule_time_slot/healthcare_schedule_time_slot.py +++ b/erpnext/healthcare/doctype/healthcare_schedule_time_slot/healthcare_schedule_time_slot.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class HealthcareScheduleTimeSlot(Document): pass diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py index 989d4267897..550b9fbff27 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py @@ -4,11 +4,12 @@ from __future__ import unicode_literals -from frappe.utils.nestedset import NestedSet -from frappe.utils import cint, cstr +import json + import frappe from frappe import _ -import json +from frappe.utils import cint, cstr +from frappe.utils.nestedset import NestedSet class HealthcareServiceUnit(NestedSet): @@ -30,7 +31,7 @@ class HealthcareServiceUnit(NestedSet): self.validate_one_root() def set_service_unit_properties(self): - if self.is_group: + if cint(self.is_group): self.allow_appointments = False self.overlap_appointments = False self.inpatient_occupancy = False diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py index bced2fe1f63..84197e56c56 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestHealthcareServiceUnit(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py index a318e506003..181cb529fc2 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.model.rename_doc import rename_doc + class HealthcareServiceUnitType(Document): def validate(self): if self.allow_appointments and self.inpatient_occupancy: diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py index 0ac548b3ffd..7421ec3b89c 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'service_unit_type', diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py index 3ee3377b004..839e1d6a4db 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py @@ -2,9 +2,12 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + import frappe + class TestHealthcareServiceUnitType(unittest.TestCase): def test_item_creation(self): unit_type = get_unit_type() diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py index a16fceb74dd..9ab88817661 100644 --- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py +++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import json + import frappe from frappe import _ -from frappe.model.document import Document from frappe.core.doctype.sms_settings.sms_settings import send_sms -import json +from frappe.model.document import Document + class HealthcareSettings(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.py b/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.py index 1b620d5f5da..af2f2b4c4f5 100644 --- a/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.py +++ b/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestHealthcareSettings(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py index 3a299eda262..b28e37a9c31 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py +++ b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt, get_link_to_form, getdate, nowtime -from erpnext.stock.utils import get_latest_stock_qty +from frappe.utils import flt, get_link_to_form + from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account +from erpnext.stock.utils import get_latest_stock_qty + class InpatientMedicationEntry(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry_dashboard.py b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry_dashboard.py index a4bec45596f..ca9364d66a1 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry_dashboard.py +++ b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'against_imoe', diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry/test_inpatient_medication_entry.py b/erpnext/healthcare/doctype/inpatient_medication_entry/test_inpatient_medication_entry.py index 0c463ddc029..dec3b7e0ead 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_entry/test_inpatient_medication_entry.py +++ b/erpnext/healthcare/doctype/inpatient_medication_entry/test_inpatient_medication_entry.py @@ -3,14 +3,32 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import add_days, getdate, now_datetime -from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy -from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge -from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import create_ipmo, create_ipme -from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_drug_shortage_map, make_difference_stock_entry + from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account +from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import ( + get_drug_shortage_map, + make_difference_stock_entry, +) +from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import ( + create_ipme, + create_ipmo, +) +from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, +) +from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import ( + create_inpatient, + create_patient, + get_healthcare_service_unit, + mark_invoiced_inpatient_occupancy, +) + class TestInpatientMedicationEntry(unittest.TestCase): def setUp(self): diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry_detail/inpatient_medication_entry_detail.py b/erpnext/healthcare/doctype/inpatient_medication_entry_detail/inpatient_medication_entry_detail.py index 644898d9edc..91734312d4a 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_entry_detail/inpatient_medication_entry_detail.py +++ b/erpnext/healthcare/doctype/inpatient_medication_entry_detail/inpatient_medication_entry_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class InpatientMedicationEntryDetail(Document): pass diff --git a/erpnext/healthcare/doctype/inpatient_medication_order/inpatient_medication_order.py b/erpnext/healthcare/doctype/inpatient_medication_order/inpatient_medication_order.py index b379e98fe13..2e6d73208f7 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_order/inpatient_medication_order.py +++ b/erpnext/healthcare/doctype/inpatient_medication_order/inpatient_medication_order.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import cstr + from erpnext.healthcare.doctype.patient_encounter.patient_encounter import get_prescription_dates + class InpatientMedicationOrder(Document): def validate(self): self.validate_inpatient() diff --git a/erpnext/healthcare/doctype/inpatient_medication_order/test_inpatient_medication_order.py b/erpnext/healthcare/doctype/inpatient_medication_order/test_inpatient_medication_order.py index ec1a28034e3..14ea1205f41 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_order/test_inpatient_medication_order.py +++ b/erpnext/healthcare/doctype/inpatient_medication_order/test_inpatient_medication_order.py @@ -3,11 +3,23 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import add_days, getdate, now_datetime -from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy -from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge + +from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, +) +from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import ( + create_inpatient, + create_patient, + get_healthcare_service_unit, + mark_invoiced_inpatient_occupancy, +) + class TestInpatientMedicationOrder(unittest.TestCase): def setUp(self): diff --git a/erpnext/healthcare/doctype/inpatient_medication_order_entry/inpatient_medication_order_entry.py b/erpnext/healthcare/doctype/inpatient_medication_order_entry/inpatient_medication_order_entry.py index ebfe366346e..15800ad15f6 100644 --- a/erpnext/healthcare/doctype/inpatient_medication_order_entry/inpatient_medication_order_entry.py +++ b/erpnext/healthcare/doctype/inpatient_medication_order_entry/inpatient_medication_order_entry.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class InpatientMedicationOrderEntry(Document): pass diff --git a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.py b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.py index 52de25b4571..c8f3296d0db 100644 --- a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.py +++ b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class InpatientOccupancy(Document): pass diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py index 2cdfa04d5c0..9cede8a2f69 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json + +import json + +import frappe from frappe import _ -from frappe.utils import today, now_datetime, getdate, get_datetime, get_link_to_form -from frappe.model.document import Document from frappe.desk.reportview import get_match_cond +from frappe.model.document import Document +from frappe.utils import get_datetime, get_link_to_form, getdate, now_datetime, today + class InpatientRecord(Document): def after_insert(self): diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record_dashboard.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record_dashboard.py index 92cc6103f45..0f4adce4edf 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record_dashboard.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'inpatient_record', diff --git a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py index 9b5cd717a0c..a778890f4a2 100644 --- a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py @@ -3,14 +3,21 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import now_datetime, today from frappe.utils.make_random import get_random -from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge + +from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, +) from erpnext.healthcare.doctype.lab_test.test_lab_test import create_patient_encounter from erpnext.healthcare.utils import get_encounters_to_invoice + class TestInpatientRecord(unittest.TestCase): def test_admit_and_discharge(self): frappe.db.sql("""delete from `tabInpatient Record`""") diff --git a/erpnext/healthcare/doctype/lab_prescription/lab_prescription.py b/erpnext/healthcare/doctype/lab_prescription/lab_prescription.py index b788a0db7e7..a3f9aa24c48 100644 --- a/erpnext/healthcare/doctype/lab_prescription/lab_prescription.py +++ b/erpnext/healthcare/doctype/lab_prescription/lab_prescription.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class LabPrescription(Document): pass diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py index 74495a85910..7db497c24d7 100644 --- a/erpnext/healthcare/doctype/lab_test/lab_test.py +++ b/erpnext/healthcare/doctype/lab_test/lab_test.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import getdate, cstr, get_link_to_form +from frappe.utils import get_link_to_form, getdate + class LabTest(Document): def validate(self): @@ -48,7 +50,7 @@ class LabTest(Document): if item.result_value and item.secondary_uom and item.conversion_factor: try: item.secondary_uom_result = float(item.result_value) * float(item.conversion_factor) - except: + except Exception: item.secondary_uom_result = '' frappe.msgprint(_('Row #{0}: Result for Secondary UOM not calculated').format(item.idx), title = _('Warning')) diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.py b/erpnext/healthcare/doctype/lab_test/test_lab_test.py index c9f0029ed80..da10bd86bdf 100644 --- a/erpnext/healthcare/doctype/lab_test/test_lab_test.py +++ b/erpnext/healthcare/doctype/lab_test/test_lab_test.py @@ -2,13 +2,22 @@ # Copyright (c) 2015, ESS LLP and Contributors # See license.txt from __future__ import unicode_literals + import unittest + import frappe from frappe.utils import getdate, nowtime -from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient + +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import ( + get_income_account, + get_receivable_account, +) from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple -from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account -from erpnext.healthcare.doctype.patient_medical_record.test_patient_medical_record import create_lab_test_template as create_blood_test_template +from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient +from erpnext.healthcare.doctype.patient_medical_record.test_patient_medical_record import ( + create_lab_test_template as create_blood_test_template, +) + class TestLabTest(unittest.TestCase): def test_lab_test_item(self): diff --git a/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py index 1e2cef4e18b..2e3c4093c7c 100644 --- a/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py +++ b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class LabTestGroupTemplate(Document): pass diff --git a/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.py b/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.py index 4c66b7276b6..3a765fe2436 100644 --- a/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.py +++ b/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class LabTestSample(Document): pass diff --git a/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.py b/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.py index 2bc56bd3241..8896572d783 100644 --- a/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.py +++ b/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestLabTestSample(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py index 543dee27ebc..a75c533f947 100644 --- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py +++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py @@ -3,10 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json + +import json + +import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.rename_doc import rename_doc -from frappe import _ + class LabTestTemplate(Document): def after_insert(self): @@ -27,7 +31,7 @@ class LabTestTemplate(Document): item_price = self.item_price_exists() if not item_price: if self.lab_test_rate and self.lab_test_rate > 0.0: - price_list_name = frappe.db.get_value('Price List', {'selling': 1}) + price_list_name = frappe.db.get_value('Selling Settings', None, 'selling_price_list') or frappe.db.get_value('Price List', {'selling': 1}) make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate) else: frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.lab_test_rate) @@ -110,7 +114,7 @@ def create_item_from_template(doc): # Insert item price if doc.is_billable and doc.lab_test_rate != 0.0: - price_list_name = frappe.db.get_value('Price List', {'selling': 1}) + price_list_name = frappe.db.get_value('Selling Settings', None, 'selling_price_list') or frappe.db.get_value('Price List', {'selling': 1}) if doc.lab_test_rate: make_item_price(item.name, price_list_name, doc.lab_test_rate) else: diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template_dashboard.py b/erpnext/healthcare/doctype/lab_test_template/lab_test_template_dashboard.py index 94dfeea7a42..a4f9d4b714e 100644 --- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template_dashboard.py +++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'template', diff --git a/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.py b/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.py index 4c9f55a839e..8d8ac647500 100644 --- a/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.py +++ b/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.py @@ -2,6 +2,7 @@ # Copyright (c) 2015, ESS and Contributors # See license.txt from __future__ import unicode_literals + import unittest # test_records = frappe.get_test_records('Lab Test Template') diff --git a/erpnext/healthcare/doctype/lab_test_uom/lab_test_uom.py b/erpnext/healthcare/doctype/lab_test_uom/lab_test_uom.py index 7ce8d2d1c81..ce11c0ffce3 100644 --- a/erpnext/healthcare/doctype/lab_test_uom/lab_test_uom.py +++ b/erpnext/healthcare/doctype/lab_test_uom/lab_test_uom.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class LabTestUOM(Document): pass diff --git a/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.py b/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.py index 0b3f516497d..9fe2de51a6d 100644 --- a/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.py +++ b/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.py @@ -2,6 +2,7 @@ # Copyright (c) 2015, ESS and Contributors # See license.txt from __future__ import unicode_literals + import unittest # test_records = frappe.get_test_records('Lab Test UOM') diff --git a/erpnext/healthcare/doctype/medical_code/medical_code.py b/erpnext/healthcare/doctype/medical_code/medical_code.py index 0deaac38ca3..4ed3d31e907 100644 --- a/erpnext/healthcare/doctype/medical_code/medical_code.py +++ b/erpnext/healthcare/doctype/medical_code/medical_code.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class MedicalCode(Document): def autoname(self): self.name = self.medical_code_standard+" "+self.code diff --git a/erpnext/healthcare/doctype/medical_code/test_medical_code.py b/erpnext/healthcare/doctype/medical_code/test_medical_code.py index b1e04027907..7584b050a65 100644 --- a/erpnext/healthcare/doctype/medical_code/test_medical_code.py +++ b/erpnext/healthcare/doctype/medical_code/test_medical_code.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestMedicalCode(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/medical_code_standard/medical_code_standard.py b/erpnext/healthcare/doctype/medical_code_standard/medical_code_standard.py index 7b2731c1def..be0ea8922ed 100644 --- a/erpnext/healthcare/doctype/medical_code_standard/medical_code_standard.py +++ b/erpnext/healthcare/doctype/medical_code_standard/medical_code_standard.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class MedicalCodeStandard(Document): pass diff --git a/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.py b/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.py index fde095d8098..3b046e360f3 100644 --- a/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.py +++ b/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestMedicalCodeStandard(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/medical_department/medical_department.py b/erpnext/healthcare/doctype/medical_department/medical_department.py index 0f2d4fc5f91..7be5a1ade34 100644 --- a/erpnext/healthcare/doctype/medical_department/medical_department.py +++ b/erpnext/healthcare/doctype/medical_department/medical_department.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class MedicalDepartment(Document): pass diff --git a/erpnext/healthcare/doctype/medical_department/test_medical_department.py b/erpnext/healthcare/doctype/medical_department/test_medical_department.py index 543750a7e7d..6435a23e928 100644 --- a/erpnext/healthcare/doctype/medical_department/test_medical_department.py +++ b/erpnext/healthcare/doctype/medical_department/test_medical_department.py @@ -2,6 +2,7 @@ # Copyright (c) 2015, ESS LLP and Contributors # See license.txt from __future__ import unicode_literals + import unittest # test_records = frappe.get_test_records('Medical Department') diff --git a/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py index 63abf0297e7..e72f7269fc3 100644 --- a/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py +++ b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class NormalTestResult(Document): pass diff --git a/erpnext/healthcare/doctype/normal_test_template/normal_test_template.py b/erpnext/healthcare/doctype/normal_test_template/normal_test_template.py index bc2c9914846..9df48559cde 100644 --- a/erpnext/healthcare/doctype/normal_test_template/normal_test_template.py +++ b/erpnext/healthcare/doctype/normal_test_template/normal_test_template.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class NormalTestTemplate(Document): pass diff --git a/erpnext/healthcare/doctype/organism/organism.py b/erpnext/healthcare/doctype/organism/organism.py index 1ead762c2fe..dfb9c0dd0d4 100644 --- a/erpnext/healthcare/doctype/organism/organism.py +++ b/erpnext/healthcare/doctype/organism/organism.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Organism(Document): pass diff --git a/erpnext/healthcare/doctype/organism/test_organism.py b/erpnext/healthcare/doctype/organism/test_organism.py index ecb96650e11..9d7ea0ba33d 100644 --- a/erpnext/healthcare/doctype/organism/test_organism.py +++ b/erpnext/healthcare/doctype/organism/test_organism.py @@ -2,7 +2,9 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestOrganism(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py index 019a55b396c..6bb8e8f4c07 100644 --- a/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py +++ b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class OrganismTestItem(Document): pass diff --git a/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py index 02393c27004..3428403e3c0 100644 --- a/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py +++ b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class OrganismTestResult(Document): pass diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py index 95cce73f231..961a8be3691 100644 --- a/erpnext/healthcare/doctype/patient/patient.py +++ b/erpnext/healthcare/doctype/patient/patient.py @@ -3,18 +3,25 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import dateutil import frappe from frappe import _ -from frappe.model.document import Document -from frappe.utils import cint, cstr, getdate -import dateutil from frappe.contacts.address_and_contact import load_address_and_contact from frappe.contacts.doctype.contact.contact import get_default_contact +from frappe.model.document import Document from frappe.model.naming import set_name_by_naming_series +from frappe.utils import cint, cstr, getdate from frappe.utils.nestedset import get_root_of + from erpnext import get_default_currency -from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account, send_registration_sms from erpnext.accounts.party import get_dashboard_info +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import ( + get_income_account, + get_receivable_account, + send_registration_sms, +) + class Patient(Document): def onload(self): diff --git a/erpnext/healthcare/doctype/patient/patient_dashboard.py b/erpnext/healthcare/doctype/patient/patient_dashboard.py index 7f7cfa8e5b9..a388b74f61a 100644 --- a/erpnext/healthcare/doctype/patient/patient_dashboard.py +++ b/erpnext/healthcare/doctype/patient/patient_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/healthcare/doctype/patient/test_patient.py b/erpnext/healthcare/doctype/patient/test_patient.py index 9274b6f5e85..4b8c7326468 100644 --- a/erpnext/healthcare/doctype/patient/test_patient.py +++ b/erpnext/healthcare/doctype/patient/test_patient.py @@ -4,9 +4,12 @@ from __future__ import unicode_literals import unittest + import frappe + from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient + class TestPatient(unittest.TestCase): def test_customer_created(self): frappe.db.sql("""delete from `tabPatient`""") diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py index 36047c48381..dcbcda09d81 100755 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py @@ -3,17 +3,28 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document -import json -from frappe.utils import getdate, get_time, flt -from frappe.model.mapper import get_mapped_doc -from frappe import _ + import datetime +import json + +import frappe +from frappe import _ from frappe.core.doctype.sms_settings.sms_settings import send_sms +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, get_link_to_form, get_time, getdate + +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import ( + get_income_account, + get_receivable_account, +) +from erpnext.healthcare.utils import ( + check_fee_validity, + get_service_item_and_practitioner_charge, + manage_fee_validity, +) from erpnext.hr.doctype.employee.employee import is_holiday -from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account -from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_practitioner_charge, manage_fee_validity + class MaximumCapacityError(frappe.ValidationError): pass @@ -100,7 +111,9 @@ class PatientAppointment(Document): def validate_service_unit(self): if self.inpatient_record and self.service_unit: - from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit + from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import ( + get_current_healthcare_service_unit, + ) is_inpatient_occupancy_unit = frappe.db.get_value('Healthcare Service Unit', self.service_unit, 'inpatient_occupancy') @@ -333,17 +346,13 @@ def check_employee_wise_availability(date, practitioner_doc): def get_available_slots(practitioner_doc, date): - available_slots = [] - slot_details = [] + available_slots = slot_details = [] weekday = date.strftime('%A') practitioner = practitioner_doc.name for schedule_entry in practitioner_doc.practitioner_schedules: - if schedule_entry.schedule: - practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule_entry.schedule) - else: - frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner').format( - frappe.bold(practitioner)), title=_('Practitioner Schedule Not Found')) + validate_practitioner_schedules(schedule_entry, practitioner) + practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule_entry.schedule) if practitioner_schedule: available_slots = [] @@ -386,6 +395,19 @@ def get_available_slots(practitioner_doc, date): return slot_details +def validate_practitioner_schedules(schedule_entry, practitioner): + if schedule_entry.schedule: + if not schedule_entry.service_unit: + frappe.throw(_('Practitioner {0} does not have a Service Unit set against the Practitioner Schedule {1}.').format( + get_link_to_form('Healthcare Practitioner', practitioner), frappe.bold(schedule_entry.schedule)), + title=_('Service Unit Not Found')) + + else: + frappe.throw(_('Practitioner {0} does not have a Practitioner Schedule assigned.').format( + get_link_to_form('Healthcare Practitioner', practitioner)), + title=_('Practitioner Schedule Not Found')) + + @frappe.whitelist() def update_status(appointment_id, status): frappe.db.set_value('Patient Appointment', appointment_id, 'status', status) diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_dashboard.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_dashboard.py index 085c4f6cbf8..43c63c96e6d 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_dashboard.py +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'appointment', diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py index d0db3226326..d9c2fbfb3a7 100644 --- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py @@ -2,12 +2,19 @@ # Copyright (c) 2015, ESS LLP and Contributors # See license.txt from __future__ import unicode_literals + import unittest + import frappe -from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter, check_payment_fields_reqd, check_is_new_patient -from frappe.utils import nowdate, add_days, now_datetime -from frappe.utils.make_random import get_random +from frappe.utils import add_days, now_datetime, nowdate + from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.healthcare.doctype.patient_appointment.patient_appointment import ( + check_is_new_patient, + check_payment_fields_reqd, + make_encounter, + update_status, +) class TestPatientAppointment(unittest.TestCase): @@ -131,9 +138,16 @@ class TestPatientAppointment(unittest.TestCase): self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'status'), 'Cancelled') def test_appointment_booking_for_admission_service_unit(self): - from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge - from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \ - create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy + from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, + ) + from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import ( + create_inpatient, + get_healthcare_service_unit, + mark_invoiced_inpatient_occupancy, + ) frappe.db.sql("""delete from `tabInpatient Record`""") patient, practitioner = create_healthcare_docs() @@ -157,9 +171,16 @@ class TestPatientAppointment(unittest.TestCase): discharge_patient(ip_record1, now_datetime()) def test_invalid_healthcare_service_unit_validation(self): - from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge - from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \ - create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy + from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, + ) + from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import ( + create_inpatient, + get_healthcare_service_unit, + mark_invoiced_inpatient_occupancy, + ) frappe.db.sql("""delete from `tabInpatient Record`""") patient, practitioner = create_healthcare_docs() @@ -238,7 +259,10 @@ class TestPatientAppointment(unittest.TestCase): self.assertRaises(OverlapError, appointment.save) def test_service_unit_capacity(self): - from erpnext.healthcare.doctype.patient_appointment.patient_appointment import MaximumCapacityError, OverlapError + from erpnext.healthcare.doctype.patient_appointment.patient_appointment import ( + MaximumCapacityError, + OverlapError, + ) practitioner = create_practitioner() capacity = 3 overlap_service_unit_type = create_service_unit_type(id=10, allow_appointments=1, overlap_appointments=1) diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py index 7bad20dffdc..90cb30035d4 100644 --- a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py +++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc + class PatientAssessment(Document): def validate(self): self.set_total_score() diff --git a/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py index 3fda8550f6c..0ffbd1f5049 100644 --- a/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py +++ b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestPatientAssessment(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py index 0519599ac0c..4da679b8892 100644 --- a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py +++ b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientAssessmentDetail(Document): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py index b8e00747171..783c5378481 100644 --- a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py +++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientAssessmentParameter(Document): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py index e722f9905ec..f06fffb1ef4 100644 --- a/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py +++ b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestPatientAssessmentParameter(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py index 40da7630132..4686e9e2617 100644 --- a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py +++ b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientAssessmentSheet(Document): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py index 083cab5d017..e0d8fca37f7 100644 --- a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py +++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientAssessmentTemplate(Document): pass diff --git a/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py index 86dbd5438cd..7d639cb6af4 100644 --- a/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py +++ b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestPatientAssessmentTemplate(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py index 7a745ae468e..2daa6c145c8 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py @@ -3,12 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cstr, getdate, add_days -from frappe import _ from frappe.model.mapper import get_mapped_doc +from frappe.utils import add_days, getdate class PatientEncounter(Document): diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_dashboard.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_dashboard.py index 39e54f5b35c..3b64d988715 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_dashboard.py +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'encounter', diff --git a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py index 96976821a71..fa643a31d8e 100644 --- a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py +++ b/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py @@ -2,9 +2,11 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest import frappe + from erpnext.healthcare.doctype.patient_encounter.patient_encounter import PatientEncounter diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py index 34b0cf8a580..e4d2069a50e 100644 --- a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py +++ b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientEncounterDiagnosis(Document): pass diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py index bdb7bb218eb..47f2a2be7e9 100644 --- a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py +++ b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientEncounterSymptom(Document): pass diff --git a/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py index f0a1f929f45..34e15dc46a2 100644 --- a/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py +++ b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientHistoryCustomDocumentType(Document): pass diff --git a/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py index 9e0d3c3e278..b763591d3ac 100644 --- a/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py +++ b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ -from frappe.utils import cstr, cint from frappe.model.document import Document +from frappe.utils import cint, cstr + from erpnext.healthcare.page.patient_history.patient_history import get_patient_history_doctypes + class PatientHistorySettings(Document): def validate(self): self.validate_submittable_doctypes() diff --git a/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py b/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py index 9169ea642b9..c37a2adc368 100644 --- a/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py +++ b/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py @@ -3,12 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest import json +import unittest + +import frappe from frappe.utils import getdate, strip_html + from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient + class TestPatientHistorySettings(unittest.TestCase): def setUp(self): dt = create_custom_doctype() diff --git a/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py index 2d94911855a..b7dd09bc10c 100644 --- a/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py +++ b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PatientHistoryStandardDocumentType(Document): pass diff --git a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.py index 35e42bd6bd5..ac2cffa3e89 100644 --- a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.py +++ b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class PatientMedicalRecord(Document): def after_insert(self): if self.reference_doctype == "Patient Medical Record" : diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py index 5b7d8d62c83..099146c7ee7 100644 --- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py +++ b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py @@ -2,11 +2,20 @@ # Copyright (c) 2015, ESS LLP and Contributors # See license.txt from __future__ import unicode_literals + import unittest + import frappe from frappe.utils import nowdate -from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_encounter, create_healthcare_docs, create_appointment, create_medical_department + from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import ( + create_appointment, + create_encounter, + create_healthcare_docs, + create_medical_department, +) + class TestPatientMedicalRecord(unittest.TestCase): def setUp(self): diff --git a/erpnext/healthcare/doctype/patient_relation/patient_relation.py b/erpnext/healthcare/doctype/patient_relation/patient_relation.py index 150b96200d0..17bc20940d6 100644 --- a/erpnext/healthcare/doctype/patient_relation/patient_relation.py +++ b/erpnext/healthcare/doctype/patient_relation/patient_relation.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class PatientRelation(Document): pass diff --git a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.py b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.py index 8bd0937948b..7fa31e5fb67 100644 --- a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.py +++ b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class PractitionerSchedule(Document): def autoname(self): self.name = self.schedule_name diff --git a/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.py b/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.py index 52638cb618e..1ecaa47248a 100644 --- a/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.py +++ b/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.py @@ -2,7 +2,9 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestPractitionerSchedule(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/practitioner_service_unit_schedule/practitioner_service_unit_schedule.py b/erpnext/healthcare/doctype/practitioner_service_unit_schedule/practitioner_service_unit_schedule.py index c18a4406cab..4eba1fbf6b4 100644 --- a/erpnext/healthcare/doctype/practitioner_service_unit_schedule/practitioner_service_unit_schedule.py +++ b/erpnext/healthcare/doctype/practitioner_service_unit_schedule/practitioner_service_unit_schedule.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class PractitionerServiceUnitSchedule(Document): pass diff --git a/erpnext/healthcare/doctype/prescription_dosage/prescription_dosage.py b/erpnext/healthcare/doctype/prescription_dosage/prescription_dosage.py index dea263dca09..19f9b70bb61 100644 --- a/erpnext/healthcare/doctype/prescription_dosage/prescription_dosage.py +++ b/erpnext/healthcare/doctype/prescription_dosage/prescription_dosage.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class PrescriptionDosage(Document): pass diff --git a/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.py b/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.py index e61a4188966..cabfd35e23d 100644 --- a/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.py +++ b/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestPrescriptionDosage(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/prescription_duration/prescription_duration.py b/erpnext/healthcare/doctype/prescription_duration/prescription_duration.py index 96ddf8dafe8..988276da748 100644 --- a/erpnext/healthcare/doctype/prescription_duration/prescription_duration.py +++ b/erpnext/healthcare/doctype/prescription_duration/prescription_duration.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document from frappe.utils import cstr + class PrescriptionDuration(Document): def autoname(self): self.name = " ".join(filter(None, diff --git a/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.py b/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.py index fe5524c5aa7..197bb3e7fb9 100644 --- a/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.py +++ b/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.py @@ -2,7 +2,9 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestPrescriptionDuration(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.py b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.py index 62ea9f1a400..f4d29fa6a30 100644 --- a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.py +++ b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class ProcedurePrescription(Document): pass diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.py b/erpnext/healthcare/doctype/sample_collection/sample_collection.py index 461f8095076..7de6ac08ca1 100644 --- a/erpnext/healthcare/doctype/sample_collection/sample_collection.py +++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import flt -from frappe import _ + class SampleCollection(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/sensitivity/sensitivity.py b/erpnext/healthcare/doctype/sensitivity/sensitivity.py index bf7c36b9d28..f61781d3f86 100644 --- a/erpnext/healthcare/doctype/sensitivity/sensitivity.py +++ b/erpnext/healthcare/doctype/sensitivity/sensitivity.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Sensitivity(Document): pass diff --git a/erpnext/healthcare/doctype/sensitivity/test_sensitivity.py b/erpnext/healthcare/doctype/sensitivity/test_sensitivity.py index 1616d2decbb..c772c72faf0 100644 --- a/erpnext/healthcare/doctype/sensitivity/test_sensitivity.py +++ b/erpnext/healthcare/doctype/sensitivity/test_sensitivity.py @@ -2,6 +2,7 @@ # Copyright (c) 2015, ESS and Contributors # See license.txt from __future__ import unicode_literals + import unittest # test_records = frappe.get_test_records('Sensitivity') diff --git a/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py index 64f1e6ca255..53f7acc4af0 100644 --- a/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py +++ b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SensitivityTestResult(Document): pass diff --git a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py index 983fba9f5ff..4f96f6a7066 100644 --- a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py +++ b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py @@ -3,13 +3,23 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import getdate, flt, nowdate + +import frappe +from frappe.utils import flt, getdate, nowdate + +from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import ( + create_appointment, + create_healthcare_docs, + create_medical_department, + create_patient, +) +from erpnext.healthcare.doctype.therapy_plan.therapy_plan import ( + make_sales_invoice, + make_therapy_session, +) from erpnext.healthcare.doctype.therapy_type.test_therapy_type import create_therapy_type -from erpnext.healthcare.doctype.therapy_plan.therapy_plan import make_therapy_session, make_sales_invoice -from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import \ - create_healthcare_docs, create_patient, create_appointment, create_medical_department + class TestTherapyPlan(unittest.TestCase): def test_creation_on_encounter_submission(self): @@ -31,7 +41,7 @@ class TestTherapyPlan(unittest.TestCase): self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed') patient, practitioner = create_healthcare_docs() - appointment = create_appointment(patient, practitioner, nowdate()) + appointment = create_appointment(patient, practitioner, nowdate()) session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company', appointment.name) session = frappe.get_doc(session) diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py index e2096604344..6d63f391895 100644 --- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py +++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.utils import flt, today + class TherapyPlan(Document): def validate(self): self.set_totals() diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py index 6526acda153..25c8df1d6b7 100644 --- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py +++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'therapy_plan', diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py index 44211f32e3a..1842fc2197b 100644 --- a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py +++ b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TherapyPlanDetail(Document): pass diff --git a/erpnext/healthcare/doctype/therapy_plan_template/test_therapy_plan_template.py b/erpnext/healthcare/doctype/therapy_plan_template/test_therapy_plan_template.py index 33ee29db7d7..cd3d5686bc0 100644 --- a/erpnext/healthcare/doctype/therapy_plan_template/test_therapy_plan_template.py +++ b/erpnext/healthcare/doctype/therapy_plan_template/test_therapy_plan_template.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestTherapyPlanTemplate(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template.py b/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template.py index 635d4beb8df..f5512be207f 100644 --- a/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template.py +++ b/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.utils import cint, flt + from erpnext.healthcare.doctype.therapy_type.therapy_type import make_item_price + class TherapyPlanTemplate(Document): def after_insert(self): self.create_item_from_template() diff --git a/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template_dashboard.py b/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template_dashboard.py index c748fbfcb7c..def5c482d15 100644 --- a/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template_dashboard.py +++ b/erpnext/healthcare/doctype/therapy_plan_template/therapy_plan_template_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'therapy_plan_template', diff --git a/erpnext/healthcare/doctype/therapy_plan_template_detail/therapy_plan_template_detail.py b/erpnext/healthcare/doctype/therapy_plan_template_detail/therapy_plan_template_detail.py index 7b979fe9fc8..104c1bf28bd 100644 --- a/erpnext/healthcare/doctype/therapy_plan_template_detail/therapy_plan_template_detail.py +++ b/erpnext/healthcare/doctype/therapy_plan_template_detail/therapy_plan_template_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TherapyPlanTemplateDetail(Document): pass diff --git a/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py index 75bb8df1963..e4afacf3f0a 100644 --- a/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py +++ b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestTherapySession(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py index 51f267f9496..915e6e42f4c 100644 --- a/erpnext/healthcare/doctype/therapy_session/therapy_session.py +++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py @@ -3,14 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import datetime -from frappe.model.document import Document -from frappe.utils import get_time, flt -from frappe.model.mapper import get_mapped_doc + +import frappe from frappe import _ -from frappe.utils import cstr, getdate, get_link_to_form -from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, get_link_to_form, get_time, getdate + +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import ( + get_income_account, + get_receivable_account, +) + class TherapySession(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py index 9de7e293238..b8a37820ba0 100644 --- a/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py +++ b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'therapy_session', diff --git a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py index 80fc83fd6ce..23d542236b8 100644 --- a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py +++ b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestTherapyType(unittest.TestCase): def test_therapy_type_item(self): therapy_type = create_therapy_type() diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.py b/erpnext/healthcare/doctype/therapy_type/therapy_type.py index 3f6a36a9686..3517ef2c5ad 100644 --- a/erpnext/healthcare/doctype/therapy_type/therapy_type.py +++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ -from frappe.utils import cint from frappe.model.document import Document from frappe.model.rename_doc import rename_doc +from frappe.utils import cint + class TherapyType(Document): def validate(self): diff --git a/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py b/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py index 21ede7129f1..b8a1dd77869 100644 --- a/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py +++ b/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py @@ -4,5 +4,6 @@ # import frappe import unittest + class TestTreatmentPlanTemplate(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py index a92e2668fe8..dbe0e9ae5f4 100644 --- a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py +++ b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py @@ -5,6 +5,7 @@ import frappe from frappe import _ from frappe.model.document import Document + class TreatmentPlanTemplate(Document): def validate(self): self.validate_age() diff --git a/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py index 5f58b06af60..8b8d89f07f3 100644 --- a/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py +++ b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class TreatmentPlanTemplateItem(Document): pass diff --git a/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py index 6d34568e15c..c2d08bcc1ab 100644 --- a/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py +++ b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class TreatmentPlanTemplatePractitioner(Document): pass diff --git a/erpnext/healthcare/doctype/vital_signs/test_vital_signs.py b/erpnext/healthcare/doctype/vital_signs/test_vital_signs.py index 5d3e00740f9..22b52fb4822 100644 --- a/erpnext/healthcare/doctype/vital_signs/test_vital_signs.py +++ b/erpnext/healthcare/doctype/vital_signs/test_vital_signs.py @@ -2,6 +2,7 @@ # Copyright (c) 2015, ESS LLP and Contributors # See license.txt from __future__ import unicode_literals + import unittest # test_records = frappe.get_test_records('Vital Signs') diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py index 4bb3940ae0f..29dbeb470dd 100644 --- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py +++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py @@ -3,10 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document -from frappe.utils import cstr from frappe import _ +from frappe.model.document import Document + class VitalSigns(Document): def validate(self): diff --git a/erpnext/healthcare/page/patient_history/patient_history.py b/erpnext/healthcare/page/patient_history/patient_history.py index 4cdfd64a697..77d8846f373 100644 --- a/erpnext/healthcare/page/patient_history/patient_history.py +++ b/erpnext/healthcare/page/patient_history/patient_history.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe.utils import cint -from erpnext.healthcare.utils import render_docs_as_html + @frappe.whitelist() def get_feed(name, document_types=None, date_range=None, start=0, page_length=20): diff --git a/erpnext/healthcare/page/patient_progress/patient_progress.py b/erpnext/healthcare/page/patient_progress/patient_progress.py index 46bfb3db5d4..c17f10574a9 100644 --- a/erpnext/healthcare/page/patient_progress/patient_progress.py +++ b/erpnext/healthcare/page/patient_progress/patient_progress.py @@ -1,8 +1,10 @@ -import frappe -from datetime import datetime -from frappe import _ -from frappe.utils import getdate, get_timespan_date_range import json +from datetime import datetime + +import frappe +from frappe import _ +from frappe.utils import get_timespan_date_range, getdate + @frappe.whitelist() def get_therapy_sessions_count(patient): diff --git a/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py index 28b60bdcc92..2e809fb66b0 100644 --- a/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py +++ b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py @@ -2,8 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit + +from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import ( + get_current_healthcare_service_unit, +) + def execute(filters=None): columns = get_columns() diff --git a/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py b/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py index 0a538fdff0d..7c4b326c8e5 100644 --- a/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py +++ b/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py @@ -2,14 +2,32 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest -import frappe + import datetime +import unittest + +import frappe from frappe.utils import getdate, now_datetime -from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy -from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge -from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import create_ipmo, create_ipme -from erpnext.healthcare.report.inpatient_medication_orders.inpatient_medication_orders import execute + +from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import ( + create_ipme, + create_ipmo, +) +from erpnext.healthcare.doctype.inpatient_record.inpatient_record import ( + admit_patient, + discharge_patient, + schedule_discharge, +) +from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import ( + create_inpatient, + create_patient, + get_healthcare_service_unit, + mark_invoiced_inpatient_occupancy, +) +from erpnext.healthcare.report.inpatient_medication_orders.inpatient_medication_orders import ( + execute, +) + class TestInpatientMedicationOrders(unittest.TestCase): @classmethod diff --git a/erpnext/healthcare/report/lab_test_report/lab_test_report.py b/erpnext/healthcare/report/lab_test_report/lab_test_report.py index ba4ca4172dc..e2a53bb1e46 100644 --- a/erpnext/healthcare/report/lab_test_report/lab_test_report.py +++ b/erpnext/healthcare/report/lab_test_report/lab_test_report.py @@ -2,8 +2,10 @@ # License: See license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _, msgprint + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py index 9a4840acfea..1afb5da1fb4 100644 --- a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py +++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import getdate, flt, add_to_date, add_days -from frappe import _ , scrub +from frappe import _, scrub +from frappe.utils import add_days, add_to_date, flt, getdate from six import iteritems + from erpnext.accounts.utils import get_fiscal_year + def execute(filters=None): return Analytics(filters).run() @@ -26,7 +29,7 @@ class Analytics(object): return self.columns, self.data, None, self.chart def get_period_date_ranges(self): - from dateutil.relativedelta import relativedelta, MO + from dateutil.relativedelta import MO, relativedelta from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date) increment = { diff --git a/erpnext/healthcare/setup.py b/erpnext/healthcare/setup.py index 891272ddf81..167f24399cd 100644 --- a/erpnext/healthcare/setup.py +++ b/erpnext/healthcare/setup.py @@ -1,9 +1,11 @@ from __future__ import unicode_literals -import frappe +import frappe from frappe import _ + from erpnext.setup.utils import insert_record + def setup_healthcare(): if frappe.db.exists('Medical Department', 'Cardiology'): # already setup diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py index 7c80bdb73ce..cae3008ca82 100644 --- a/erpnext/healthcare/utils.py +++ b/erpnext/healthcare/utils.py @@ -3,16 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals -import math -import frappe + import json +import math + +import frappe from frappe import _ +from frappe.utils import cstr, rounded, time_diff_in_hours from frappe.utils.formatters import format_value -from frappe.utils import time_diff_in_hours, rounded, cstr -from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account + from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple + @frappe.whitelist() def get_healthcare_services_to_invoice(patient, company): patient = frappe.get_doc('Patient', patient) @@ -339,7 +343,9 @@ def get_service_item_and_practitioner_charge(doc): def get_appointment_type_service_item(appointment_type, department, is_inpatient): - from erpnext.healthcare.doctype.appointment_type.appointment_type import get_service_item_based_on_department + from erpnext.healthcare.doctype.appointment_type.appointment_type import ( + get_service_item_based_on_department, + ) item_list = get_service_item_based_on_department(appointment_type, department) service_item = None diff --git a/erpnext/healthcare/web_form/lab_test/lab_test.py b/erpnext/healthcare/web_form/lab_test/lab_test.py index 5a8c8a421cd..ec08985b191 100644 --- a/erpnext/healthcare/web_form/lab_test/lab_test.py +++ b/erpnext/healthcare/web_form/lab_test/lab_test.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe + def get_context(context): context.read_only = 1 diff --git a/erpnext/healthcare/web_form/patient_appointments/patient_appointments.py b/erpnext/healthcare/web_form/patient_appointments/patient_appointments.py index 09bcb42b579..80c12fd2144 100644 --- a/erpnext/healthcare/web_form/patient_appointments/patient_appointments.py +++ b/erpnext/healthcare/web_form/patient_appointments/patient_appointments.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe + def get_context(context): context.read_only = 1 diff --git a/erpnext/healthcare/web_form/patient_registration/patient_registration.py b/erpnext/healthcare/web_form/patient_registration/patient_registration.py index 1bc4d1874c8..f57de916dd1 100644 --- a/erpnext/healthcare/web_form/patient_registration/patient_registration.py +++ b/erpnext/healthcare/web_form/patient_registration/patient_registration.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_context(context): # do your magic here pass diff --git a/erpnext/healthcare/web_form/prescription/prescription.py b/erpnext/healthcare/web_form/prescription/prescription.py index efdeaa906ae..f6f273ad580 100644 --- a/erpnext/healthcare/web_form/prescription/prescription.py +++ b/erpnext/healthcare/web_form/prescription/prescription.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe + def get_context(context): context.read_only = 1 diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 2385b7cbade..7790061ce06 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from frappe import _ app_name = "erpnext" @@ -51,15 +52,15 @@ additional_print_settings = "erpnext.controllers.print_settings.get_print_settin on_session_creation = [ "erpnext.portal.utils.create_customer_or_supplier", - "erpnext.shopping_cart.utils.set_cart_count" + "erpnext.e_commerce.shopping_cart.utils.set_cart_count" ] -on_logout = "erpnext.shopping_cart.utils.clear_cart_count" +on_logout = "erpnext.e_commerce.shopping_cart.utils.clear_cart_count" treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group', 'Department'] # website -update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"] -my_account_context = "erpnext.shopping_cart.utils.update_my_account_context" +update_website_context = ["erpnext.e_commerce.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"] +my_account_context = "erpnext.e_commerce.shopping_cart.utils.update_my_account_context" calendars = ["Task", "Work Order", "Leave Application", "Sales Order", "Holiday List", "Course Schedule"] @@ -75,7 +76,7 @@ domains = { 'Services': 'erpnext.domains.services', } -website_generators = ["Item Group", "Item", "BOM", "Sales Partner", +website_generators = ["Item Group", "Website Item", "BOM", "Sales Partner", "Job Opening", "Student Admission"] website_context = { @@ -243,11 +244,13 @@ doc_events = { "on_update": ["erpnext.hr.doctype.employee.employee.update_user_permissions", "erpnext.portal.utils.set_default_role"] }, - "Sales Taxes and Charges Template": { - "on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings" + "Communication": { + "on_update": [ + "erpnext.support.doctype.issue.issue.set_first_response_time" + ] }, - "Website Settings": { - "validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products" + "Sales Taxes and Charges Template": { + "on_update": "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.validate_cart_settings" }, "Tax Category": { "validate": "erpnext.regional.india.utils.validate_tax_category" @@ -278,6 +281,7 @@ doc_events = { ] }, "Payment Entry": { + "validate": "erpnext.regional.india.utils.update_place_of_supply", "on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status", "erpnext.accounts.doctype.dunning.dunning.resolve_dunning"], "on_trash": "erpnext.regional.check_deletion_permission" }, @@ -308,6 +312,9 @@ doc_events = { }, "Company": { "on_trash": "erpnext.regional.india.utils.delete_gst_settings_for_company" + }, + "Integration Request": { + "validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment" } } diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.py b/erpnext/hotels/doctype/hotel_room/hotel_room.py index 6a2fc02574f..93a62c98e79 100644 --- a/erpnext/hotels/doctype/hotel_room/hotel_room.py +++ b/erpnext/hotels/doctype/hotel_room/hotel_room.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class HotelRoom(Document): def validate(self): if not self.capacity: diff --git a/erpnext/hotels/doctype/hotel_room/test_hotel_room.py b/erpnext/hotels/doctype/hotel_room/test_hotel_room.py index e307b5ac37a..4fedbd42a92 100644 --- a/erpnext/hotels/doctype/hotel_room/test_hotel_room.py +++ b/erpnext/hotels/doctype/hotel_room/test_hotel_room.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + test_dependencies = ["Hotel Room Package"] test_records = [ dict(doctype="Hotel Room", name="1001", diff --git a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py index 69da007fc6b..982b3ef911d 100644 --- a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py +++ b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomAmenity(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py index 8a62eea8fa1..1864081842d 100644 --- a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py +++ b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class HotelRoomPackage(Document): def validate(self): if not self.item: diff --git a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py index ebf7f2b7e9f..fe5d79dcc32 100644 --- a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py +++ b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + test_records = [ dict(doctype='Item', item_code='Breakfast', item_group='Products', is_stock_item=0), diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py index 8eee0f24c5c..5797fef30db 100644 --- a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py +++ b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomPricing(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py index b73fd44cd5e..72030c69397 100644 --- a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py +++ b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + test_dependencies = ["Hotel Room Package"] test_records = [ dict(doctype="Hotel Room Pricing", enabled=1, diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py index 6bf01bf941b..4a344df8485 100644 --- a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py +++ b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomPricingItem(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py index 9ae9fcfaf83..f594ac709ec 100644 --- a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py +++ b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomPricingPackage(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py index fec1c86ad02..ea258ccb75d 100644 --- a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py +++ b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestHotelRoomPricingPackage(unittest.TestCase): pass diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py index a8ebe8610ec..4944862284a 100644 --- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py +++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py @@ -3,10 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe.model.document import Document + +import json + +import frappe from frappe import _ -from frappe.utils import date_diff, add_days, flt +from frappe.model.document import Document +from frappe.utils import add_days, date_diff, flt + class HotelRoomUnavailableError(frappe.ValidationError): pass class HotelRoomPricingNotSetError(frappe.ValidationError): pass diff --git a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py index d4979968e61..e03005cf042 100644 --- a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py +++ b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py @@ -3,9 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import HotelRoomPricingNotSetError, HotelRoomUnavailableError + +import frappe + +from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import ( + HotelRoomPricingNotSetError, + HotelRoomUnavailableError, +) + test_dependencies = ["Hotel Room Package", "Hotel Room Pricing", "Hotel Room"] class TestHotelRoomReservation(unittest.TestCase): diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py index 3406faea0e6..0cf854722e1 100644 --- a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py +++ b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomReservationItem(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py index 1fc1303f393..610cf181c1d 100644 --- a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py +++ b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelRoomType(Document): pass diff --git a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py index 3b243e95669..6dba7b7407b 100644 --- a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py +++ b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestHotelRoomType(unittest.TestCase): pass diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/hotel_settings.py index d78bca149df..f8f8fe964da 100644 --- a/erpnext/hotels/doctype/hotel_settings/hotel_settings.py +++ b/erpnext/hotels/doctype/hotel_settings/hotel_settings.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HotelSettings(Document): pass diff --git a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py index a081acc0e08..5cf58b994e1 100644 --- a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py +++ b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestHotelSettings(unittest.TestCase): pass diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py index 259edb9c06d..f02baebdf6f 100644 --- a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py +++ b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py @@ -2,12 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import add_days, date_diff from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import get_rooms_booked + def execute(filters=None): columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/hr/doctype/appointment_letter/appointment_letter.py b/erpnext/hr/doctype/appointment_letter/appointment_letter.py index 85b82c50145..b9a8ec63017 100644 --- a/erpnext/hr/doctype/appointment_letter/appointment_letter.py +++ b/erpnext/hr/doctype/appointment_letter/appointment_letter.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class AppointmentLetter(Document): pass diff --git a/erpnext/hr/doctype/appointment_letter/test_appointment_letter.py b/erpnext/hr/doctype/appointment_letter/test_appointment_letter.py index b9ce9819c5a..88637b9fe93 100644 --- a/erpnext/hr/doctype/appointment_letter/test_appointment_letter.py +++ b/erpnext/hr/doctype/appointment_letter/test_appointment_letter.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestAppointmentLetter(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/appointment_letter_content/appointment_letter_content.py b/erpnext/hr/doctype/appointment_letter_content/appointment_letter_content.py index a1a49e536b6..f4db456af38 100644 --- a/erpnext/hr/doctype/appointment_letter_content/appointment_letter_content.py +++ b/erpnext/hr/doctype/appointment_letter_content/appointment_letter_content.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AppointmentLettercontent(Document): pass diff --git a/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.py b/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.py index c23881f8007..acb5c1f6924 100644 --- a/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.py +++ b/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class AppointmentLetterTemplate(Document): pass diff --git a/erpnext/hr/doctype/appointment_letter_template/test_appointment_letter_template.py b/erpnext/hr/doctype/appointment_letter_template/test_appointment_letter_template.py index 3d061ac8e93..46dd3e12727 100644 --- a/erpnext/hr/doctype/appointment_letter_template/test_appointment_letter_template.py +++ b/erpnext/hr/doctype/appointment_letter_template/test_appointment_letter_template.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestAppointmentLetterTemplate(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/appraisal/appraisal.py b/erpnext/hr/doctype/appraisal/appraisal.py index c2ed4579844..96a4ffa524a 100644 --- a/erpnext/hr/doctype/appraisal/appraisal.py +++ b/erpnext/hr/doctype/appraisal/appraisal.py @@ -2,15 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc from frappe.utils import flt, getdate -from frappe import _ -from frappe.model.mapper import get_mapped_doc -from frappe.model.document import Document from erpnext.hr.utils import set_employee_name, validate_active_employee + class Appraisal(Document): def validate(self): if not self.status: diff --git a/erpnext/hr/doctype/appraisal/test_appraisal.py b/erpnext/hr/doctype/appraisal/test_appraisal.py index f70dc481c80..cf2bd7c2427 100644 --- a/erpnext/hr/doctype/appraisal/test_appraisal.py +++ b/erpnext/hr/doctype/appraisal/test_appraisal.py @@ -2,7 +2,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Appraisal') diff --git a/erpnext/hr/doctype/appraisal_goal/appraisal_goal.py b/erpnext/hr/doctype/appraisal_goal/appraisal_goal.py index 11d9f3944d5..d9789a028bd 100644 --- a/erpnext/hr/doctype/appraisal_goal/appraisal_goal.py +++ b/erpnext/hr/doctype/appraisal_goal/appraisal_goal.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class AppraisalGoal(Document): pass diff --git a/erpnext/hr/doctype/appraisal_template/appraisal_template.py b/erpnext/hr/doctype/appraisal_template/appraisal_template.py index d0dfad4be31..d10a0de3bce 100644 --- a/erpnext/hr/doctype/appraisal_template/appraisal_template.py +++ b/erpnext/hr/doctype/appraisal_template/appraisal_template.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import cint, flt -from frappe import _ +import frappe +from frappe import _ from frappe.model.document import Document +from frappe.utils import cint, flt + class AppraisalTemplate(Document): def validate(self): diff --git a/erpnext/hr/doctype/appraisal_template/appraisal_template_dashboard.py b/erpnext/hr/doctype/appraisal_template/appraisal_template_dashboard.py index 392b370e6c3..b8d04944edb 100644 --- a/erpnext/hr/doctype/appraisal_template/appraisal_template_dashboard.py +++ b/erpnext/hr/doctype/appraisal_template/appraisal_template_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/appraisal_template/test_appraisal_template.py b/erpnext/hr/doctype/appraisal_template/test_appraisal_template.py index e3029d980a0..a814ec8d5b2 100644 --- a/erpnext/hr/doctype/appraisal_template/test_appraisal_template.py +++ b/erpnext/hr/doctype/appraisal_template/test_appraisal_template.py @@ -2,7 +2,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Appraisal Template') diff --git a/erpnext/hr/doctype/appraisal_template_goal/appraisal_template_goal.py b/erpnext/hr/doctype/appraisal_template_goal/appraisal_template_goal.py index b3c5704fa53..1b15fbd51e1 100644 --- a/erpnext/hr/doctype/appraisal_template_goal/appraisal_template_goal.py +++ b/erpnext/hr/doctype/appraisal_template_goal/appraisal_template_goal.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class AppraisalTemplateGoal(Document): pass diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py index c1a7c8f88a5..002f9bbcac2 100644 --- a/erpnext/hr/doctype/attendance/attendance.py +++ b/erpnext/hr/doctype/attendance/attendance.py @@ -2,14 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import getdate, nowdate +import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cstr, get_datetime, formatdate +from frappe.utils import cstr, formatdate, get_datetime, getdate, nowdate + from erpnext.hr.utils import validate_active_employee + class Attendance(Document): def validate(self): from erpnext.controllers.status_updater import validate_status @@ -134,7 +135,6 @@ def mark_attendance(employee, attendance_date, status, shift=None, leave_type=No @frappe.whitelist() def mark_bulk_attendance(data): import json - from pprint import pprint if isinstance(data, str): data = json.loads(data) data = frappe._dict(data) diff --git a/erpnext/hr/doctype/attendance/attendance_dashboard.py b/erpnext/hr/doctype/attendance/attendance_dashboard.py index 5dd9403674e..bbe67dfcc8f 100644 --- a/erpnext/hr/doctype/attendance/attendance_dashboard.py +++ b/erpnext/hr/doctype/attendance/attendance_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/attendance/test_attendance.py b/erpnext/hr/doctype/attendance/test_attendance.py index 838b704c5a5..ab443774212 100644 --- a/erpnext/hr/doctype/attendance/test_attendance.py +++ b/erpnext/hr/doctype/attendance/test_attendance.py @@ -2,8 +2,9 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import nowdate test_records = frappe.get_test_records('Attendance') diff --git a/erpnext/hr/doctype/attendance_request/attendance_request.py b/erpnext/hr/doctype/attendance_request/attendance_request.py index 7f88fed73a2..1e7429656d2 100644 --- a/erpnext/hr/doctype/attendance_request/attendance_request.py +++ b/erpnext/hr/doctype/attendance_request/attendance_request.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import date_diff, add_days, getdate +from frappe.utils import add_days, date_diff, getdate + from erpnext.hr.doctype.employee.employee import is_holiday -from erpnext.hr.utils import validate_dates, validate_active_employee +from erpnext.hr.utils import validate_active_employee, validate_dates + class AttendanceRequest(Document): def validate(self): diff --git a/erpnext/hr/doctype/attendance_request/attendance_request_dashboard.py b/erpnext/hr/doctype/attendance_request/attendance_request_dashboard.py index 2d3eb000119..8feb6f2f23e 100644 --- a/erpnext/hr/doctype/attendance_request/attendance_request_dashboard.py +++ b/erpnext/hr/doctype/attendance_request/attendance_request_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'attendance_request', diff --git a/erpnext/hr/doctype/attendance_request/test_attendance_request.py b/erpnext/hr/doctype/attendance_request/test_attendance_request.py index 9e668aa72fb..a9db74cbf75 100644 --- a/erpnext/hr/doctype/attendance_request/test_attendance_request.py +++ b/erpnext/hr/doctype/attendance_request/test_attendance_request.py @@ -3,11 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate from datetime import date +import frappe +from frappe.utils import nowdate + test_dependencies = ["Employee"] class TestAttendanceRequest(unittest.TestCase): diff --git a/erpnext/hr/doctype/branch/branch.py b/erpnext/hr/doctype/branch/branch.py index a847c8e2174..c770dc34090 100644 --- a/erpnext/hr/doctype/branch/branch.py +++ b/erpnext/hr/doctype/branch/branch.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class Branch(Document): pass diff --git a/erpnext/hr/doctype/branch/test_branch.py b/erpnext/hr/doctype/branch/test_branch.py index 807698ba0a2..7bf9b395308 100644 --- a/erpnext/hr/doctype/branch/test_branch.py +++ b/erpnext/hr/doctype/branch/test_branch.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Branch') diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py index 3db81654a65..f24483bf827 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py +++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py @@ -3,12 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import date_diff, add_days, getdate, cint, format_date from frappe.model.document import Document -from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period, validate_active_employee, \ - create_additional_leave_ledger_entry, get_holiday_dates_for_employee +from frappe.utils import add_days, cint, date_diff, format_date, getdate + +from erpnext.hr.utils import ( + create_additional_leave_ledger_entry, + get_holiday_dates_for_employee, + get_leave_period, + validate_active_employee, + validate_dates, + validate_overlap, +) + class CompensatoryLeaveRequest(Document): diff --git a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py index 3b99c57051a..95bdd514ef3 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py +++ b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py @@ -3,12 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import today, add_months, add_days + +import frappe +from frappe.utils import add_days, add_months, today + from erpnext.hr.doctype.attendance_request.test_attendance_request import get_employee -from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on +from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period test_dependencies = ["Employee"] diff --git a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py index 1cc23812f75..92cf6aac851 100644 --- a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py +++ b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py @@ -3,11 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document -from frappe import _ from email_reply_parser import EmailReplyParser -from erpnext.hr.doctype.employee.employee import is_holiday +from frappe import _ +from frappe.model.document import Document from frappe.utils import global_date_format from six import string_types @@ -82,7 +82,7 @@ class DailyWorkSummary(Document): crop=True ) d.image = thumbnail_image - except: + except Exception: d.image = original_image if d.sender in did_not_reply: diff --git a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py index 38684799763..bed12e31eaa 100644 --- a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py +++ b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py @@ -4,8 +4,9 @@ from __future__ import unicode_literals import os -import frappe import unittest + +import frappe import frappe.utils # test_records = frappe.get_test_records('Daily Work Summary') @@ -64,8 +65,7 @@ class TestDailyWorkSummary(unittest.TestCase): filters=dict(email=('!=', 'test@example.com'))) self.setup_groups(hour) - from erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group \ - import trigger_emails + from erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group import trigger_emails trigger_emails() # check if emails are created diff --git a/erpnext/hr/doctype/daily_work_summary_group/daily_work_summary_group.py b/erpnext/hr/doctype/daily_work_summary_group/daily_work_summary_group.py index ece331aa718..152b1a9c7c5 100644 --- a/erpnext/hr/doctype/daily_work_summary_group/daily_work_summary_group.py +++ b/erpnext/hr/doctype/daily_work_summary_group/daily_work_summary_group.py @@ -3,13 +3,16 @@ # # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document import frappe.utils from frappe import _ +from frappe.model.document import Document + from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_user_emails_from_group from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday + class DailyWorkSummaryGroup(Document): def validate(self): if self.users: diff --git a/erpnext/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py b/erpnext/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py index eefcc0c3a65..d69a7fbf987 100644 --- a/erpnext/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py +++ b/erpnext/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class DailyWorkSummaryGroupUser(Document): pass diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py index 539a360269f..b4771b3fed0 100644 --- a/erpnext/hr/doctype/department/department.py +++ b/erpnext/hr/doctype/department/department.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils.nestedset import NestedSet, get_root_of + from erpnext.utilities.transaction_base import delete_events -from frappe.model.document import Document + class Department(NestedSet): nsm_parent_field = 'parent_department' diff --git a/erpnext/hr/doctype/department/test_department.py b/erpnext/hr/doctype/department/test_department.py index e4f6645ee42..2fb3b95ef43 100644 --- a/erpnext/hr/doctype/department/test_department.py +++ b/erpnext/hr/doctype/department/test_department.py @@ -1,9 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import unittest +import frappe + test_ignore = ["Leave Block List"] class TestDepartment(unittest.TestCase): def test_remove_department_data(self): diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py index d337959d534..113ea1887fc 100644 --- a/erpnext/hr/doctype/department_approver/department_approver.py +++ b/erpnext/hr/doctype/department_approver/department_approver.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class DepartmentApprover(Document): pass diff --git a/erpnext/hr/doctype/designation/designation.py b/erpnext/hr/doctype/designation/designation.py index a3f84aab5f0..0291a992cd9 100644 --- a/erpnext/hr/doctype/designation/designation.py +++ b/erpnext/hr/doctype/designation/designation.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class Designation(Document): pass diff --git a/erpnext/hr/doctype/designation/test_designation.py b/erpnext/hr/doctype/designation/test_designation.py index 2778862a1c2..33aa2433cee 100644 --- a/erpnext/hr/doctype/designation/test_designation.py +++ b/erpnext/hr/doctype/designation/test_designation.py @@ -2,8 +2,8 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + # test_records = frappe.get_test_records('Designation') def create_designation(**args): diff --git a/erpnext/hr/doctype/designation_skill/designation_skill.py b/erpnext/hr/doctype/designation_skill/designation_skill.py index c37d21f454e..2074dc9df51 100644 --- a/erpnext/hr/doctype/designation_skill/designation_skill.py +++ b/erpnext/hr/doctype/designation_skill/designation_skill.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DesignationSkill(Document): pass diff --git a/erpnext/hr/doctype/driver/driver.py b/erpnext/hr/doctype/driver/driver.py index 2cd22cd5480..5c428b57fc9 100644 --- a/erpnext/hr/doctype/driver/driver.py +++ b/erpnext/hr/doctype/driver/driver.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class Driver(Document): pass diff --git a/erpnext/hr/doctype/driver/test_driver.py b/erpnext/hr/doctype/driver/test_driver.py index 4bc4a8fd57b..fa3623745ba 100644 --- a/erpnext/hr/doctype/driver/test_driver.py +++ b/erpnext/hr/doctype/driver/test_driver.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestDriver(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/driving_license_category/driving_license_category.py b/erpnext/hr/doctype/driving_license_category/driving_license_category.py index 33ba138e27c..63ac4184bd9 100644 --- a/erpnext/hr/doctype/driving_license_category/driving_license_category.py +++ b/erpnext/hr/doctype/driving_license_category/driving_license_category.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DrivingLicenseCategory(Document): pass diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 643f3da2ff7..79e8f6140aa 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -1,15 +1,21 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt import frappe - -from frappe.utils import getdate, validate_email_address, today, add_years, cstr +from frappe import _, scrub, throw from frappe.model.naming import set_name_by_naming_series -from frappe import throw, _, scrub -from frappe.permissions import add_user_permission, remove_user_permission, \ - set_user_permission_if_allowed, has_permission, get_doc_permissions -from erpnext.utilities.transaction_base import delete_events +from frappe.permissions import ( + add_user_permission, + get_doc_permissions, + has_permission, + remove_user_permission, + set_user_permission_if_allowed, +) +from frappe.utils import add_years, cstr, getdate, today, validate_email_address from frappe.utils.nestedset import NestedSet +from erpnext.utilities.transaction_base import delete_events + + class EmployeeUserDisabledError(frappe.ValidationError): pass class InactiveEmployeeStatusError(frappe.ValidationError): diff --git a/erpnext/hr/doctype/employee/employee_dashboard.py b/erpnext/hr/doctype/employee/employee_dashboard.py index e853bee69f2..ce307be60e8 100644 --- a/erpnext/hr/doctype/employee/employee_dashboard.py +++ b/erpnext/hr/doctype/employee/employee_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/hr/doctype/employee/employee_reminders.py b/erpnext/hr/doctype/employee/employee_reminders.py index 2155c027a9b..ba086dc0602 100644 --- a/erpnext/hr/doctype/employee/employee_reminders.py +++ b/erpnext/hr/doctype/employee/employee_reminders.py @@ -3,15 +3,17 @@ import frappe from frappe import _ -from frappe.utils import comma_sep, getdate, today, add_months, add_days +from frappe.utils import add_days, add_months, comma_sep, getdate, today + from erpnext.hr.doctype.employee.employee import get_all_employee_emails, get_employee_email from erpnext.hr.utils import get_holidays_for_employee + # ----------------- # HOLIDAY REMINDERS # ----------------- def send_reminders_in_advance_weekly(): - to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders") or 1) + to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders")) frequency = frappe.db.get_single_value("HR Settings", "frequency") if not (to_send_in_advance and frequency == "Weekly"): return @@ -19,7 +21,7 @@ def send_reminders_in_advance_weekly(): send_advance_holiday_reminders("Weekly") def send_reminders_in_advance_monthly(): - to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders") or 1) + to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders")) frequency = frappe.db.get_single_value("HR Settings", "frequency") if not (to_send_in_advance and frequency == "Monthly"): return @@ -77,7 +79,7 @@ def send_holidays_reminder_in_advance(employee, holidays): # ------------------ def send_birthday_reminders(): """Send Employee birthday reminders if no 'Stop Birthday Reminders' is not set.""" - to_send = int(frappe.db.get_single_value("HR Settings", "send_birthday_reminders") or 1) + to_send = int(frappe.db.get_single_value("HR Settings", "send_birthday_reminders")) if not to_send: return diff --git a/erpnext/hr/doctype/employee/test_employee.py b/erpnext/hr/doctype/employee/test_employee.py index 5feb6de8f2b..8d6dfa2c1d2 100644 --- a/erpnext/hr/doctype/employee/test_employee.py +++ b/erpnext/hr/doctype/employee/test_employee.py @@ -1,10 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import frappe -import erpnext import unittest + +import frappe import frappe.utils + +import erpnext from erpnext.hr.doctype.employee.employee import InactiveEmployeeStatusError test_records = frappe.get_test_records('Employee') @@ -23,9 +25,9 @@ class TestEmployee(unittest.TestCase): self.assertRaises(InactiveEmployeeStatusError, employee1_doc.save) def test_employee_status_inactive(self): - from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure - from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list + from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip + from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure employee = make_employee("test_employee_status@company.com") employee_doc = frappe.get_doc("Employee", employee) diff --git a/erpnext/hr/doctype/employee/test_employee_reminders.py b/erpnext/hr/doctype/employee/test_employee_reminders.py index 7e560f512d1..52c00982443 100644 --- a/erpnext/hr/doctype/employee/test_employee_reminders.py +++ b/erpnext/hr/doctype/employee/test_employee_reminders.py @@ -1,11 +1,12 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import frappe import unittest - -from frappe.utils import getdate from datetime import timedelta + +import frappe +from frappe.utils import getdate + from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.hr.doctype.hr_settings.hr_settings import set_proceed_with_frequency_change @@ -18,7 +19,7 @@ class TestEmployeeReminders(unittest.TestCase): # Create a test holiday list test_holiday_dates = cls.get_test_holiday_dates() test_holiday_list = make_holiday_list( - 'TestHolidayRemindersList', + 'TestHolidayRemindersList', holiday_dates=[ {'holiday_date': test_holiday_dates[0], 'description': 'test holiday1'}, {'holiday_date': test_holiday_dates[1], 'description': 'test holiday2'}, @@ -49,8 +50,8 @@ class TestEmployeeReminders(unittest.TestCase): def get_test_holiday_dates(cls): today_date = getdate() return [ - today_date, - today_date-timedelta(days=4), + today_date, + today_date-timedelta(days=4), today_date-timedelta(days=3), today_date+timedelta(days=1), today_date+timedelta(days=3), @@ -63,7 +64,7 @@ class TestEmployeeReminders(unittest.TestCase): def test_is_holiday(self): from erpnext.hr.doctype.employee.employee import is_holiday - + self.assertTrue(is_holiday(self.test_employee.name)) self.assertTrue(is_holiday(self.test_employee.name, date=self.test_holiday_dates[1])) self.assertFalse(is_holiday(self.test_employee.name, date=getdate()-timedelta(days=1))) @@ -84,7 +85,10 @@ class TestEmployeeReminders(unittest.TestCase): employee.company = "_Test Company" employee.save() - from erpnext.hr.doctype.employee.employee_reminders import get_employees_who_are_born_today, send_birthday_reminders + from erpnext.hr.doctype.employee.employee_reminders import ( + get_employees_who_are_born_today, + send_birthday_reminders, + ) employees_born_today = get_employees_who_are_born_today() self.assertTrue(employees_born_today.get("_Test Company")) @@ -105,7 +109,10 @@ class TestEmployeeReminders(unittest.TestCase): employee.company = "_Test Company" employee.save() - from erpnext.hr.doctype.employee.employee_reminders import get_employees_having_an_event_today, send_work_anniversary_reminders + from erpnext.hr.doctype.employee.employee_reminders import ( + get_employees_having_an_event_today, + send_work_anniversary_reminders, + ) employees_having_work_anniversary = get_employees_having_an_event_today('work_anniversary') self.assertTrue(employees_having_work_anniversary.get("_Test Company")) @@ -118,10 +125,10 @@ class TestEmployeeReminders(unittest.TestCase): email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True) self.assertTrue("Subject: Work Anniversary Reminder" in email_queue[0].message) - + def test_send_holidays_reminder_in_advance(self): - from erpnext.hr.utils import get_holidays_for_employee from erpnext.hr.doctype.employee.employee_reminders import send_holidays_reminder_in_advance + from erpnext.hr.utils import get_holidays_for_employee # Get HR settings and enable advance holiday reminders hr_settings = frappe.get_doc("HR Settings", "HR Settings") @@ -133,10 +140,10 @@ class TestEmployeeReminders(unittest.TestCase): holidays = get_holidays_for_employee( self.test_employee.get('name'), getdate(), getdate() + timedelta(days=3), - only_non_weekly=True, + only_non_weekly=True, raise_exception=False ) - + send_holidays_reminder_in_advance( self.test_employee.get('name'), holidays @@ -147,6 +154,7 @@ class TestEmployeeReminders(unittest.TestCase): def test_advance_holiday_reminders_monthly(self): from erpnext.hr.doctype.employee.employee_reminders import send_reminders_in_advance_monthly + # Get HR settings and enable advance holiday reminders hr_settings = frappe.get_doc("HR Settings", "HR Settings") hr_settings.send_holiday_reminders = 1 @@ -158,9 +166,10 @@ class TestEmployeeReminders(unittest.TestCase): email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True) self.assertTrue(len(email_queue) > 0) - + def test_advance_holiday_reminders_weekly(self): from erpnext.hr.doctype.employee.employee_reminders import send_reminders_in_advance_weekly + # Get HR settings and enable advance holiday reminders hr_settings = frappe.get_doc("HR Settings", "HR Settings") hr_settings.send_holiday_reminders = 1 diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index cbb3cc813b4..87d42d34e39 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -3,13 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import flt, nowdate + +import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account from erpnext.hr.utils import validate_active_employee + class EmployeeAdvanceOverPayment(frappe.ValidationError): pass diff --git a/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py b/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py index 2f493e2d4e6..17d5bd27a6e 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.py b/erpnext/hr/doctype/employee_advance/test_employee_advance.py index 100968bb7aa..f8e5f535cb5 100644 --- a/erpnext/hr/doctype/employee_advance/test_employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/test_employee_advance.py @@ -3,12 +3,18 @@ # See license.txt from __future__ import unicode_literals -import frappe, erpnext import unittest + +import frappe from frappe.utils import nowdate -from erpnext.hr.doctype.employee_advance.employee_advance import make_bank_entry -from erpnext.hr.doctype.employee_advance.employee_advance import EmployeeAdvanceOverPayment + +import erpnext from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.employee_advance.employee_advance import ( + EmployeeAdvanceOverPayment, + make_bank_entry, +) + class TestEmployeeAdvance(unittest.TestCase): def test_paid_amount_and_status(self): diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py index 16c1a32b9b5..7c751a47a6b 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py +++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe.model.document import Document from frappe.utils import getdate diff --git a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.py b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.py index 496f1653ba0..48c85f48aa2 100644 --- a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.py +++ b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeBoardingActivity(Document): pass diff --git a/erpnext/hr/doctype/employee_checkin/employee_checkin.py b/erpnext/hr/doctype/employee_checkin/employee_checkin.py index 6c0cd4f963b..1ae9b1fa829 100644 --- a/erpnext/hr/doctype/employee_checkin/employee_checkin.py +++ b/erpnext/hr/doctype/employee_checkin/employee_checkin.py @@ -3,14 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import now, cint, get_datetime -from frappe.model.document import Document -from frappe import _ -from erpnext.hr.doctype.shift_assignment.shift_assignment import get_actual_start_end_datetime_of_shift +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import cint, get_datetime + +from erpnext.hr.doctype.shift_assignment.shift_assignment import ( + get_actual_start_end_datetime_of_shift, +) from erpnext.hr.utils import validate_active_employee + class EmployeeCheckin(Document): def validate(self): validate_active_employee(self.employee) diff --git a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py index 7ba511f08d5..71c6498dd7c 100644 --- a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py +++ b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py @@ -3,13 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import now_datetime, nowdate, to_timedelta import unittest from datetime import timedelta -from erpnext.hr.doctype.employee_checkin.employee_checkin import add_log_based_on_employee_field, mark_attendance_and_link_log, calculate_working_hours +import frappe +from frappe.utils import now_datetime, nowdate + from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.employee_checkin.employee_checkin import ( + add_log_based_on_employee_field, + calculate_working_hours, + mark_attendance_and_link_log, +) + class TestEmployeeCheckin(unittest.TestCase): def test_add_log_based_on_employee_field(self): diff --git a/erpnext/hr/doctype/employee_education/employee_education.py b/erpnext/hr/doctype/employee_education/employee_education.py index f0a76172b2c..cadf5d64594 100644 --- a/erpnext/hr/doctype/employee_education/employee_education.py +++ b/erpnext/hr/doctype/employee_education/employee_education.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class EmployeeEducation(Document): pass diff --git a/erpnext/hr/doctype/employee_external_work_history/employee_external_work_history.py b/erpnext/hr/doctype/employee_external_work_history/employee_external_work_history.py index 517ef57be85..4d0e8d9b74a 100644 --- a/erpnext/hr/doctype/employee_external_work_history/employee_external_work_history.py +++ b/erpnext/hr/doctype/employee_external_work_history/employee_external_work_history.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class EmployeeExternalWorkHistory(Document): pass diff --git a/erpnext/hr/doctype/employee_grade/employee_grade.py b/erpnext/hr/doctype/employee_grade/employee_grade.py index 42a9f161359..b097038b5c2 100644 --- a/erpnext/hr/doctype/employee_grade/employee_grade.py +++ b/erpnext/hr/doctype/employee_grade/employee_grade.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeGrade(Document): pass diff --git a/erpnext/hr/doctype/employee_grade/employee_grade_dashboard.py b/erpnext/hr/doctype/employee_grade/employee_grade_dashboard.py index df679104185..92d9fa082c9 100644 --- a/erpnext/hr/doctype/employee_grade/employee_grade_dashboard.py +++ b/erpnext/hr/doctype/employee_grade/employee_grade_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'transactions': [ diff --git a/erpnext/hr/doctype/employee_grade/test_employee_grade.py b/erpnext/hr/doctype/employee_grade/test_employee_grade.py index 93058cf1083..cd4fcb5aeb4 100644 --- a/erpnext/hr/doctype/employee_grade/test_employee_grade.py +++ b/erpnext/hr/doctype/employee_grade/test_employee_grade.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeGrade(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employee_grievance/employee_grievance.py b/erpnext/hr/doctype/employee_grievance/employee_grievance.py index 17055829efb..fd9a33b3771 100644 --- a/erpnext/hr/doctype/employee_grievance/employee_grievance.py +++ b/erpnext/hr/doctype/employee_grievance/employee_grievance.py @@ -5,6 +5,7 @@ import frappe from frappe import _, bold from frappe.model.document import Document + class EmployeeGrievance(Document): def on_submit(self): if self.status not in ["Invalid", "Resolved"]: diff --git a/erpnext/hr/doctype/employee_grievance/test_employee_grievance.py b/erpnext/hr/doctype/employee_grievance/test_employee_grievance.py index ed897ee1032..e2d0002aa62 100644 --- a/erpnext/hr/doctype/employee_grievance/test_employee_grievance.py +++ b/erpnext/hr/doctype/employee_grievance/test_employee_grievance.py @@ -1,10 +1,14 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import frappe import unittest + +import frappe from frappe.utils import today + from erpnext.hr.doctype.employee.test_employee import make_employee + + class TestEmployeeGrievance(unittest.TestCase): def test_create_employee_grievance(self): create_employee_grievance() diff --git a/erpnext/hr/doctype/employee_group/employee_group.py b/erpnext/hr/doctype/employee_group/employee_group.py index 3025877b8e1..b2fe5eb3ad6 100644 --- a/erpnext/hr/doctype/employee_group/employee_group.py +++ b/erpnext/hr/doctype/employee_group/employee_group.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class EmployeeGroup(Document): pass diff --git a/erpnext/hr/doctype/employee_group/test_employee_group.py b/erpnext/hr/doctype/employee_group/test_employee_group.py index 26a61c407b2..053e840740a 100644 --- a/erpnext/hr/doctype/employee_group/test_employee_group.py +++ b/erpnext/hr/doctype/employee_group/test_employee_group.py @@ -2,10 +2,14 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe + import unittest + +import frappe + from erpnext.hr.doctype.employee.test_employee import make_employee + class TestEmployeeGroup(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employee_group_table/employee_group_table.py b/erpnext/hr/doctype/employee_group_table/employee_group_table.py index 816611d018d..d9407a96fa6 100644 --- a/erpnext/hr/doctype/employee_group_table/employee_group_table.py +++ b/erpnext/hr/doctype/employee_group_table/employee_group_table.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class EmployeeGroupTable(Document): pass diff --git a/erpnext/hr/doctype/employee_health_insurance/employee_health_insurance.py b/erpnext/hr/doctype/employee_health_insurance/employee_health_insurance.py index abc01ef8d4b..4f2d1a07653 100644 --- a/erpnext/hr/doctype/employee_health_insurance/employee_health_insurance.py +++ b/erpnext/hr/doctype/employee_health_insurance/employee_health_insurance.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeHealthInsurance(Document): pass diff --git a/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.py b/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.py index f0787f52d20..38e3ee316bb 100644 --- a/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.py +++ b/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeHealthInsurance(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employee_internal_work_history/employee_internal_work_history.py b/erpnext/hr/doctype/employee_internal_work_history/employee_internal_work_history.py index 2f385a8113e..6076abb3468 100644 --- a/erpnext/hr/doctype/employee_internal_work_history/employee_internal_work_history.py +++ b/erpnext/hr/doctype/employee_internal_work_history/employee_internal_work_history.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class EmployeeInternalWorkHistory(Document): pass diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py index 0cb50475bf8..7421e17ca84 100644 --- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py +++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from erpnext.hr.utils import EmployeeBoardingController from frappe.model.mapper import get_mapped_doc +from erpnext.hr.utils import EmployeeBoardingController + + class IncompleteTaskError(frappe.ValidationError): pass class EmployeeOnboarding(EmployeeBoardingController): diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py index 336e13c9b77..33cad7b7e9b 100644 --- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py +++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py @@ -3,13 +3,18 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import nowdate -from erpnext.hr.doctype.employee_onboarding.employee_onboarding import make_employee -from erpnext.hr.doctype.employee_onboarding.employee_onboarding import IncompleteTaskError + +from erpnext.hr.doctype.employee_onboarding.employee_onboarding import ( + IncompleteTaskError, + make_employee, +) from erpnext.hr.doctype.job_offer.test_job_offer import create_job_offer + class TestEmployeeOnboarding(unittest.TestCase): def test_employee_onboarding_incomplete_task(self): if frappe.db.exists('Employee Onboarding', {'employee_name': 'Test Researcher'}): diff --git a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py index d1706318191..526c2c9cde6 100644 --- a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py +++ b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeOnboardingActivity(Document): pass diff --git a/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template.py b/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template.py index 6f1c3167315..a46b3cdda39 100644 --- a/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template.py +++ b/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeOnboardingTemplate(Document): pass diff --git a/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template_dashboard.py b/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template_dashboard.py index ab0eb2f5dce..1d2e8ae18db 100644 --- a/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template_dashboard.py +++ b/erpnext/hr/doctype/employee_onboarding_template/employee_onboarding_template_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.py b/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.py index f4b5b883428..92a328b71ef 100644 --- a/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.py +++ b/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeOnboardingTemplate(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.py b/erpnext/hr/doctype/employee_promotion/employee_promotion.py index a3a61834c8c..164d48b8952 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import getdate + from erpnext.hr.utils import update_employee, validate_active_employee + class EmployeePromotion(Document): def validate(self): validate_active_employee(self.employee) diff --git a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py index 9e7d3186b88..39af6ff7cc7 100644 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py @@ -3,11 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import getdate, add_days + +import frappe +from frappe.utils import add_days, getdate + from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee + class TestEmployeePromotion(unittest.TestCase): def setUp(self): self.employee = make_employee("employee@promotions.com") diff --git a/erpnext/hr/doctype/employee_property_history/employee_property_history.py b/erpnext/hr/doctype/employee_property_history/employee_property_history.py index fb67852d164..9e2549284fb 100644 --- a/erpnext/hr/doctype/employee_property_history/employee_property_history.py +++ b/erpnext/hr/doctype/employee_property_history/employee_property_history.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeePropertyHistory(Document): pass diff --git a/erpnext/hr/doctype/employee_referral/employee_referral.py b/erpnext/hr/doctype/employee_referral/employee_referral.py index 547a95e3bdf..5cb5bb5fd3a 100644 --- a/erpnext/hr/doctype/employee_referral/employee_referral.py +++ b/erpnext/hr/doctype/employee_referral/employee_referral.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import get_link_to_form from frappe.model.document import Document +from frappe.utils import get_link_to_form + from erpnext.hr.utils import validate_active_employee + class EmployeeReferral(Document): def validate(self): validate_active_employee(self.referrer) @@ -56,6 +59,7 @@ def create_job_applicant(source_name, target_doc=None): @frappe.whitelist() def create_additional_salary(doc): import json + from six import string_types if isinstance(doc, string_types): diff --git a/erpnext/hr/doctype/employee_referral/employee_referral_dashboard.py b/erpnext/hr/doctype/employee_referral/employee_referral_dashboard.py index caca2961a1a..85d6c2089b8 100644 --- a/erpnext/hr/doctype/employee_referral/employee_referral_dashboard.py +++ b/erpnext/hr/doctype/employee_referral/employee_referral_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'employee_referral', diff --git a/erpnext/hr/doctype/employee_referral/test_employee_referral.py b/erpnext/hr/doctype/employee_referral/test_employee_referral.py index 599f3262240..d0ee2fcdea7 100644 --- a/erpnext/hr/doctype/employee_referral/test_employee_referral.py +++ b/erpnext/hr/doctype/employee_referral/test_employee_referral.py @@ -3,12 +3,18 @@ # See license.txt from __future__ import unicode_literals +import unittest + import frappe from frappe.utils import today + from erpnext.hr.doctype.designation.test_designation import create_designation -from erpnext.hr.doctype.employee_referral.employee_referral import create_job_applicant, create_additional_salary from erpnext.hr.doctype.employee.test_employee import make_employee -import unittest +from erpnext.hr.doctype.employee_referral.employee_referral import ( + create_additional_salary, + create_job_applicant, +) + class TestEmployeeReferral(unittest.TestCase): def test_workflow_and_status_sync(self): diff --git a/erpnext/hr/doctype/employee_separation/employee_separation.py b/erpnext/hr/doctype/employee_separation/employee_separation.py index b64668157b0..140115bcf0f 100644 --- a/erpnext/hr/doctype/employee_separation/employee_separation.py +++ b/erpnext/hr/doctype/employee_separation/employee_separation.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + from erpnext.hr.utils import EmployeeBoardingController + class EmployeeSeparation(EmployeeBoardingController): def validate(self): super(EmployeeSeparation, self).validate() diff --git a/erpnext/hr/doctype/employee_separation/test_employee_separation.py b/erpnext/hr/doctype/employee_separation/test_employee_separation.py index 0b72efa1378..0489e71305b 100644 --- a/erpnext/hr/doctype/employee_separation/test_employee_separation.py +++ b/erpnext/hr/doctype/employee_separation/test_employee_separation.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_dependencies = ["Employee Onboarding"] class TestEmployeeSeparation(unittest.TestCase): diff --git a/erpnext/hr/doctype/employee_separation_template/employee_separation_template.py b/erpnext/hr/doctype/employee_separation_template/employee_separation_template.py index 0508fc462e2..7a263dcac10 100644 --- a/erpnext/hr/doctype/employee_separation_template/employee_separation_template.py +++ b/erpnext/hr/doctype/employee_separation_template/employee_separation_template.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeSeparationTemplate(Document): pass diff --git a/erpnext/hr/doctype/employee_separation_template/employee_separation_template_dashboard.py b/erpnext/hr/doctype/employee_separation_template/employee_separation_template_dashboard.py index 75f985cec39..970ba26d794 100644 --- a/erpnext/hr/doctype/employee_separation_template/employee_separation_template_dashboard.py +++ b/erpnext/hr/doctype/employee_separation_template/employee_separation_template_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.py b/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.py index 3fd3d398bd1..4c91a791038 100644 --- a/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.py +++ b/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeSeparationTemplate(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employee_skill/employee_skill.py b/erpnext/hr/doctype/employee_skill/employee_skill.py index ac05fba624b..6f860c6c599 100644 --- a/erpnext/hr/doctype/employee_skill/employee_skill.py +++ b/erpnext/hr/doctype/employee_skill/employee_skill.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeSkill(Document): pass diff --git a/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py index 073f02fa258..d93c22f2ab8 100644 --- a/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py +++ b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeSkillMap(Document): pass diff --git a/erpnext/hr/doctype/employee_training/employee_training.py b/erpnext/hr/doctype/employee_training/employee_training.py index 810796d66cf..068116a77f6 100644 --- a/erpnext/hr/doctype/employee_training/employee_training.py +++ b/erpnext/hr/doctype/employee_training/employee_training.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeTraining(Document): pass diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py index c2007747fb3..b1f66098f0d 100644 --- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py +++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import getdate + from erpnext.hr.utils import update_employee + class EmployeeTransfer(Document): def before_submit(self): if getdate(self.transfer_date) > getdate(): diff --git a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py b/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py index 93fc7a27056..ad2f3ade054 100644 --- a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py +++ b/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py @@ -3,11 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import getdate, add_days + +import frappe +from frappe.utils import add_days, getdate + from erpnext.hr.doctype.employee.test_employee import make_employee + class TestEmployeeTransfer(unittest.TestCase): def setUp(self): make_employee("employee2@transfers.com") diff --git a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py b/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py index 1a665dc1008..f67fd7c6564 100644 --- a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py +++ b/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeTransferProperty(Document): pass diff --git a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py b/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py index 39c20a6f716..287dac66f10 100644 --- a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py +++ b/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeTransferProperty(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/employment_type/employment_type.py b/erpnext/hr/doctype/employment_type/employment_type.py index 00aa6bb9bc4..e2a55570fd9 100644 --- a/erpnext/hr/doctype/employment_type/employment_type.py +++ b/erpnext/hr/doctype/employment_type/employment_type.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class EmploymentType(Document): pass diff --git a/erpnext/hr/doctype/employment_type/test_employment_type.py b/erpnext/hr/doctype/employment_type/test_employment_type.py index 0297ffa01a3..2ba4e8c1a46 100644 --- a/erpnext/hr/doctype/employment_type/test_employment_type.py +++ b/erpnext/hr/doctype/employment_type/test_employment_type.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Employment Type') diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 4dc089cb1d2..d785db7872c 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -2,17 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import get_fullname, flt, cstr, get_link_to_form -from frappe.model.document import Document -from erpnext.hr.utils import set_employee_name, share_doc_with_approver, validate_active_employee -from erpnext.accounts.party import get_party_account -from erpnext.accounts.general_ledger import make_gl_entries +from frappe.utils import cstr, flt, get_link_to_form + +import erpnext from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account +from erpnext.accounts.general_ledger import make_gl_entries from erpnext.controllers.accounts_controller import AccountsController -from frappe.utils.csvutils import getlink -from erpnext.accounts.utils import get_account_currency +from erpnext.hr.utils import set_employee_name, share_doc_with_approver, validate_active_employee + class InvalidExpenseApproverError(frappe.ValidationError): pass class ExpenseApproverIdentityError(frappe.ValidationError): pass diff --git a/erpnext/hr/doctype/expense_claim/expense_claim_dashboard.py b/erpnext/hr/doctype/expense_claim/expense_claim_dashboard.py index fe973507019..a5682dc1e95 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim_dashboard.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'reference_name', diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py index b5fc1fbe758..e54c1457244 100644 --- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py @@ -2,12 +2,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import random_string, nowdate, flt -from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry + +import frappe +from frappe.utils import flt, nowdate, random_string + from erpnext.accounts.doctype.account.test_account import create_account from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry test_records = frappe.get_test_records('Expense Claim') test_dependencies = ['Employee'] @@ -144,20 +146,20 @@ class TestExpenseClaim(unittest.TestCase): expense_claim = make_expense_claim(payable_account, 5500, 5500, "_Test Company", "Travel Expenses - _TC") expense_claim.save() expense_claim.submit() - + # Payment entry 1: paying 500 make_payment_entry(expense_claim, payable_account,500) outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) self.assertEqual(outstanding_amount, 5000) self.assertEqual(total_amount_reimbursed, 500) - + # Payment entry 1: paying 2000 make_payment_entry(expense_claim, payable_account,2000) outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) self.assertEqual(outstanding_amount, 3000) self.assertEqual(total_amount_reimbursed, 2500) - - # Payment entry 1: paying 3000 + + # Payment entry 1: paying 3000 make_payment_entry(expense_claim, payable_account,3000) outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) self.assertEqual(outstanding_amount, 0) @@ -221,7 +223,7 @@ def get_outstanding_and_total_reimbursed_amounts(expense_claim): outstanding_amount = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_sanctioned_amount")) - \ flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed")) total_amount_reimbursed = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed")) - + return outstanding_amount,total_amount_reimbursed def make_payment_entry(expense_claim, payable_account, amt): @@ -234,5 +236,5 @@ def make_payment_entry(expense_claim, payable_account, amt): pe.paid_to = payable_account pe.references[0].allocated_amount = amt pe.insert() - pe.submit() - + pe.submit() + diff --git a/erpnext/hr/doctype/expense_claim_account/expense_claim_account.py b/erpnext/hr/doctype/expense_claim_account/expense_claim_account.py index f34633cf58b..a982002ebb4 100644 --- a/erpnext/hr/doctype/expense_claim_account/expense_claim_account.py +++ b/erpnext/hr/doctype/expense_claim_account/expense_claim_account.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ExpenseClaimAccount(Document): pass diff --git a/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.py b/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.py index c4e7b026e3b..5607f41d917 100644 --- a/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.py +++ b/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ExpenseClaimAdvance(Document): pass diff --git a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.py b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.py index 5d48990c5ce..019e9f4dfe2 100644 --- a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.py +++ b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ExpenseClaimDetail(Document): pass diff --git a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.py b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.py index a637a540213..101461c54b1 100644 --- a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.py +++ b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class ExpenseClaimType(Document): def validate(self): self.validate_accounts() diff --git a/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.py b/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.py index 1d894308d3a..f0c900e6ef0 100644 --- a/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.py +++ b/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Expense Claim Type') diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py index 4103bef1ffe..596e8c719a4 100644 --- a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ExpenseTaxesandCharges(Document): pass diff --git a/erpnext/hr/doctype/grievance_type/grievance_type.py b/erpnext/hr/doctype/grievance_type/grievance_type.py index 618cf0a0318..5d8d41cb73d 100644 --- a/erpnext/hr/doctype/grievance_type/grievance_type.py +++ b/erpnext/hr/doctype/grievance_type/grievance_type.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class GrievanceType(Document): pass diff --git a/erpnext/hr/doctype/grievance_type/test_grievance_type.py b/erpnext/hr/doctype/grievance_type/test_grievance_type.py index a02a34d41fa..481f4e58a79 100644 --- a/erpnext/hr/doctype/grievance_type/test_grievance_type.py +++ b/erpnext/hr/doctype/grievance_type/test_grievance_type.py @@ -4,5 +4,6 @@ # import frappe import unittest + class TestGrievanceType(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/holiday/holiday.py b/erpnext/hr/doctype/holiday/holiday.py index 78a95b9b741..fbfe7563aa2 100644 --- a/erpnext/hr/doctype/holiday/holiday.py +++ b/erpnext/hr/doctype/holiday/holiday.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class Holiday(Document): pass diff --git a/erpnext/hr/doctype/holiday_list/holiday_list.py b/erpnext/hr/doctype/holiday_list/holiday_list.py index 8af8cea605d..8d91ac2ddd7 100644 --- a/erpnext/hr/doctype/holiday_list/holiday_list.py +++ b/erpnext/hr/doctype/holiday_list/holiday_list.py @@ -3,11 +3,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json -from frappe.utils import cint, getdate, formatdate, today -from frappe import throw, _ + +import frappe +from frappe import _, throw from frappe.model.document import Document +from frappe.utils import cint, formatdate, getdate, today + class OverlapError(frappe.ValidationError): pass @@ -44,9 +47,10 @@ class HolidayList(Document): def get_weekly_off_date_list(self, start_date, end_date): start_date, end_date = getdate(start_date), getdate(end_date) - from dateutil import relativedelta - from datetime import timedelta import calendar + from datetime import timedelta + + from dateutil import relativedelta date_list = [] existing_date_list = [] diff --git a/erpnext/hr/doctype/holiday_list/holiday_list_dashboard.py b/erpnext/hr/doctype/holiday_list/holiday_list_dashboard.py index 05641c7dc26..bbba36af875 100644 --- a/erpnext/hr/doctype/holiday_list/holiday_list_dashboard.py +++ b/erpnext/hr/doctype/holiday_list/holiday_list_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'holiday_list', diff --git a/erpnext/hr/doctype/holiday_list/test_holiday_list.py b/erpnext/hr/doctype/holiday_list/test_holiday_list.py index 64bed6637bd..27131932db4 100644 --- a/erpnext/hr/doctype/holiday_list/test_holiday_list.py +++ b/erpnext/hr/doctype/holiday_list/test_holiday_list.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import getdate from datetime import timedelta +import frappe +from frappe.utils import getdate + class TestHolidayList(unittest.TestCase): def test_holiday_list(self): diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.py b/erpnext/hr/doctype/hr_settings/hr_settings.py index a47409363c7..c295bcbc0d9 100644 --- a/erpnext/hr/doctype/hr_settings/hr_settings.py +++ b/erpnext/hr/doctype/hr_settings/hr_settings.py @@ -4,7 +4,6 @@ # For license information, please see license.txt import frappe - from frappe.model.document import Document from frappe.utils import format_date diff --git a/erpnext/hr/doctype/hr_settings/test_hr_settings.py b/erpnext/hr/doctype/hr_settings/test_hr_settings.py index b0b07b0c0b3..69a060a90f9 100644 --- a/erpnext/hr/doctype/hr_settings/test_hr_settings.py +++ b/erpnext/hr/doctype/hr_settings/test_hr_settings.py @@ -3,11 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.hr.doctype.employee.test_employee import make_employee -from frappe.utils import now_datetime -from datetime import timedelta + class TestHRSettings(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/identification_document_type/identification_document_type.py b/erpnext/hr/doctype/identification_document_type/identification_document_type.py index d9d81d2fa8f..862cd374fb4 100644 --- a/erpnext/hr/doctype/identification_document_type/identification_document_type.py +++ b/erpnext/hr/doctype/identification_document_type/identification_document_type.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class IdentificationDocumentType(Document): pass diff --git a/erpnext/hr/doctype/identification_document_type/test_identification_document_type.py b/erpnext/hr/doctype/identification_document_type/test_identification_document_type.py index 1265afaf457..87f302450db 100644 --- a/erpnext/hr/doctype/identification_document_type/test_identification_document_type.py +++ b/erpnext/hr/doctype/identification_document_type/test_identification_document_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestIdentificationDocumentType(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/interest/interest.py b/erpnext/hr/doctype/interest/interest.py index 2a9c19c09d8..1b8f49f9585 100644 --- a/erpnext/hr/doctype/interest/interest.py +++ b/erpnext/hr/doctype/interest/interest.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class Interest(Document): pass diff --git a/erpnext/hr/doctype/interest/test_interest.py b/erpnext/hr/doctype/interest/test_interest.py index a7fe83bccc8..f3727bee0b0 100644 --- a/erpnext/hr/doctype/interest/test_interest.py +++ b/erpnext/hr/doctype/interest/test_interest.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Interest') diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.py b/erpnext/hr/doctype/job_applicant/job_applicant.py index 14aeb03a87e..6971e5b4fef 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant.py +++ b/erpnext/hr/doctype/job_applicant/job_applicant.py @@ -4,11 +4,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + import frappe from frappe import _ +from frappe.model.document import Document from frappe.utils import comma_and, validate_email_address + class DuplicationError(frappe.ValidationError): pass class JobApplicant(Document): diff --git a/erpnext/hr/doctype/job_applicant/job_applicant_dashboard.py b/erpnext/hr/doctype/job_applicant/job_applicant_dashboard.py index ed97978a8ad..c0059431cfc 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant_dashboard.py +++ b/erpnext/hr/doctype/job_applicant/job_applicant_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/job_applicant/test_job_applicant.py b/erpnext/hr/doctype/job_applicant/test_job_applicant.py index 872834230e6..e583e25eae0 100644 --- a/erpnext/hr/doctype/job_applicant/test_job_applicant.py +++ b/erpnext/hr/doctype/job_applicant/test_job_applicant.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + # test_records = frappe.get_test_records('Job Applicant') class TestJobApplicant(unittest.TestCase): diff --git a/erpnext/hr/doctype/job_applicant_source/job_applicant_source.py b/erpnext/hr/doctype/job_applicant_source/job_applicant_source.py index 5f543d285cf..9139584aa5c 100644 --- a/erpnext/hr/doctype/job_applicant_source/job_applicant_source.py +++ b/erpnext/hr/doctype/job_applicant_source/job_applicant_source.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class JobApplicantSource(Document): pass diff --git a/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.py b/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.py index f318df20f7c..0c29124560b 100644 --- a/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.py +++ b/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestJobApplicantSource(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/job_offer/job_offer.py b/erpnext/hr/doctype/job_offer/job_offer.py index 7e650f76917..07a7809891d 100644 --- a/erpnext/hr/doctype/job_offer/job_offer.py +++ b/erpnext/hr/doctype/job_offer/job_offer.py @@ -2,13 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cint +from frappe import _ from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc -from frappe import _ +from frappe.utils import cint from frappe.utils.data import get_link_to_form + class JobOffer(Document): def onload(self): employee = frappe.db.get_value("Employee", {"job_applicant": self.job_applicant}, "name") or "" diff --git a/erpnext/hr/doctype/job_offer/test_job_offer.py b/erpnext/hr/doctype/job_offer/test_job_offer.py index edb21321fcc..3f3eca17e62 100644 --- a/erpnext/hr/doctype/job_offer/test_job_offer.py +++ b/erpnext/hr/doctype/job_offer/test_job_offer.py @@ -2,11 +2,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, add_days -from erpnext.hr.doctype.job_applicant.test_job_applicant import create_job_applicant + +import frappe +from frappe.utils import add_days, nowdate + from erpnext.hr.doctype.designation.test_designation import create_designation +from erpnext.hr.doctype.job_applicant.test_job_applicant import create_job_applicant from erpnext.hr.doctype.staffing_plan.test_staffing_plan import make_company # test_records = frappe.get_test_records('Job Offer') diff --git a/erpnext/hr/doctype/job_offer_term/job_offer_term.py b/erpnext/hr/doctype/job_offer_term/job_offer_term.py index 6dbe6757a70..573cc6ae21d 100644 --- a/erpnext/hr/doctype/job_offer_term/job_offer_term.py +++ b/erpnext/hr/doctype/job_offer_term/job_offer_term.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class JobOfferTerm(Document): pass diff --git a/erpnext/hr/doctype/job_opening/job_opening.py b/erpnext/hr/doctype/job_opening/job_opening.py index 1e897671770..38d9a718170 100644 --- a/erpnext/hr/doctype/job_opening/job_opening.py +++ b/erpnext/hr/doctype/job_opening/job_opening.py @@ -4,11 +4,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.website.website_generator import WebsiteGenerator +import frappe from frappe import _ -from erpnext.hr.doctype.staffing_plan.staffing_plan import get_designation_counts, get_active_staffing_plan_details +from frappe.website.website_generator import WebsiteGenerator + +from erpnext.hr.doctype.staffing_plan.staffing_plan import ( + get_active_staffing_plan_details, + get_designation_counts, +) + class JobOpening(WebsiteGenerator): website = frappe._dict( diff --git a/erpnext/hr/doctype/job_opening/job_opening_dashboard.py b/erpnext/hr/doctype/job_opening/job_opening_dashboard.py index 31ef33ef2ce..a13e2a7c23a 100644 --- a/erpnext/hr/doctype/job_opening/job_opening_dashboard.py +++ b/erpnext/hr/doctype/job_opening/job_opening_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/job_opening/test_job_opening.py b/erpnext/hr/doctype/job_opening/test_job_opening.py index 815ce5bdb8c..a66975c91ed 100644 --- a/erpnext/hr/doctype/job_opening/test_job_opening.py +++ b/erpnext/hr/doctype/job_opening/test_job_opening.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Job Opening') diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py index 4757cd3b192..e4886d7ae72 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py @@ -2,13 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt, date_diff, formatdate, add_days, today, getdate from frappe import _ from frappe.model.document import Document -from erpnext.hr.utils import set_employee_name, get_leave_period -from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import expire_allocation, create_leave_ledger_entry +from frappe.utils import add_days, date_diff, flt, formatdate, getdate + from erpnext.hr.doctype.leave_application.leave_application import get_approved_leaves_for_period +from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import ( + create_leave_ledger_entry, + expire_allocation, +) +from erpnext.hr.utils import get_leave_period, set_employee_name + class OverlapError(frappe.ValidationError): pass class BackDatedAllocationError(frappe.ValidationError): pass diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py b/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py index 7a063d92eac..84423bd2b45 100644 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py index bff06e6a91c..b1850562e3a 100644 --- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py @@ -1,10 +1,14 @@ from __future__ import unicode_literals -import frappe -import erpnext + import unittest -from frappe.utils import nowdate, add_months, getdate, add_days + +import frappe +from frappe.utils import add_days, add_months, getdate, nowdate + +import erpnext +from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type -from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation, expire_allocation + class TestLeaveAllocation(unittest.TestCase): @classmethod diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 2e37c135947..9e6fc6d0f14 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -2,14 +2,33 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, get_fullname, add_days, nowdate -from erpnext.hr.utils import set_employee_name, get_leave_period, share_doc_with_approver, validate_active_employee -from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates -from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee +from frappe.utils import ( + add_days, + cint, + cstr, + date_diff, + flt, + formatdate, + get_fullname, + get_link_to_form, + getdate, + nowdate, +) + from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import daterange +from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee +from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry +from erpnext.hr.utils import ( + get_leave_period, + set_employee_name, + share_doc_with_approver, + validate_active_employee, +) + class LeaveDayBlockedError(frappe.ValidationError): pass class OverlapError(frappe.ValidationError): pass @@ -17,6 +36,8 @@ class AttendanceAlreadyMarkedError(frappe.ValidationError): pass class NotAnOptionalHoliday(frappe.ValidationError): pass from frappe.model.document import Document + + class LeaveApplication(Document): def get_feed(self): return _("{0}: From {0} of type {1}").format(self.employee_name, self.leave_type) diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 2832e2fad3b..b9c785a8a9c 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -2,16 +2,24 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError, NotAnOptionalHoliday, get_leave_balance_on +import frappe from frappe.permissions import clear_user_permissions_for_doctype -from frappe.utils import add_days, nowdate, now_datetime, getdate, add_months -from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type -from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation -from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees +from frappe.utils import add_days, add_months, getdate, nowdate + from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation +from erpnext.hr.doctype.leave_application.leave_application import ( + LeaveDayBlockedError, + NotAnOptionalHoliday, + OverlapError, + get_leave_balance_on, +) +from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import ( + create_assignment_for_multiple_employees, +) +from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type test_dependencies = ["Leave Allocation", "Leave Block List", "Employee"] diff --git a/erpnext/hr/doctype/leave_block_list/leave_block_list.py b/erpnext/hr/doctype/leave_block_list/leave_block_list.py index 9cb9fc05cee..9ba079c6e1f 100644 --- a/erpnext/hr/doctype/leave_block_list/leave_block_list.py +++ b/erpnext/hr/doctype/leave_block_list/leave_block_list.py @@ -4,10 +4,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class LeaveBlockList(Document): def validate(self): diff --git a/erpnext/hr/doctype/leave_block_list/leave_block_list_dashboard.py b/erpnext/hr/doctype/leave_block_list/leave_block_list_dashboard.py index 45aa4915bc6..30e7572c383 100644 --- a/erpnext/hr/doctype/leave_block_list/leave_block_list_dashboard.py +++ b/erpnext/hr/doctype/leave_block_list/leave_block_list_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'leave_block_list', diff --git a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py b/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py index 0eb69a55a70..dd90e4f9eea 100644 --- a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py +++ b/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe from frappe.utils import getdate + from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates + class TestLeaveBlockList(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") diff --git a/erpnext/hr/doctype/leave_block_list_allow/leave_block_list_allow.py b/erpnext/hr/doctype/leave_block_list_allow/leave_block_list_allow.py index 8e5a09e01ec..2f648470f73 100644 --- a/erpnext/hr/doctype/leave_block_list_allow/leave_block_list_allow.py +++ b/erpnext/hr/doctype/leave_block_list_allow/leave_block_list_allow.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class LeaveBlockListAllow(Document): pass diff --git a/erpnext/hr/doctype/leave_block_list_date/leave_block_list_date.py b/erpnext/hr/doctype/leave_block_list_date/leave_block_list_date.py index 54978a1e83a..4a8f45dbcd1 100644 --- a/erpnext/hr/doctype/leave_block_list_date/leave_block_list_date.py +++ b/erpnext/hr/doctype/leave_block_list_date/leave_block_list_date.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class LeaveBlockListDate(Document): pass diff --git a/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py b/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py index 74014020fc6..681a5e27943 100644 --- a/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py +++ b/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import cint, cstr, flt, nowdate, comma_and, date_diff -from frappe import msgprint, _ +import frappe +from frappe import _, msgprint from frappe.model.document import Document +from frappe.utils import cint, comma_and, cstr, flt + class LeaveControlPanel(Document): def get_employees(self): @@ -51,7 +52,7 @@ class LeaveControlPanel(Document): la.docstatus = 1 la.save() leave_allocated_for.append(d[0]) - except: + except Exception: pass if leave_allocated_for: msgprint(_("Leaves Allocated Successfully for {0}").format(comma_and(leave_allocated_for))) diff --git a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.py b/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.py index 9a907c885ac..f64b2334e86 100644 --- a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.py +++ b/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestLeaveControlPanel(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py index d136210a043..7656abfa45e 100644 --- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py +++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py @@ -3,14 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import getdate, nowdate, flt -from erpnext.hr.utils import set_employee_name, validate_active_employee -from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure -from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry +from frappe.utils import getdate, nowdate + from erpnext.hr.doctype.leave_allocation.leave_allocation import get_unused_leaves +from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry +from erpnext.hr.utils import set_employee_name, validate_active_employee +from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import ( + get_assigned_salary_structure, +) + class LeaveEncashment(Document): def validate(self): diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py index c1da8b47ffa..762745b88f4 100644 --- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py +++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py @@ -3,14 +3,18 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import today, add_months + +import frappe +from frappe.utils import add_months, today + from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period -from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees -from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy\ +from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy +from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import ( + create_assignment_for_multiple_employees, +) +from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure test_dependencies = ["Leave Type"] diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py index 33a6243e609..6cf96851556 100644 --- a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py +++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import add_days, today, flt, DATE_FORMAT, getdate +from frappe.model.document import Document +from frappe.utils import DATE_FORMAT, flt, getdate, today + class LeaveLedgerEntry(Document): def validate(self): diff --git a/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py b/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py index 6f7725c254e..5fa419da43c 100644 --- a/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py +++ b/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLeaveLedgerEntry(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py index 28a33f6fac8..143d23ab14b 100644 --- a/erpnext/hr/doctype/leave_period/leave_period.py +++ b/erpnext/hr/doctype/leave_period/leave_period.py @@ -3,12 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate, cstr, add_days, date_diff, getdate, ceil from frappe.model.document import Document +from frappe.utils import getdate + from erpnext.hr.utils import validate_overlap -from frappe.utils.background_jobs import enqueue + class LeavePeriod(Document): diff --git a/erpnext/hr/doctype/leave_period/leave_period_dashboard.py b/erpnext/hr/doctype/leave_period/leave_period_dashboard.py index 7c2c9632d85..a64c63af867 100644 --- a/erpnext/hr/doctype/leave_period/leave_period_dashboard.py +++ b/erpnext/hr/doctype/leave_period/leave_period_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'leave_period', diff --git a/erpnext/hr/doctype/leave_period/test_leave_period.py b/erpnext/hr/doctype/leave_period/test_leave_period.py index cbb34371fc9..5c5ae133a13 100644 --- a/erpnext/hr/doctype/leave_period/test_leave_period.py +++ b/erpnext/hr/doctype/leave_period/test_leave_period.py @@ -3,9 +3,12 @@ # See license.txt from __future__ import unicode_literals -import frappe, erpnext import unittest +import frappe + +import erpnext + test_dependencies = ["Employee", "Leave Type", "Leave Policy"] class TestLeavePeriod(unittest.TestCase): diff --git a/erpnext/hr/doctype/leave_policy/leave_policy.py b/erpnext/hr/doctype/leave_policy/leave_policy.py index 964a5de83ec..b11459d8155 100644 --- a/erpnext/hr/doctype/leave_policy/leave_policy.py +++ b/erpnext/hr/doctype/leave_policy/leave_policy.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class LeavePolicy(Document): def validate(self): if self.leave_policy_details: diff --git a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py index 474f3a77ad0..76f886c73eb 100644 --- a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py +++ b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'leave_policy', diff --git a/erpnext/hr/doctype/leave_policy/test_leave_policy.py b/erpnext/hr/doctype/leave_policy/test_leave_policy.py index af7567b5bc7..b0743f535bf 100644 --- a/erpnext/hr/doctype/leave_policy/test_leave_policy.py +++ b/erpnext/hr/doctype/leave_policy/test_leave_policy.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestLeavePolicy(unittest.TestCase): def test_max_leave_allowed(self): random_leave_type = frappe.get_all("Leave Type", fields=["name", "max_leaves_allowed"]) diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py index d7cb1c88c92..f62b3002194 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py @@ -3,14 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document -from frappe import _, bold -from frappe.utils import getdate, date_diff, comma_and, formatdate, get_datetime, flt -from math import ceil + import json +from math import ceil + +import frappe +from frappe import _, bold +from frappe.model.document import Document +from frappe.utils import date_diff, flt, formatdate, get_datetime, getdate from six import string_types + class LeavePolicyAssignment(Document): def validate(self): diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py index a2f7f5866b7..79142a63429 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'leave_policy_assignment', diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py index 0089804f512..cbb26a1e285 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py +++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py @@ -3,11 +3,18 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.hr.doctype.leave_application.test_leave_application import get_leave_period, get_employee -from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees + +import frappe + +from erpnext.hr.doctype.leave_application.test_leave_application import ( + get_employee, + get_leave_period, +) from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy +from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import ( + create_assignment_for_multiple_employees, +) test_dependencies = ["Employee"] diff --git a/erpnext/hr/doctype/leave_policy_detail/leave_policy_detail.py b/erpnext/hr/doctype/leave_policy_detail/leave_policy_detail.py index c103f08cd97..f889424ee51 100644 --- a/erpnext/hr/doctype/leave_policy_detail/leave_policy_detail.py +++ b/erpnext/hr/doctype/leave_policy_detail/leave_policy_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LeavePolicyDetail(Document): pass diff --git a/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.py b/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.py index 610b1fa332e..4cf9db26a2d 100644 --- a/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.py +++ b/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestLeavePolicyDetail(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/leave_type/leave_type.py b/erpnext/hr/doctype/leave_type/leave_type.py index 21f180b857d..195c8587b97 100644 --- a/erpnext/hr/doctype/leave_type/leave_type.py +++ b/erpnext/hr/doctype/leave_type/leave_type.py @@ -2,13 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import calendar -import frappe -from datetime import datetime -from frappe.utils import today -from frappe import _ +import frappe +from frappe import _ from frappe.model.document import Document +from frappe.utils import today + class LeaveType(Document): def validate(self): diff --git a/erpnext/hr/doctype/leave_type/leave_type_dashboard.py b/erpnext/hr/doctype/leave_type/leave_type_dashboard.py index c8944fcb9e2..773d4e88beb 100644 --- a/erpnext/hr/doctype/leave_type/leave_type_dashboard.py +++ b/erpnext/hr/doctype/leave_type/leave_type_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'leave_type', diff --git a/erpnext/hr/doctype/leave_type/test_leave_type.py b/erpnext/hr/doctype/leave_type/test_leave_type.py index 048dddd3ef9..ee8db743f2a 100644 --- a/erpnext/hr/doctype/leave_type/test_leave_type.py +++ b/erpnext/hr/doctype/leave_type/test_leave_type.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -from frappe import _ test_records = frappe.get_test_records('Leave Type') diff --git a/erpnext/hr/doctype/offer_term/offer_term.py b/erpnext/hr/doctype/offer_term/offer_term.py index 6a632011060..5f8f591c97c 100644 --- a/erpnext/hr/doctype/offer_term/offer_term.py +++ b/erpnext/hr/doctype/offer_term/offer_term.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class OfferTerm(Document): pass diff --git a/erpnext/hr/doctype/offer_term/test_offer_term.py b/erpnext/hr/doctype/offer_term/test_offer_term.py index d0dd14d1e62..ec7edd44c6f 100644 --- a/erpnext/hr/doctype/offer_term/test_offer_term.py +++ b/erpnext/hr/doctype/offer_term/test_offer_term.py @@ -2,7 +2,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Offer Term') diff --git a/erpnext/hr/doctype/purpose_of_travel/purpose_of_travel.py b/erpnext/hr/doctype/purpose_of_travel/purpose_of_travel.py index 62f62a5c249..f66fd276a56 100644 --- a/erpnext/hr/doctype/purpose_of_travel/purpose_of_travel.py +++ b/erpnext/hr/doctype/purpose_of_travel/purpose_of_travel.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PurposeofTravel(Document): pass diff --git a/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.py b/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.py index ccd950dff3a..b33f389a48b 100644 --- a/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.py +++ b/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestPurposeofTravel(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.py b/erpnext/hr/doctype/shift_assignment/shift_assignment.py index 89ae4d535d4..69af5c54c3b 100644 --- a/erpnext/hr/doctype/shift_assignment/shift_assignment.py +++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.py @@ -3,14 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from datetime import datetime, timedelta + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, now_datetime, nowdate +from frappe.utils import cstr, getdate, now_datetime, nowdate + from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday from erpnext.hr.utils import validate_active_employee -from datetime import timedelta, datetime + class ShiftAssignment(Document): def validate(self): diff --git a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py index 07d92fe61d6..84003e2ec28 100644 --- a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py +++ b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, add_days + +import frappe +from frappe.utils import add_days, nowdate test_dependencies = ["Shift Type"] diff --git a/erpnext/hr/doctype/shift_request/shift_request.py b/erpnext/hr/doctype/shift_request/shift_request.py index 2731da125a8..a6ac7c83aeb 100644 --- a/erpnext/hr/doctype/shift_request/shift_request.py +++ b/erpnext/hr/doctype/shift_request/shift_request.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import formatdate, getdate + from erpnext.hr.utils import share_doc_with_approver, validate_active_employee + class OverlapError(frappe.ValidationError): pass class ShiftRequest(Document): diff --git a/erpnext/hr/doctype/shift_request/shift_request_dashboard.py b/erpnext/hr/doctype/shift_request/shift_request_dashboard.py index f70b61a20a6..3ceafc0cefe 100644 --- a/erpnext/hr/doctype/shift_request/shift_request_dashboard.py +++ b/erpnext/hr/doctype/shift_request/shift_request_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/shift_request/test_shift_request.py b/erpnext/hr/doctype/shift_request/test_shift_request.py index 60b7676e251..7b4a3ca5aab 100644 --- a/erpnext/hr/doctype/shift_request/test_shift_request.py +++ b/erpnext/hr/doctype/shift_request/test_shift_request.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, add_days + +import frappe +from frappe.utils import add_days, nowdate + from erpnext.hr.doctype.employee.test_employee import make_employee test_dependencies = ["Shift Type"] diff --git a/erpnext/hr/doctype/shift_type/shift_type.py b/erpnext/hr/doctype/shift_type/shift_type.py index d5fdda80944..e53373df279 100644 --- a/erpnext/hr/doctype/shift_type/shift_type.py +++ b/erpnext/hr/doctype/shift_type/shift_type.py @@ -3,16 +3,25 @@ # For license information, please see license.txt from __future__ import unicode_literals + import itertools from datetime import timedelta import frappe from frappe.model.document import Document -from frappe.utils import cint, getdate, get_datetime -from erpnext.hr.doctype.shift_assignment.shift_assignment import get_actual_start_end_datetime_of_shift, get_employee_shift -from erpnext.hr.doctype.employee_checkin.employee_checkin import mark_attendance_and_link_log, calculate_working_hours +from frappe.utils import cint, get_datetime, getdate + from erpnext.hr.doctype.attendance.attendance import mark_attendance from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee +from erpnext.hr.doctype.employee_checkin.employee_checkin import ( + calculate_working_hours, + mark_attendance_and_link_log, +) +from erpnext.hr.doctype.shift_assignment.shift_assignment import ( + get_actual_start_end_datetime_of_shift, + get_employee_shift, +) + class ShiftType(Document): @frappe.whitelist() diff --git a/erpnext/hr/doctype/shift_type/shift_type_dashboard.py b/erpnext/hr/doctype/shift_type/shift_type_dashboard.py index aedd190bcb4..b78c69a2a1e 100644 --- a/erpnext/hr/doctype/shift_type/shift_type_dashboard.py +++ b/erpnext/hr/doctype/shift_type/shift_type_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/shift_type/test_shift_type.py b/erpnext/hr/doctype/shift_type/test_shift_type.py index bc4f0eafcd5..699030f2196 100644 --- a/erpnext/hr/doctype/shift_type/test_shift_type.py +++ b/erpnext/hr/doctype/shift_type/test_shift_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestShiftType(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/skill/skill.py b/erpnext/hr/doctype/skill/skill.py index 8d242120753..ebaa410fbdd 100644 --- a/erpnext/hr/doctype/skill/skill.py +++ b/erpnext/hr/doctype/skill/skill.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class Skill(Document): pass diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py index e6c783aca22..57a92b05871 100644 --- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py @@ -3,12 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import getdate, nowdate, cint, flt +from frappe.model.document import Document +from frappe.utils import cint, flt, getdate, nowdate from frappe.utils.nestedset import get_descendants_of + class SubsidiaryCompanyError(frappe.ValidationError): pass class ParentCompanyError(frappe.ValidationError): pass diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan_dashboard.py b/erpnext/hr/doctype/staffing_plan/staffing_plan_dashboard.py index 8e89d53c8e0..24ae1223440 100644 --- a/erpnext/hr/doctype/staffing_plan/staffing_plan_dashboard.py +++ b/erpnext/hr/doctype/staffing_plan/staffing_plan_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py index 1c6218e9a70..4517cba2335 100644 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py @@ -3,11 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.hr.doctype.staffing_plan.staffing_plan import SubsidiaryCompanyError -from erpnext.hr.doctype.staffing_plan.staffing_plan import ParentCompanyError -from frappe.utils import nowdate, add_days + +import frappe +from frappe.utils import add_days, nowdate + +from erpnext.hr.doctype.staffing_plan.staffing_plan import ( + ParentCompanyError, + SubsidiaryCompanyError, +) test_dependencies = ["Designation"] diff --git a/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.py b/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.py index 28a651e72d8..ea89df3ba6e 100644 --- a/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.py +++ b/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StaffingPlanDetail(Document): pass diff --git a/erpnext/hr/doctype/training_event/test_training_event.py b/erpnext/hr/doctype/training_event/test_training_event.py index 6a275b330c0..ed44fa60704 100644 --- a/erpnext/hr/doctype/training_event/test_training_event.py +++ b/erpnext/hr/doctype/training_event/test_training_event.py @@ -3,11 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import today, add_days + +import frappe +from frappe.utils import add_days, today + from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee + class TestTrainingEvent(unittest.TestCase): def setUp(self): create_training_program("Basic Training") diff --git a/erpnext/hr/doctype/training_event/training_event.py b/erpnext/hr/doctype/training_event/training_event.py index e2c30cb3145..9b01d3d9026 100644 --- a/erpnext/hr/doctype/training_event/training_event.py +++ b/erpnext/hr/doctype/training_event/training_event.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document from frappe.utils import time_diff_in_seconds + from erpnext.hr.doctype.employee.employee import get_employee_emails + class TrainingEvent(Document): def validate(self): self.set_employee_emails() diff --git a/erpnext/hr/doctype/training_event/training_event_dashboard.py b/erpnext/hr/doctype/training_event/training_event_dashboard.py index 19afd8dd6e1..a917c8744f7 100644 --- a/erpnext/hr/doctype/training_event/training_event_dashboard.py +++ b/erpnext/hr/doctype/training_event/training_event_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/hr/doctype/training_event_employee/training_event_employee.py b/erpnext/hr/doctype/training_event_employee/training_event_employee.py index 234e958a212..089235507a2 100644 --- a/erpnext/hr/doctype/training_event_employee/training_event_employee.py +++ b/erpnext/hr/doctype/training_event_employee/training_event_employee.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TrainingEventEmployee(Document): pass diff --git a/erpnext/hr/doctype/training_feedback/test_training_feedback.py b/erpnext/hr/doctype/training_feedback/test_training_feedback.py index 4c0c18029d0..a9bf6d6bbde 100644 --- a/erpnext/hr/doctype/training_feedback/test_training_feedback.py +++ b/erpnext/hr/doctype/training_feedback/test_training_feedback.py @@ -3,10 +3,17 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + +from erpnext.hr.doctype.training_event.test_training_event import ( + create_training_event, + create_training_program, +) from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee -from erpnext.hr.doctype.training_event.test_training_event import create_training_program, create_training_event + + class TestTrainingFeedback(unittest.TestCase): def setUp(self): create_training_program("Basic Training") diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.py b/erpnext/hr/doctype/training_feedback/training_feedback.py index 3d4b9b3ea96..6a41a657cea 100644 --- a/erpnext/hr/doctype/training_feedback/training_feedback.py +++ b/erpnext/hr/doctype/training_feedback/training_feedback.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class TrainingFeedback(Document): def validate(self): diff --git a/erpnext/hr/doctype/training_program/test_training_program.py b/erpnext/hr/doctype/training_program/test_training_program.py index 9d5b28616b1..aec319f4077 100644 --- a/erpnext/hr/doctype/training_program/test_training_program.py +++ b/erpnext/hr/doctype/training_program/test_training_program.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestTrainingProgram(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/training_program/training_program.py b/erpnext/hr/doctype/training_program/training_program.py index 7a3720b66b6..6f3ab5a806f 100644 --- a/erpnext/hr/doctype/training_program/training_program.py +++ b/erpnext/hr/doctype/training_program/training_program.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class TrainingProgram(Document): pass diff --git a/erpnext/hr/doctype/training_program/training_program_dashboard.py b/erpnext/hr/doctype/training_program/training_program_dashboard.py index 0fc18a80298..b2eed6895ca 100644 --- a/erpnext/hr/doctype/training_program/training_program_dashboard.py +++ b/erpnext/hr/doctype/training_program/training_program_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'training_program', diff --git a/erpnext/hr/doctype/training_result/test_training_result.py b/erpnext/hr/doctype/training_result/test_training_result.py index 29ed2a0ff38..17ccc4b4eef 100644 --- a/erpnext/hr/doctype/training_result/test_training_result.py +++ b/erpnext/hr/doctype/training_result/test_training_result.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Training Result') diff --git a/erpnext/hr/doctype/training_result/training_result.py b/erpnext/hr/doctype/training_result/training_result.py index 7cdc51f8010..9cfc5707cac 100644 --- a/erpnext/hr/doctype/training_result/training_result.py +++ b/erpnext/hr/doctype/training_result/training_result.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + from erpnext.hr.doctype.employee.employee import get_employee_emails + class TrainingResult(Document): def validate(self): training_event = frappe.get_doc("Training Event", self.training_event) diff --git a/erpnext/hr/doctype/training_result_employee/training_result_employee.py b/erpnext/hr/doctype/training_result_employee/training_result_employee.py index 54e2a18260a..b0d4605910c 100644 --- a/erpnext/hr/doctype/training_result_employee/training_result_employee.py +++ b/erpnext/hr/doctype/training_result_employee/training_result_employee.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TrainingResultEmployee(Document): pass diff --git a/erpnext/hr/doctype/travel_itinerary/travel_itinerary.py b/erpnext/hr/doctype/travel_itinerary/travel_itinerary.py index 0b369beb134..467ef16aaee 100644 --- a/erpnext/hr/doctype/travel_itinerary/travel_itinerary.py +++ b/erpnext/hr/doctype/travel_itinerary/travel_itinerary.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TravelItinerary(Document): pass diff --git a/erpnext/hr/doctype/travel_request/test_travel_request.py b/erpnext/hr/doctype/travel_request/test_travel_request.py index dac5517aab0..95bf8b9c8bc 100644 --- a/erpnext/hr/doctype/travel_request/test_travel_request.py +++ b/erpnext/hr/doctype/travel_request/test_travel_request.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestTravelRequest(unittest.TestCase): pass diff --git a/erpnext/hr/doctype/travel_request/travel_request.py b/erpnext/hr/doctype/travel_request/travel_request.py index 60834d3f4a6..b10333fd2d6 100644 --- a/erpnext/hr/doctype/travel_request/travel_request.py +++ b/erpnext/hr/doctype/travel_request/travel_request.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + from erpnext.hr.utils import validate_active_employee + class TravelRequest(Document): def validate(self): validate_active_employee(self.employee) diff --git a/erpnext/hr/doctype/travel_request_costing/travel_request_costing.py b/erpnext/hr/doctype/travel_request_costing/travel_request_costing.py index 9fa85e84c28..9b38d888fcb 100644 --- a/erpnext/hr/doctype/travel_request_costing/travel_request_costing.py +++ b/erpnext/hr/doctype/travel_request_costing/travel_request_costing.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TravelRequestCosting(Document): pass diff --git a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py index 03b0cf3da21..e0a776c45d0 100644 --- a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py +++ b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py @@ -3,12 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -import erpnext + +import frappe from frappe.utils import getdate -from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data + +import erpnext from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data test_dependencies = ['Holiday List'] diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py index 9c765d73716..030ecec74f9 100644 --- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py +++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py @@ -4,14 +4,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cstr, add_days, date_diff, getdate from frappe import _ -from frappe.utils.csvutils import UnicodeWriter from frappe.model.document import Document +from frappe.utils import add_days, cstr, date_diff, getdate +from frappe.utils.csvutils import UnicodeWriter + from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.hr.utils import get_holiday_dates_for_employee + class UploadAttendance(Document): pass diff --git a/erpnext/hr/doctype/vehicle/test_vehicle.py b/erpnext/hr/doctype/vehicle/test_vehicle.py index ff3429d0e7e..2bc94c65090 100644 --- a/erpnext/hr/doctype/vehicle/test_vehicle.py +++ b/erpnext/hr/doctype/vehicle/test_vehicle.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate,flt, cstr,random_string + +import frappe +from frappe.utils import random_string + # test_records = frappe.get_test_records('Vehicle') class TestVehicle(unittest.TestCase): diff --git a/erpnext/hr/doctype/vehicle/vehicle.py b/erpnext/hr/doctype/vehicle/vehicle.py index 1df50682683..2ff190426dd 100644 --- a/erpnext/hr/doctype/vehicle/vehicle.py +++ b/erpnext/hr/doctype/vehicle/vehicle.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate from frappe.model.document import Document +from frappe.utils import getdate + class Vehicle(Document): def validate(self): diff --git a/erpnext/hr/doctype/vehicle/vehicle_dashboard.py b/erpnext/hr/doctype/vehicle/vehicle_dashboard.py index 628c8972cec..6a01bcffd50 100644 --- a/erpnext/hr/doctype/vehicle/vehicle_dashboard.py +++ b/erpnext/hr/doctype/vehicle/vehicle_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py index ed02120cca3..1b0bfcb08f9 100644 --- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py @@ -3,12 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, flt, cstr, random_string + +import frappe +from frappe.utils import cstr, flt, nowdate, random_string + from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.hr.doctype.vehicle_log.vehicle_log import make_expense_claim + class TestVehicleLog(unittest.TestCase): def setUp(self): employee_id = frappe.db.sql("""select name from `tabEmployee` where name='testdriver@example.com'""") diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py index 04c94e37d5a..73c848b0346 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py @@ -3,11 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, cstr -from frappe.model.mapper import get_mapped_doc from frappe.model.document import Document +from frappe.utils import flt + class VehicleLog(Document): def validate(self): diff --git a/erpnext/hr/doctype/vehicle_service/vehicle_service.py b/erpnext/hr/doctype/vehicle_service/vehicle_service.py index 18ed7821382..bc93a97481d 100644 --- a/erpnext/hr/doctype/vehicle_service/vehicle_service.py +++ b/erpnext/hr/doctype/vehicle_service/vehicle_service.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class VehicleService(Document): pass diff --git a/erpnext/hr/notification/training_feedback/training_feedback.py b/erpnext/hr/notification/training_feedback/training_feedback.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/hr/notification/training_feedback/training_feedback.py +++ b/erpnext/hr/notification/training_feedback/training_feedback.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.py b/erpnext/hr/notification/training_scheduled/training_scheduled.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/hr/notification/training_scheduled/training_scheduled.py +++ b/erpnext/hr/notification/training_scheduled/training_scheduled.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/hr/page/organizational_chart/organizational_chart.js b/erpnext/hr/page/organizational_chart/organizational_chart.js index b6fcc6014bd..26a5e48ff20 100644 --- a/erpnext/hr/page/organizational_chart/organizational_chart.js +++ b/erpnext/hr/page/organizational_chart/organizational_chart.js @@ -15,6 +15,8 @@ frappe.pages['organizational-chart'].on_page_load = function(wrapper) { } else { organizational_chart = new erpnext.HierarchyChart('Employee', wrapper, method); } + + frappe.breadcrumbs.add('HR'); organizational_chart.show(); }); }); diff --git a/erpnext/hr/page/organizational_chart/organizational_chart.py b/erpnext/hr/page/organizational_chart/organizational_chart.py index 4423d29e402..1baf805f4b9 100644 --- a/erpnext/hr/page/organizational_chart/organizational_chart.py +++ b/erpnext/hr/page/organizational_chart/organizational_chart.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + @frappe.whitelist() def get_children(parent=None, company=None, exclude_node=None): filters = [['status', '!=', 'Left']] diff --git a/erpnext/hr/page/team_updates/team_updates.py b/erpnext/hr/page/team_updates/team_updates.py index 58cdc4b7e1d..a5e7c44c31d 100644 --- a/erpnext/hr/page/team_updates/team_updates.py +++ b/erpnext/hr/page/team_updates/team_updates.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe from email_reply_parser import EmailReplyParser + @frappe.whitelist() def get_data(start=0): #frappe.only_for('Employee', 'System Manager') diff --git a/erpnext/hr/report/daily_work_summary_replies/daily_work_summary_replies.py b/erpnext/hr/report/daily_work_summary_replies/daily_work_summary_replies.py index d8691b4d025..62ffb7d3445 100644 --- a/erpnext/hr/report/daily_work_summary_replies/daily_work_summary_replies.py +++ b/erpnext/hr/report/daily_work_summary_replies/daily_work_summary_replies.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe import _ + import frappe +from frappe import _ + from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_user_emails_from_group + def execute(filters=None): if not filters.group: return [], [] columns, data = get_columns(), get_data(filters) diff --git a/erpnext/hr/report/employee_advance_summary/employee_advance_summary.py b/erpnext/hr/report/employee_advance_summary/employee_advance_summary.py index 363e31d0960..d0c295df9f1 100644 --- a/erpnext/hr/report/employee_advance_summary/employee_advance_summary.py +++ b/erpnext/hr/report/employee_advance_summary/employee_advance_summary.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _, msgprint + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/hr/report/employee_analytics/employee_analytics.py b/erpnext/hr/report/employee_analytics/employee_analytics.py index fe77b6abc96..725c5a15713 100644 --- a/erpnext/hr/report/employee_analytics/employee_analytics.py +++ b/erpnext/hr/report/employee_analytics/employee_analytics.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/hr/report/employee_birthday/employee_birthday.py b/erpnext/hr/report/employee_birthday/employee_birthday.py index e8d78449bff..b284e6babe6 100644 --- a/erpnext/hr/report/employee_birthday/employee_birthday.py +++ b/erpnext/hr/report/employee_birthday/employee_birthday.py @@ -2,9 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index b8953b3eaac..6bca1368d3f 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -2,12 +2,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import flt, add_days -from frappe import _ -from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on + from itertools import groupby +import frappe +from frappe import _ +from frappe.utils import add_days + +from erpnext.hr.doctype.leave_application.leave_application import ( + get_leave_balance_on, + get_leaves_for_period, +) + + def execute(filters=None): if filters.to_date <= filters.from_date: frappe.throw(_('"From Date" can not be greater than or equal to "To Date"')) diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py index 9dd7bcd8dd9..14ce9ed22a6 100644 --- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py +++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py @@ -2,14 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt -from erpnext.hr.doctype.leave_application.leave_application \ - import get_leave_details -from erpnext.hr.report.employee_leave_balance.employee_leave_balance \ - import get_department_leave_approver_map +from erpnext.hr.doctype.leave_application.leave_application import get_leave_details +from erpnext.hr.report.employee_leave_balance.employee_leave_balance import ( + get_department_leave_approver_map, +) + def execute(filters=None): leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc") @@ -65,7 +66,7 @@ def get_data(filters, leave_types): for leave_type in leave_types: remaining = 0 if leave_type in available_leave["leave_allocation"]: - # opening balance + # opening balance remaining = available_leave["leave_allocation"][leave_type]['remaining_leaves'] row += [remaining] diff --git a/erpnext/hr/report/employees_working_on_a_holiday/employees_working_on_a_holiday.py b/erpnext/hr/report/employees_working_on_a_holiday/employees_working_on_a_holiday.py index 59f56d7345f..3a268821361 100644 --- a/erpnext/hr/report/employees_working_on_a_holiday/employees_working_on_a_holiday.py +++ b/erpnext/hr/report/employees_working_on_a_holiday/employees_working_on_a_holiday.py @@ -2,6 +2,7 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py index c5929c6bf99..8c40da29ee9 100644 --- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py +++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import cstr, cint, getdate -from frappe import msgprint, _ + from calendar import monthrange +import frappe +from frappe import _, msgprint +from frappe.utils import cint, cstr, getdate + status_map = { "Absent": "A", "Half Day": "HD", diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py index 303c829eb6c..c598e9e3730 100644 --- a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py +++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py b/erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py index 26e0f26392e..2ba87efd9b2 100644 --- a/erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py +++ b/erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py @@ -2,14 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest + import frappe from frappe.utils import getdate -from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.hr.doctype.vehicle_log.vehicle_log import make_expense_claim -from erpnext.hr.doctype.vehicle_log.test_vehicle_log import get_vehicle, make_vehicle_log -from erpnext.hr.report.vehicle_expenses.vehicle_expenses import execute + from erpnext.accounts.utils import get_fiscal_year +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.vehicle_log.test_vehicle_log import get_vehicle, make_vehicle_log +from erpnext.hr.doctype.vehicle_log.vehicle_log import make_expense_claim +from erpnext.hr.report.vehicle_expenses.vehicle_expenses import execute + class TestVehicleExpenses(unittest.TestCase): @classmethod diff --git a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py index d847cbb5c9b..2be3565a059 100644 --- a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py +++ b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py @@ -2,12 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _ from frappe.utils import flt + from erpnext.accounts.report.financial_statements import get_period_list + def execute(filters=None): filters = frappe._dict(filters or {}) @@ -96,8 +98,6 @@ def get_columns(): } ] - return columns - def get_vehicle_log_data(filters): start_date, end_date = get_period_dates(filters) diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 9c936ab4ad0..3f4a0b90b56 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -1,14 +1,30 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import erpnext import frappe -from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee, InactiveEmployeeStatusError from frappe import _ from frappe.desk.form import assign_to from frappe.model.document import Document -from frappe.utils import (add_days, cstr, flt, format_datetime, formatdate, - get_datetime, getdate, nowdate, today, unique, get_link_to_form) +from frappe.utils import ( + add_days, + cstr, + flt, + format_datetime, + formatdate, + get_datetime, + get_link_to_form, + getdate, + nowdate, + today, + unique, +) + +import erpnext +from erpnext.hr.doctype.employee.employee import ( + InactiveEmployeeStatusError, + get_holiday_list_for_employee, +) + class DuplicateDeclarationError(frappe.ValidationError): pass @@ -385,6 +401,7 @@ def create_additional_leave_ledger_entry(allocation, leaves, date): def check_effective_date(from_date, to_date, frequency, based_on_date_of_joining_date): import calendar + from dateutil import relativedelta from_date = get_datetime(from_date) @@ -450,9 +467,9 @@ def get_sal_slip_total_benefit_given(employee, payroll_period, component=False): def get_holiday_dates_for_employee(employee, start_date, end_date): """return a list of holiday dates for the given employee between start_date and end_date""" - # return only date - holidays = get_holidays_for_employee(employee, start_date, end_date) - + # return only date + holidays = get_holidays_for_employee(employee, start_date, end_date) + return [cstr(h.holiday_date) for h in holidays] @@ -465,7 +482,7 @@ def get_holidays_for_employee(employee, start_date, end_date, raise_exception=Tr `raise_exception` (bool) `only_non_weekly` (bool) - return: list of dicts with `holiday_date` and `description` + return: list of dicts with `holiday_date` and `description` """ holiday_list = get_holiday_list_for_employee(employee, raise_exception=raise_exception) @@ -481,11 +498,11 @@ def get_holidays_for_employee(employee, start_date, end_date, raise_exception=Tr filters['weekly_off'] = False holidays = frappe.get_all( - 'Holiday', + 'Holiday', fields=['description', 'holiday_date'], filters=filters ) - + return holidays @erpnext.allow_regional diff --git a/erpnext/hr/web_form/job_application/job_application.py b/erpnext/hr/web_form/job_application/job_application.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/hr/web_form/job_application/job_application.py +++ b/erpnext/hr/web_form/job_application/job_application.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/hub_node/__init__.py b/erpnext/hub_node/__init__.py index 85ffe29d118..6ac3255c12a 100644 --- a/erpnext/hub_node/__init__.py +++ b/erpnext/hub_node/__init__.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe + @frappe.whitelist() def enable_hub(): hub_settings = frappe.get_doc('Marketplace Settings') diff --git a/erpnext/hub_node/api.py b/erpnext/hub_node/api.py index 42f90006f4d..55304917759 100644 --- a/erpnext/hub_node/api.py +++ b/erpnext/hub_node/api.py @@ -1,11 +1,11 @@ from __future__ import unicode_literals -import frappe import json +import frappe from frappe import _ -from frappe.frappeclient import FrappeClient from frappe.desk.form.load import get_attachments +from frappe.frappeclient import FrappeClient from six import string_types current_user = frappe.session.user diff --git a/erpnext/hub_node/doctype/hub_tracked_item/hub_tracked_item.py b/erpnext/hub_node/doctype/hub_tracked_item/hub_tracked_item.py index be2cd6b3ee9..823c79eb72b 100644 --- a/erpnext/hub_node/doctype/hub_tracked_item/hub_tracked_item.py +++ b/erpnext/hub_node/doctype/hub_tracked_item/hub_tracked_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HubTrackedItem(Document): pass diff --git a/erpnext/hub_node/doctype/hub_tracked_item/test_hub_tracked_item.py b/erpnext/hub_node/doctype/hub_tracked_item/test_hub_tracked_item.py index 92b294064fb..c403f902a2c 100644 --- a/erpnext/hub_node/doctype/hub_tracked_item/test_hub_tracked_item.py +++ b/erpnext/hub_node/doctype/hub_tracked_item/test_hub_tracked_item.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestHubTrackedItem(unittest.TestCase): pass diff --git a/erpnext/hub_node/doctype/hub_user/hub_user.py b/erpnext/hub_node/doctype/hub_user/hub_user.py index de43f4e0c04..1f7c8fc3f20 100644 --- a/erpnext/hub_node/doctype/hub_user/hub_user.py +++ b/erpnext/hub_node/doctype/hub_user/hub_user.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HubUser(Document): pass diff --git a/erpnext/hub_node/doctype/hub_users/hub_users.py b/erpnext/hub_node/doctype/hub_users/hub_users.py index 440be14c0bf..e08ed68ed8f 100644 --- a/erpnext/hub_node/doctype/hub_users/hub_users.py +++ b/erpnext/hub_node/doctype/hub_users/hub_users.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HubUsers(Document): pass diff --git a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py index 91c7bf5850a..af2ff37797e 100644 --- a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py +++ b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py @@ -1,15 +1,13 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors and contributors # For license information, please see license.txt -from __future__ import unicode_literals -import frappe, requests, json, time +import json -from frappe.model.document import Document -from frappe.utils import add_years, now, get_datetime, get_datetime_str, cint -from frappe import _ +import frappe from frappe.frappeclient import FrappeClient -from erpnext.utilities.product import get_price, get_qty_in_stock -from six import string_types +from frappe.model.document import Document +from frappe.utils import cint + class MarketplaceSettings(Document): @@ -83,7 +81,6 @@ class MarketplaceSettings(Document): def unregister(self): """Disable the User on hubmarket.org""" - pass @frappe.whitelist() def is_marketplace_enabled(): diff --git a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py index 549b9914c34..7922f45ab59 100644 --- a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py +++ b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestMarketplaceSettings(unittest.TestCase): pass diff --git a/erpnext/hub_node/legacy.py b/erpnext/hub_node/legacy.py index b61b88bf078..2e4c2668436 100644 --- a/erpnext/hub_node/legacy.py +++ b/erpnext/hub_node/legacy.py @@ -1,9 +1,13 @@ from __future__ import unicode_literals -import frappe, json -from frappe.utils import nowdate -from frappe.frappeclient import FrappeClient -from frappe.utils.nestedset import get_root_of + +import json + +import frappe from frappe.contacts.doctype.contact.contact import get_default_contact +from frappe.frappeclient import FrappeClient +from frappe.utils import nowdate +from frappe.utils.nestedset import get_root_of + def get_list(doctype, start, limit, fields, filters, order_by): pass diff --git a/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py b/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py index 6ce2a54b190..0911e8f49bb 100644 --- a/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py +++ b/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py @@ -2,12 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils.dashboard import cache_source -from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure \ - import get_loan_security_details from six import iteritems +from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure import ( + get_loan_security_details, +) + + @frappe.whitelist() @cache_source def get_data(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index ff7fbbdf49a..7dbd42297e1 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -3,14 +3,22 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, math, json -import erpnext + +import json +import math + +import frappe from frappe import _ +from frappe.utils import add_months, flt, getdate, now_datetime, nowdate from six import string_types -from frappe.utils import flt, rounded, add_months, nowdate, getdate, now_datetime -from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty + +import erpnext from erpnext.controllers.accounts_controller import AccountsController from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts +from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import ( + get_pledged_security_qty, +) + class Loan(AccountsController): def validate(self): @@ -361,7 +369,9 @@ def create_loan_security_unpledge(unpledge_map, loan, company, applicant_type, a return unpledge_request def validate_employee_currency_with_company_currency(applicant, company): - from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_employee_currency + from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import ( + get_employee_currency, + ) if not applicant: frappe.throw(_("Please select Applicant")) if not company: diff --git a/erpnext/loan_management/doctype/loan/loan_dashboard.py b/erpnext/loan_management/doctype/loan/loan_dashboard.py index 711a7829baf..28ccc03b684 100644 --- a/erpnext/loan_management/doctype/loan/loan_dashboard.py +++ b/erpnext/loan_management/doctype/loan/loan_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index 122d7236051..ec0aebbb8a4 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -3,23 +3,40 @@ # See license.txt from __future__ import unicode_literals -import frappe -import erpnext import unittest -from frappe.utils import (nowdate, add_days, getdate, now_datetime, add_to_date, get_datetime, - add_months, get_first_day, get_last_day, flt, date_diff) -from erpnext.selling.doctype.customer.test_customer import get_customer_dict -from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import (process_loan_interest_accrual_for_demand_loans, - process_loan_interest_accrual_for_term_loans) -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year -from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import create_process_loan_security_shortfall -from erpnext.loan_management.doctype.loan.loan import unpledge_security, request_loan_closure, make_loan_write_off -from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty + +import frappe +from frappe.utils import add_days, add_months, add_to_date, date_diff, flt, get_datetime, nowdate + +from erpnext.loan_management.doctype.loan.loan import ( + make_loan_write_off, + request_loan_closure, + unpledge_security, +) from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge -from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import get_disbursal_amount +from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import ( + get_disbursal_amount, +) +from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import ( + days_in_year, +) from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts -from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure +from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import ( + get_pledged_security_qty, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_demand_loans, + process_loan_interest_accrual_for_term_loans, +) +from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import ( + create_process_loan_security_shortfall, +) +from erpnext.payroll.doctype.salary_structure.test_salary_structure import ( + make_employee, + make_salary_structure, +) +from erpnext.selling.doctype.customer.test_customer import get_customer_dict + class TestLoan(unittest.TestCase): def setUp(self): diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py index d8f3577b2c3..e492920abb3 100644 --- a/erpnext/loan_management/doctype/loan_application/loan_application.py +++ b/erpnext/loan_management/doctype/loan_application/loan_application.py @@ -3,17 +3,28 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, math -from frappe import _ -from frappe.utils import flt, rounded, cint -from frappe.model.mapper import get_mapped_doc -from frappe.model.document import Document -from erpnext.loan_management.doctype.loan.loan import (get_monthly_repayment_amount, validate_repayment_method, - get_total_loan_amount, get_sanctioned_amount_limit) -from erpnext.loan_management.doctype.loan_security_price.loan_security_price import get_loan_security_price + import json +import math + +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, flt, rounded from six import string_types +from erpnext.loan_management.doctype.loan.loan import ( + get_monthly_repayment_amount, + get_sanctioned_amount_limit, + get_total_loan_amount, + validate_repayment_method, +) +from erpnext.loan_management.doctype.loan_security_price.loan_security_price import ( + get_loan_security_price, +) + + class LoanApplication(Document): def validate(self): self.set_pledge_amount() diff --git a/erpnext/loan_management/doctype/loan_application/loan_application_dashboard.py b/erpnext/loan_management/doctype/loan_application/loan_application_dashboard.py index 3975adf4431..992d6699747 100644 --- a/erpnext/loan_management/doctype/loan_application/loan_application_dashboard.py +++ b/erpnext/loan_management/doctype/loan_application/loan_application_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/loan_application/test_loan_application.py b/erpnext/loan_management/doctype/loan_application/test_loan_application.py index 2a659e9fc2e..aefa08970a4 100644 --- a/erpnext/loan_management/doctype/loan_application/test_loan_application.py +++ b/erpnext/loan_management/doctype/loan_application/test_loan_application.py @@ -3,10 +3,16 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee, make_salary_structure -from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan_accounts + +import frappe + +from erpnext.loan_management.doctype.loan.test_loan import create_loan_accounts, create_loan_type +from erpnext.payroll.doctype.salary_structure.test_salary_structure import ( + make_employee, + make_salary_structure, +) + class TestLoanApplication(unittest.TestCase): def setUp(self): diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py index f113c10ef71..6d9d4f490d3 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py +++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py @@ -3,15 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.model.document import Document -from frappe.utils import nowdate, getdate, add_days, flt -from erpnext.controllers.accounts_controller import AccountsController +from frappe.utils import add_days, flt, get_datetime, nowdate + +import erpnext from erpnext.accounts.general_ledger import make_gl_entries -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans -from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty -from frappe.utils import get_datetime +from erpnext.controllers.accounts_controller import AccountsController +from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import ( + get_pledged_security_qty, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_demand_loans, +) + class LoanDisbursement(AccountsController): diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py index da56710c679..b17c9a177e0 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py +++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py @@ -2,16 +2,44 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe + import unittest -from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date) -from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry, create_loan_application, - make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_security_price) -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year, get_per_day_interest -from erpnext.selling.doctype.customer.test_customer import get_customer_dict + +import frappe +from frappe.utils import ( + add_days, + add_to_date, + date_diff, + flt, + get_datetime, + get_first_day, + get_last_day, + nowdate, +) + +from erpnext.loan_management.doctype.loan.test_loan import ( + create_demand_loan, + create_loan_accounts, + create_loan_application, + create_loan_security, + create_loan_security_pledge, + create_loan_security_price, + create_loan_security_type, + create_loan_type, + create_repayment_entry, + make_loan_disbursement_entry, +) from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge +from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import ( + days_in_year, + get_per_day_interest, +) from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_demand_loans, +) +from erpnext.selling.doctype.customer.test_customer import get_customer_dict + class TestLoanDisbursement(unittest.TestCase): diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py index d75213ce78d..93513a83e7e 100644 --- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py @@ -3,13 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.model.document import Document -from frappe.utils import (nowdate, getdate, now_datetime, get_datetime, flt, date_diff, get_last_day, cint, - get_first_day, get_datetime, add_days) -from erpnext.controllers.accounts_controller import AccountsController +from frappe.utils import add_days, cint, date_diff, flt, get_datetime, getdate, nowdate + +import erpnext from erpnext.accounts.general_ledger import make_gl_entries +from erpnext.controllers.accounts_controller import AccountsController + class LoanInterestAccrual(AccountsController): def validate(self): diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py index eb626f3eee0..06b801e47c5 100644 --- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py @@ -2,15 +2,31 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe + import unittest -from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date) -from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_price, - make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_application) -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year -from erpnext.selling.doctype.customer.test_customer import get_customer_dict + +import frappe +from frappe.utils import add_to_date, date_diff, flt, get_datetime, get_first_day, nowdate + +from erpnext.loan_management.doctype.loan.test_loan import ( + create_demand_loan, + create_loan_accounts, + create_loan_application, + create_loan_security, + create_loan_security_price, + create_loan_security_type, + create_loan_type, + make_loan_disbursement_entry, +) from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge +from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import ( + days_in_year, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_demand_loans, +) +from erpnext.selling.doctype.customer.test_customer import get_customer_dict + class TestLoanInterestAccrual(unittest.TestCase): def setUp(self): diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index b67b4c4842b..13b73573274 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -3,18 +3,26 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -import json + +import frappe from frappe import _ -from frappe.utils import flt, getdate, cint +from frappe.utils import add_days, cint, date_diff, flt, get_datetime, getdate from six import iteritems -from frappe.model.document import Document -from frappe.utils import date_diff, add_days, getdate, add_months, get_first_day, get_datetime -from erpnext.controllers.accounts_controller import AccountsController + +import erpnext from erpnext.accounts.general_ledger import make_gl_entries -from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import update_shortfall_status -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import get_per_day_interest, get_last_accrual_date +from erpnext.controllers.accounts_controller import AccountsController +from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import ( + get_last_accrual_date, + get_per_day_interest, +) +from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import ( + update_shortfall_status, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_demand_loans, +) + class LoanRepayment(AccountsController): diff --git a/erpnext/loan_management/doctype/loan_repayment/test_loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/test_loan_repayment.py index 73585a51592..c6ca630e599 100644 --- a/erpnext/loan_management/doctype/loan_repayment/test_loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/test_loan_repayment.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanRepayment(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py index a83b9b59415..495466c382e 100644 --- a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py +++ b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class LoanRepaymentDetail(Document): pass diff --git a/erpnext/loan_management/doctype/loan_security/loan_security.py b/erpnext/loan_management/doctype/loan_security/loan_security.py index 8858c818362..91cce67852a 100644 --- a/erpnext/loan_management/doctype/loan_security/loan_security.py +++ b/erpnext/loan_management/doctype/loan_security/loan_security.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class LoanSecurity(Document): def autoname(self): self.name = self.loan_security_name diff --git a/erpnext/loan_management/doctype/loan_security/loan_security_dashboard.py b/erpnext/loan_management/doctype/loan_security/loan_security_dashboard.py index 3eec5660ac1..35f3ba6830f 100644 --- a/erpnext/loan_management/doctype/loan_security/loan_security_dashboard.py +++ b/erpnext/loan_management/doctype/loan_security/loan_security_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/loan_security/test_loan_security.py b/erpnext/loan_management/doctype/loan_security/test_loan_security.py index 24dbc680461..910b658a93c 100644 --- a/erpnext/loan_management/doctype/loan_security/test_loan_security.py +++ b/erpnext/loan_management/doctype/loan_security/test_loan_security.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurity(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py index c390b6c526d..eb6c79ec4fc 100644 --- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py +++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py @@ -3,12 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import now_datetime, cint from frappe.model.document import Document -from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import update_shortfall_status -from erpnext.loan_management.doctype.loan_security_price.loan_security_price import get_loan_security_price +from frappe.utils import cint, now_datetime + +from erpnext.loan_management.doctype.loan_security_price.loan_security_price import ( + get_loan_security_price, +) +from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import ( + update_shortfall_status, +) + class LoanSecurityPledge(Document): def validate(self): diff --git a/erpnext/loan_management/doctype/loan_security_pledge/test_loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/test_loan_security_pledge.py index d2347c00985..41bc78ede48 100644 --- a/erpnext/loan_management/doctype/loan_security_pledge/test_loan_security_pledge.py +++ b/erpnext/loan_management/doctype/loan_security_pledge/test_loan_security_pledge.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurityPledge(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py index 9fc1fda53f4..6ede6a2739f 100644 --- a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py +++ b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py @@ -3,11 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import getdate, now_datetime, add_to_date, get_datetime, get_timestamp, get_datetime_str -from six import iteritems +from frappe.utils import get_datetime + class LoanSecurityPrice(Document): def validate(self): diff --git a/erpnext/loan_management/doctype/loan_security_price/test_loan_security_price.py b/erpnext/loan_management/doctype/loan_security_price/test_loan_security_price.py index 2fe0bd5a24e..ac630868427 100644 --- a/erpnext/loan_management/doctype/loan_security_price/test_loan_security_price.py +++ b/erpnext/loan_management/doctype/loan_security_price/test_loan_security_price.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurityPrice(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py index 61f17780481..5863c03f0f4 100644 --- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import get_datetime, flt from frappe.model.document import Document -from six import iteritems -from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty +from frappe.utils import flt, get_datetime + +from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import ( + get_pledged_security_qty, +) + class LoanSecurityShortfall(Document): pass diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/test_loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/test_loan_security_shortfall.py index b82f3d25936..fefec43bf41 100644 --- a/erpnext/loan_management/doctype/loan_security_shortfall/test_loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/loan_security_shortfall/test_loan_security_shortfall.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurityShortfall(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.py b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.py index cb8a50a27ba..ca1957fb3aa 100644 --- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.py +++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class LoanSecurityType(Document): pass diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type_dashboard.py b/erpnext/loan_management/doctype/loan_security_type/loan_security_type_dashboard.py index 17de8c1da4d..7a2732e3190 100644 --- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type_dashboard.py +++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/loan_security_type/test_loan_security_type.py b/erpnext/loan_management/doctype/loan_security_type/test_loan_security_type.py index f7d845a779c..99d7aafb343 100644 --- a/erpnext/loan_management/doctype/loan_security_type/test_loan_security_type.py +++ b/erpnext/loan_management/doctype/loan_security_type/test_loan_security_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurityType(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py index 4f936dd7c11..0af0de1a53a 100644 --- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py +++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py @@ -3,13 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import get_datetime, flt, getdate -import json +from frappe.utils import flt, get_datetime, getdate from six import iteritems -from erpnext.loan_management.doctype.loan_security_price.loan_security_price import get_loan_security_price + class LoanSecurityUnpledge(Document): def validate(self): @@ -30,7 +30,9 @@ class LoanSecurityUnpledge(Document): d.idx, frappe.bold(d.loan_security))) def validate_unpledge_qty(self): - from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import get_ltv_ratio + from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import ( + get_ltv_ratio, + ) pledge_qty_map = get_pledged_security_qty(self.loan) diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/test_loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/test_loan_security_unpledge.py index 5b5c205bda0..17eb7c63c7a 100644 --- a/erpnext/loan_management/doctype/loan_security_unpledge/test_loan_security_unpledge.py +++ b/erpnext/loan_management/doctype/loan_security_unpledge/test_loan_security_unpledge.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanSecurityUnpledge(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.py b/erpnext/loan_management/doctype/loan_type/loan_type.py index 50ef930dbbe..5458d358f3b 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.py +++ b/erpnext/loan_management/doctype/loan_type/loan_type.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class LoanType(Document): def validate(self): self.validate_accounts() diff --git a/erpnext/loan_management/doctype/loan_type/loan_type_dashboard.py b/erpnext/loan_management/doctype/loan_type/loan_type_dashboard.py index 95d97fdf9b0..96b2c4aedcf 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type_dashboard.py +++ b/erpnext/loan_management/doctype/loan_type/loan_type_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/loan_type/test_loan_type.py b/erpnext/loan_management/doctype/loan_type/test_loan_type.py index 5877ab6f7f0..9e57fdef2fa 100644 --- a/erpnext/loan_management/doctype/loan_type/test_loan_type.py +++ b/erpnext/loan_management/doctype/loan_type/test_loan_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanType(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py index 676df701cc3..4d5e7df4de1 100644 --- a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py +++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import getdate, flt, cint -from erpnext.controllers.accounts_controller import AccountsController +from frappe.utils import cint, flt, getdate + +import erpnext from erpnext.accounts.general_ledger import make_gl_entries +from erpnext.controllers.accounts_controller import AccountsController + class LoanWriteOff(AccountsController): def validate(self): diff --git a/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py index 9f6700e2749..57337c7e5d2 100644 --- a/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py +++ b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLoanWriteOff(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/pledge/pledge.py b/erpnext/loan_management/doctype/pledge/pledge.py index 0457ad7abdb..5a41cde4b58 100644 --- a/erpnext/loan_management/doctype/pledge/pledge.py +++ b/erpnext/loan_management/doctype/pledge/pledge.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class Pledge(Document): pass diff --git a/erpnext/loan_management/doctype/pledge/test_pledge.py b/erpnext/loan_management/doctype/pledge/test_pledge.py index 2e01dc114d7..adcbc6eae03 100644 --- a/erpnext/loan_management/doctype/pledge/test_pledge.py +++ b/erpnext/loan_management/doctype/pledge/test_pledge.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestPledge(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py index 8c67c0affee..efee701dc04 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py @@ -3,11 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import nowdate from frappe.model.document import Document -from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (make_accrual_interest_entry_for_demand_loans, - make_accrual_interest_entry_for_term_loans) +from frappe.utils import nowdate + +from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import ( + make_accrual_interest_entry_for_demand_loans, + make_accrual_interest_entry_for_term_loans, +) + class ProcessLoanInterestAccrual(Document): def on_submit(self): diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual_dashboard.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual_dashboard.py index e104c6646b0..fcd0399c6e9 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual_dashboard.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/test_process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/test_process_loan_interest_accrual.py index 6bfd3f42103..e7d360209ca 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/test_process_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/test_process_loan_interest_accrual.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestProcessLoanInterestAccrual(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py index b4aad25ac80..c3f59543c4e 100644 --- a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import get_datetime -from frappe import _ from frappe.model.document import Document -from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import check_for_ltv_shortfall +from frappe.utils import get_datetime + +from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import ( + check_for_ltv_shortfall, +) + class ProcessLoanSecurityShortfall(Document): def onload(self): diff --git a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall_dashboard.py b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall_dashboard.py index e67e4d4738f..ced3bd7e4fb 100644 --- a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall_dashboard.py +++ b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/loan_management/doctype/process_loan_security_shortfall/test_process_loan_security_shortfall.py b/erpnext/loan_management/doctype/process_loan_security_shortfall/test_process_loan_security_shortfall.py index cd379a1bea2..50e0a46ee4f 100644 --- a/erpnext/loan_management/doctype/process_loan_security_shortfall/test_process_loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/process_loan_security_shortfall/test_process_loan_security_shortfall.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestProcessLoanSecurityShortfall(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.py b/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.py index dfa5c7965a0..5c125e1307e 100644 --- a/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.py +++ b/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProposedPledge(Document): pass diff --git a/erpnext/loan_management/doctype/repayment_schedule/repayment_schedule.py b/erpnext/loan_management/doctype/repayment_schedule/repayment_schedule.py index 2aa27b09687..af9c6696aca 100644 --- a/erpnext/loan_management/doctype/repayment_schedule/repayment_schedule.py +++ b/erpnext/loan_management/doctype/repayment_schedule/repayment_schedule.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class RepaymentSchedule(Document): pass diff --git a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.py b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.py index 9ee0b96dc1d..64be1b2673e 100644 --- a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.py +++ b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class SalarySlipLoan(Document): pass diff --git a/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py b/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py index 74a131015b5..5660c421022 100644 --- a/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py +++ b/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py @@ -3,9 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe +from frappe import _ from frappe.model.document import Document + class SanctionedLoanAmount(Document): def validate(self): sanctioned_doc = frappe.db.exists('Sanctioned Loan Amount', {'applicant': self.applicant, 'company': self.company}) diff --git a/erpnext/loan_management/doctype/sanctioned_loan_amount/test_sanctioned_loan_amount.py b/erpnext/loan_management/doctype/sanctioned_loan_amount/test_sanctioned_loan_amount.py index ba1372f175d..663f2e72beb 100644 --- a/erpnext/loan_management/doctype/sanctioned_loan_amount/test_sanctioned_loan_amount.py +++ b/erpnext/loan_management/doctype/sanctioned_loan_amount/test_sanctioned_loan_amount.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestSanctionedLoanAmount(unittest.TestCase): pass diff --git a/erpnext/loan_management/doctype/unpledge/unpledge.py b/erpnext/loan_management/doctype/unpledge/unpledge.py index 205230a308f..2e82e239979 100644 --- a/erpnext/loan_management/doctype/unpledge/unpledge.py +++ b/erpnext/loan_management/doctype/unpledge/unpledge.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class Unpledge(Document): pass diff --git a/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py b/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py index f2cbbb469f0..ff527029f67 100644 --- a/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py +++ b/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _ -from frappe.utils import get_datetime, flt +from frappe.utils import flt from six import iteritems +import erpnext + + def execute(filters=None): columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py index a505e72c4d9..c4adef1c7ba 100644 --- a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py +++ b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _ -from frappe.utils import flt, getdate, add_days -from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure \ - import get_loan_security_details +from frappe.utils import add_days, flt, getdate + +import erpnext +from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure import ( + get_loan_security_details, +) def execute(filters=None): diff --git a/erpnext/loan_management/report/loan_repayment_and_closure/loan_repayment_and_closure.py b/erpnext/loan_management/report/loan_repayment_and_closure/loan_repayment_and_closure.py index 65910770881..9d8a425b30c 100644 --- a/erpnext/loan_management/report/loan_repayment_and_closure/loan_repayment_and_closure.py +++ b/erpnext/loan_management/report/loan_repayment_and_closure/loan_repayment_and_closure.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns() data = get_data(filters) diff --git a/erpnext/loan_management/report/loan_security_exposure/loan_security_exposure.py b/erpnext/loan_management/report/loan_security_exposure/loan_security_exposure.py index 34bbe5a4503..3d6242a4fa1 100644 --- a/erpnext/loan_management/report/loan_security_exposure/loan_security_exposure.py +++ b/erpnext/loan_management/report/loan_security_exposure/loan_security_exposure.py @@ -2,12 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import erpnext + from frappe import _ from frappe.utils import flt from six import iteritems -from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure \ - import get_loan_security_details, get_applicant_wise_total_loan_security_qty + +import erpnext +from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applicant_wise_loan_security_exposure import ( + get_applicant_wise_total_loan_security_qty, + get_loan_security_details, +) + def execute(filters=None): columns = get_columns(filters) diff --git a/erpnext/loan_management/report/loan_security_status/loan_security_status.py b/erpnext/loan_management/report/loan_security_status/loan_security_status.py index 19518554759..a93a381eb3f 100644 --- a/erpnext/loan_management/report/loan_security_status/loan_security_status.py +++ b/erpnext/loan_management/report/loan_security_status/loan_security_status.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py index 97289032d70..52e41c5863e 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py @@ -2,15 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _, throw +from frappe.utils import add_days, cint, cstr, date_diff, formatdate, getdate -from frappe.utils import add_days, getdate, cint, cstr, date_diff, formatdate - -from frappe import throw, _ -from erpnext.utilities.transaction_base import TransactionBase, delete_events -from erpnext.stock.utils import get_valid_serial_nos from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.utils import get_valid_serial_nos +from erpnext.utilities.transaction_base import TransactionBase, delete_events + class MaintenanceSchedule(TransactionBase): @frappe.whitelist() diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py index c733dd0c92c..38654de6638 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py @@ -2,11 +2,15 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -from frappe.utils.data import add_days, today, formatdate -from erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule import make_maintenance_visit + +import unittest import frappe -import unittest +from frappe.utils.data import add_days, formatdate, today + +from erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule import ( + make_maintenance_visit, +) # test_records = frappe.get_test_records('Maintenance Schedule') diff --git a/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py b/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py index e69b4fb65e0..27c95a1ea2b 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py +++ b/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MaintenanceScheduleDetail(Document): pass diff --git a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py index 1dd47fea24f..9c4a690789d 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py +++ b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MaintenanceScheduleItem(Document): pass diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py index d63c7003870..814ec0cae4b 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import get_datetime from erpnext.utilities.transaction_base import TransactionBase + class MaintenanceVisit(TransactionBase): def get_feed(self): return _("To {0}").format(self.customer_name) diff --git a/erpnext/maintenance/doctype/maintenance_visit/test_maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/test_maintenance_visit.py index 2bea8d1e2f6..57e728d1b13 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/test_maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/test_maintenance_visit.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Maintenance Visit') diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py index a7f0f5b3bb9..4c59562685d 100644 --- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py +++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class MaintenanceVisitPurpose(Document): pass diff --git a/erpnext/manufacturing/dashboard_fixtures.py b/erpnext/manufacturing/dashboard_fixtures.py index 7ba43d6471e..1bc12ff35eb 100644 --- a/erpnext/manufacturing/dashboard_fixtures.py +++ b/erpnext/manufacturing/dashboard_fixtures.py @@ -1,9 +1,14 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import frappe, erpnext, json +import json + +import frappe from frappe import _ -from frappe.utils import nowdate, get_first_day, get_last_day, add_months +from frappe.utils import add_months, nowdate + +import erpnext + def get_data(): return frappe._dict({ diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index 1aedb1e590f..59eb168d4e4 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, getdate from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, getdate + from erpnext.stock.doctype.item.item import get_item_defaults diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py index d9aa0ca49d0..83260ec1b9f 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py index 9a0a72fb475..3104ae01177 100644 --- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py @@ -3,12 +3,16 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import add_months, today + from erpnext import get_company_currency + from .blanket_order import make_order + class TestBlanketOrder(unittest.TestCase): def setUp(self): frappe.flags.args = frappe._dict() diff --git a/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py b/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py index f07f3c8e046..0825f763dcf 100644 --- a/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py +++ b/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class BlanketOrderItem(Document): pass diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 47d94fbce31..1463aa7d34a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1,23 +1,22 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from typing import List -from collections import deque -import frappe, erpnext -from frappe.utils import cint, cstr, flt, today -from frappe import _ -from erpnext.setup.utils import get_exchange_rate -from frappe.website.website_generator import WebsiteGenerator -from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.stock.get_item_details import get_price_list_rate -from frappe.core.doctype.version.version import get_diff -from erpnext.controllers.queries import get_match_cond -from erpnext.stock.doctype.item.item import get_item_details -from frappe.model.mapper import get_mapped_doc - import functools - +from collections import deque from operator import itemgetter +from typing import List + +import frappe +from frappe import _ +from frappe.core.doctype.version.version import get_diff +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, cstr, flt, today +from frappe.website.website_generator import WebsiteGenerator + +import erpnext +from erpnext.setup.utils import get_exchange_rate +from erpnext.stock.doctype.item.item import get_item_details +from erpnext.stock.get_item_details import get_conversion_factor, get_price_list_rate form_grid_templates = { "items": "templates/form_grid/item_grid.html" diff --git a/erpnext/manufacturing/doctype/bom/bom_dashboard.py b/erpnext/manufacturing/doctype/bom/bom_dashboard.py index 361826e2d0c..f65df011a93 100644 --- a/erpnext/manufacturing/doctype/bom/bom_dashboard.py +++ b/erpnext/manufacturing/doctype/bom/bom_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'bom_no', diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index a904d7f7be0..6484b7f699d 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -2,15 +2,19 @@ # License: GNU General Public License v3. See license.txt -from collections import deque import unittest +from collections import deque + import frappe -from frappe.utils import cstr, flt from frappe.test_runner import make_test_records -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation +from frappe.utils import cstr, flt + +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost from erpnext.stock.doctype.item.test_item import make_item -from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, +) from erpnext.tests.test_subcontracting import set_backflush_based_on test_records = frappe.get_test_records('BOM') diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py index 39ccbddbea2..4317d3adf68 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class BOMExplosionItem(Document): pass diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.py b/erpnext/manufacturing/doctype/bom_item/bom_item.py index 220c73e1493..2954238a571 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.py +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class BOMItem(Document): pass diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.py b/erpnext/manufacturing/doctype/bom_operation/bom_operation.py index e3501eb9cf6..5e46c7ef932 100644 --- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.py +++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class BOMOperation(Document): pass diff --git a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py index b6d423f09f2..891fc53c71e 100644 --- a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py +++ b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class BOMScrapItem(Document): pass diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py index 8fbcd4ea1db..ed71c6d6d7b 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py @@ -3,13 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import cstr, flt -from frappe import _ -from six import string_types -from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order -from frappe.model.document import Document + +import json + import click +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import cstr, flt +from six import string_types + +from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order + class BOMUpdateTool(Document): def replace_bom(self): diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py index 80d1cdfc8f2..88c69ce2a5e 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py @@ -3,11 +3,14 @@ from __future__ import unicode_literals + import unittest + import frappe -from erpnext.stock.doctype.item.test_item import create_item -from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom + from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost +from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom +from erpnext.stock.doctype.item.test_item import create_item test_records = frappe.get_test_records('BOM') diff --git a/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py b/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py index 4088a7fc540..f627b4e5283 100644 --- a/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py +++ b/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class BOMWebsiteItem(Document): pass diff --git a/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py b/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py index bcc5ddab089..5bd8cf568c7 100644 --- a/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py +++ b/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class BOMWebsiteOperation(Document): pass diff --git a/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py b/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py index 56ec4356af4..62833d7cd20 100644 --- a/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py +++ b/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py @@ -3,9 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import time_diff_in_hours + from frappe.model.document import Document +from frappe.utils import time_diff_in_hours + class DowntimeEntry(Document): def validate(self): diff --git a/erpnext/manufacturing/doctype/downtime_entry/test_downtime_entry.py b/erpnext/manufacturing/doctype/downtime_entry/test_downtime_entry.py index 8b2a8d36c12..37169f4439a 100644 --- a/erpnext/manufacturing/doctype/downtime_entry/test_downtime_entry.py +++ b/erpnext/manufacturing/doctype/downtime_entry/test_downtime_entry.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestDowntimeEntry(unittest.TestCase): pass diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 3efbe88adaf..3bf9de2708c 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -3,16 +3,32 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import datetime import json -from frappe import _, bold -from frappe.model.mapper import get_mapped_doc -from frappe.model.document import Document -from frappe.utils import (flt, cint, time_diff_in_hours, get_datetime, getdate, - get_time, add_to_date, time_diff, add_days, get_datetime_str, get_link_to_form, time_diff_in_seconds) -from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations +import frappe +from frappe import _, bold +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc +from frappe.utils import ( + add_days, + add_to_date, + cint, + flt, + get_datetime, + get_link_to_form, + get_time, + getdate, + time_diff, + time_diff_in_hours, + time_diff_in_seconds, +) + +from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import ( + get_mins_between_operations, +) + class OverlapError(frappe.ValidationError): pass diff --git a/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py b/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py index c2aa2bd968a..3ec6697b9f4 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py +++ b/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'job_card', diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index 8fa0b27fcb8..db0e08fcd0a 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -4,11 +4,14 @@ from __future__ import unicode_literals import unittest + import frappe from frappe.utils import random_string -from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation -from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record + from erpnext.manufacturing.doctype.job_card.job_card import OperationMismatchError +from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record +from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation + class TestJobCard(unittest.TestCase): def test_job_card(self): diff --git a/erpnext/manufacturing/doctype/job_card_item/job_card_item.py b/erpnext/manufacturing/doctype/job_card_item/job_card_item.py index 373cba293e3..a1338364aa4 100644 --- a/erpnext/manufacturing/doctype/job_card_item/job_card_item.py +++ b/erpnext/manufacturing/doctype/job_card_item/job_card_item.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class JobCardItem(Document): pass diff --git a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py index 85d72982ed3..43d14220649 100644 --- a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py +++ b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class JobCardOperation(Document): pass diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py index 3dc66891216..ed27e7ff824 100644 --- a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py +++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class JobCardTimeLog(Document): pass diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index 149fe3e22b8..18d78b59f53 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe +from dateutil.relativedelta import relativedelta from frappe.model.document import Document from frappe.utils import cint -from dateutil.relativedelta import relativedelta + class ManufacturingSettings(Document): pass diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.py index 7391f65dec9..fd0ac725914 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestManufacturingSettings(unittest.TestCase): pass diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json index 6c60bbde86c..27d7c4175e5 100644 --- a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json +++ b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json @@ -6,17 +6,17 @@ "engine": "InnoDB", "field_order": [ "item_code", - "item_name", - "material_request_type", "from_warehouse", "warehouse", - "column_break_4", + "item_name", + "material_request_type", + "actual_qty", + "ordered_qty", "required_bom_qty", + "column_break_4", "quantity", "uom", "projected_qty", - "actual_qty", - "ordered_qty", "reserved_qty_for_production", "safety_stock", "item_details", @@ -28,6 +28,7 @@ ], "fields": [ { + "columns": 2, "fieldname": "item_code", "fieldtype": "Link", "in_list_view": 1, @@ -41,6 +42,7 @@ "label": "Item Name" }, { + "columns": 2, "fieldname": "warehouse", "fieldtype": "Link", "in_list_view": 1, @@ -50,10 +52,11 @@ "reqd": 1 }, { + "columns": 1, "fieldname": "material_request_type", "fieldtype": "Select", "in_list_view": 1, - "label": "Material Request Type", + "label": "Type", "options": "\nPurchase\nMaterial Transfer\nMaterial Issue\nManufacture\nCustomer Provided" }, { @@ -61,10 +64,11 @@ "fieldtype": "Column Break" }, { + "columns": 1, "fieldname": "quantity", "fieldtype": "Float", "in_list_view": 1, - "label": "Required Quantity", + "label": "Plan to Request Qty", "no_copy": 1, "reqd": 1 }, @@ -75,11 +79,12 @@ "read_only": 1 }, { + "columns": 2, "default": "0", "fieldname": "actual_qty", "fieldtype": "Float", "in_list_view": 1, - "label": "Actual Qty", + "label": "Available Qty", "no_copy": 1, "read_only": 1 }, @@ -157,16 +162,18 @@ "read_only": 1 }, { + "columns": 2, "fieldname": "required_bom_qty", "fieldtype": "Float", - "label": "Required Qty as per BOM", + "in_list_view": 1, + "label": "Qty As Per BOM", "no_copy": 1, "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2021-03-26 12:41:13.013149", + "modified": "2021-08-23 18:17:58.400462", "modified_by": "Administrator", "module": "Manufacturing", "name": "Material Request Plan Item", diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py index 73e369c149e..bc26644067f 100644 --- a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py +++ b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class MaterialRequestPlanItem(Document): pass diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.py b/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.py index dc43b69ef24..2675af94a72 100644 --- a/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.py +++ b/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestMaterialRequestPlanItem(unittest.TestCase): pass diff --git a/erpnext/manufacturing/doctype/operation/operation.py b/erpnext/manufacturing/doctype/operation/operation.py index 374f32019bd..2926f911ea1 100644 --- a/erpnext/manufacturing/doctype/operation/operation.py +++ b/erpnext/manufacturing/doctype/operation/operation.py @@ -7,6 +7,7 @@ import frappe from frappe import _ from frappe.model.document import Document + class Operation(Document): def validate(self): if not self.description: diff --git a/erpnext/manufacturing/doctype/operation/operation_dashboard.py b/erpnext/manufacturing/doctype/operation/operation_dashboard.py index 8deb9ec6e0b..284fd9dfc2f 100644 --- a/erpnext/manufacturing/doctype/operation/operation_dashboard.py +++ b/erpnext/manufacturing/doctype/operation/operation_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'operation', diff --git a/erpnext/manufacturing/doctype/operation/test_operation.py b/erpnext/manufacturing/doctype/operation/test_operation.py index 8e7e7237263..2b24118fc41 100644 --- a/erpnext/manufacturing/doctype/operation/test_operation.py +++ b/erpnext/manufacturing/doctype/operation/test_operation.py @@ -2,9 +2,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_records = frappe.get_test_records('Operation') class TestOperation(unittest.TestCase): diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js index d198a6962a5..4343e8a24eb 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.js +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js @@ -254,7 +254,7 @@ frappe.ui.form.on('Production Plan', { get_items_for_mr: function(frm) { if (!frm.doc.for_warehouse) { - frappe.throw(__("Select warehouse for material requests")); + frappe.throw(__("To make material requests, 'Make Material Request for Warehouse' field is mandatory")); } if (frm.doc.ignore_existing_ordered_qty) { @@ -265,9 +265,18 @@ frappe.ui.form.on('Production Plan', { title: title, fields: [ { - "fieldtype": "Table MultiSelect", "label": __("Source Warehouses (Optional)"), - "fieldname": "warehouses", "options": "Production Plan Material Request Warehouse", - "description": __("System will pickup the materials from the selected warehouses. If not specified, system will create material request for purchase."), + 'label': __('Target Warehouse'), + 'fieldtype': 'Link', + 'fieldname': 'target_warehouse', + 'read_only': true, + 'default': frm.doc.for_warehouse + }, + { + 'label': __('Source Warehouses (Optional)'), + 'fieldtype': 'Table MultiSelect', + 'fieldname': 'warehouses', + 'options': 'Production Plan Material Request Warehouse', + 'description': __('If source warehouse selected then system will create the material request with type Material Transfer from Source to Target warehouse. If not selected then will create the material request with type Purchase for the target warehouse.'), get_query: function () { return { filters: { @@ -342,7 +351,11 @@ frappe.ui.form.on('Production Plan', { frappe.prompt(fields, (row) => { let get_template_url = 'erpnext.manufacturing.doctype.production_plan.production_plan.download_raw_materials'; - open_url_post(frappe.request.url, { cmd: get_template_url, doc: frm.doc, warehouses: row.warehouses }); + open_url_post(frappe.request.url, { + cmd: get_template_url, + doc: frm.doc, + warehouses: row.warehouses + }); }, __('Select Warehouses to get Stock for Materials Planning'), __('Get Stock')); }, @@ -421,6 +434,25 @@ frappe.ui.form.on("Material Request Plan Item", { } }); +frappe.ui.form.on("Production Plan Sales Order", { + sales_order(frm, cdt, cdn) { + const { sales_order } = locals[cdt][cdn]; + if (!sales_order) { + return; + } + frappe.call({ + method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_so_details", + args: { sales_order }, + callback(r) { + const {transaction_date, customer, grand_total} = r.message; + frappe.model.set_value(cdt, cdn, 'sales_order_date', transaction_date); + frappe.model.set_value(cdt, cdn, 'customer', customer); + frappe.model.set_value(cdt, cdn, 'grand_total', grand_total); + } + }); + } +}); + cur_frm.fields_dict['sales_orders'].grid.get_field("sales_order").get_query = function() { return{ filters: [ diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json index 84378956c61..b5ed28802c8 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.json +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json @@ -300,7 +300,7 @@ { "fieldname": "for_warehouse", "fieldtype": "Link", - "label": "Material Request Warehouse", + "label": "Make Material Request for Warehouse", "options": "Warehouse" }, { @@ -364,7 +364,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-06-28 20:00:33.905114", + "modified": "2021-08-23 17:26:03.799876", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Plan", diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 6b61c6d330f..73db29030ef 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -3,18 +3,32 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json, copy -from frappe import msgprint, _ + +import copy +import json + +import frappe +from frappe import _, msgprint +from frappe.model.document import Document +from frappe.utils import ( + add_days, + ceil, + cint, + comma_and, + flt, + get_link_to_form, + getdate, + now_datetime, + nowdate, +) +from frappe.utils.csvutils import build_csv_response from six import iteritems -from frappe.model.document import Document -from frappe.utils import (flt, cint, nowdate, add_days, comma_and, now_datetime, - ceil, get_link_to_form, getdate) -from frappe.utils.csvutils import build_csv_response -from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_children +from erpnext.manufacturing.doctype.bom.bom import get_children, validate_bom_no from erpnext.manufacturing.doctype.work_order.work_order import get_item_details from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults + class ProductionPlan(Document): def validate(self): self.calculate_total_planned_qty() @@ -331,7 +345,7 @@ class ProductionPlan(Document): def get_production_items(self): item_dict = {} for d in self.po_items: - item_details= { + item_details = { "production_item" : d.item_code, "use_multi_level_bom" : d.include_exploded_items, "sales_order" : d.sales_order, @@ -346,8 +360,7 @@ class ProductionPlan(Document): "production_plan" : self.name, "production_plan_item" : d.name, "product_bundle_item" : d.product_bundle_item, - "planned_start_date" : d.planned_start_date, - "make_work_order_for_sub_assembly_items": d.get("make_work_order_for_sub_assembly_items", 0) + "planned_start_date" : d.planned_start_date } item_details.update({ @@ -454,10 +467,14 @@ class ProductionPlan(Document): }) def create_work_order(self, item): - from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError, get_default_warehouse + from erpnext.manufacturing.doctype.work_order.work_order import ( + OverProductionError, + get_default_warehouse, + ) warehouse = get_default_warehouse() wo = frappe.new_doc("Work Order") wo.update(item) + wo.planned_start_date = item.get('planned_start_date') or item.get('schedule_date') if item.get("warehouse"): wo.fg_warehouse = item.get("warehouse") @@ -569,7 +586,10 @@ def download_raw_materials(doc, warehouses=None): 'Reserved Qty for Production', 'Safety Stock', 'Required Qty']] doc.warehouse = None - for d in get_items_for_material_requests(doc, warehouses=warehouses, get_parent_warehouse_data=True): + frappe.flags.show_qty_in_stock_uom = 1 + items = get_items_for_material_requests(doc, warehouses=warehouses, get_parent_warehouse_data=True) + + for d in items: item_list.append([d.get('item_code'), d.get('description'), d.get('stock_uom'), d.get('warehouse'), d.get('required_bom_qty'), d.get('projected_qty'), d.get('actual_qty'), d.get('ordered_qty'), d.get('planned_qty'), d.get('reserved_qty_for_production'), d.get('safety_stock'), d.get('quantity')]) @@ -605,9 +625,16 @@ def get_exploded_items(item_details, company, bom_no, include_non_stock_items, p and bom.name=%s and item.is_stock_item in (1, {0}) group by bei.item_code, bei.stock_uom""".format(0 if include_non_stock_items else 1), (planned_qty, company, bom_no), as_dict=1): - item_details.setdefault(d.get('item_code'), d) + if not d.conversion_factor and d.purchase_uom: + d.conversion_factor = get_uom_conversion_factor(d.item_code, d.purchase_uom) + item_details.setdefault(d.get('item_code'), d) + return item_details +def get_uom_conversion_factor(item_code, uom): + return frappe.db.get_value('UOM Conversion Detail', + {'parent': item_code, 'uom': uom}, 'conversion_factor') + def get_subitems(doc, data, item_details, bom_no, company, include_non_stock_items, include_subcontracted_items, parent_qty, planned_qty=1): items = frappe.db.sql(""" @@ -642,6 +669,9 @@ def get_subitems(doc, data, item_details, bom_no, company, include_non_stock_ite if d.item_code in item_details: item_details[d.item_code].qty = item_details[d.item_code].qty + d.qty else: + if not d.conversion_factor and d.purchase_uom: + d.conversion_factor = get_uom_conversion_factor(d.item_code, d.purchase_uom) + item_details[d.item_code] = d if data.get('include_exploded_items') and d.default_bom: @@ -669,10 +699,11 @@ def get_material_request_items(row, sales_order, company, row['purchase_uom'] = row['stock_uom'] if row['purchase_uom'] != row['stock_uom']: - if not row['conversion_factor']: + if not (row['conversion_factor'] or frappe.flags.show_qty_in_stock_uom): frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}") .format(row['purchase_uom'], row['stock_uom'], row.item_code)) - required_qty = required_qty / row['conversion_factor'] + + required_qty = required_qty / row['conversion_factor'] if frappe.db.get_value("UOM", row['purchase_uom'], "must_be_whole_number"): required_qty = ceil(required_qty) @@ -769,6 +800,12 @@ def get_bin_details(row, company, for_warehouse=None, all_warehouse=False): group by item_code, warehouse """.format(conditions=conditions), { "item_code": row['item_code'] }, as_dict=1) +@frappe.whitelist() +def get_so_details(sales_order): + return frappe.db.get_value("Sales Order", sales_order, + ['transaction_date', 'customer', 'grand_total'], as_dict=1 + ) + def get_warehouse_list(warehouses): warehouse_list = [] @@ -841,10 +878,8 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d elif data.get('item_code'): item_master = frappe.get_doc('Item', data['item_code']).as_dict() purchase_uom = item_master.purchase_uom or item_master.stock_uom - conversion_factor = 0 - for d in item_master.get("uoms"): - if d.uom == purchase_uom: - conversion_factor = d.conversion_factor + conversion_factor = (get_uom_conversion_factor(item_master.name, purchase_uom) + if item_master.purchase_uom else 1.0) item_details[item_master.name] = frappe._dict( { diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py b/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py index 52a56af7bce..b4bc3467e46 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'production_plan', diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 78028039c48..6a942d54335 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -3,15 +3,23 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import nowdate, now_datetime, flt, add_to_date -from erpnext.stock.doctype.item.test_item import create_item -from erpnext.manufacturing.doctype.production_plan.production_plan import get_sales_orders -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order -from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests, get_warehouse_list + +import frappe +from frappe.utils import add_to_date, flt, now_datetime, nowdate + from erpnext.controllers.item_variant import create_variant +from erpnext.manufacturing.doctype.production_plan.production_plan import ( + get_items_for_material_requests, + get_sales_orders, + get_warehouse_list, +) +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, +) + class TestProductionPlan(unittest.TestCase): def setUp(self): diff --git a/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py b/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py index 37cf5a49dc9..24029d8f2ce 100644 --- a/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py +++ b/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ProductionPlanItem(Document): pass diff --git a/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py b/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py index 51fbc3633b1..9d25d6fc20f 100644 --- a/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py +++ b/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProductionPlanItemReference(Document): pass diff --git a/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py b/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py index 44786f8388d..d1d935c955b 100644 --- a/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py +++ b/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProductionPlanMaterialRequest(Document): pass diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py index f605985ae96..1548bd7b88a 100644 --- a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py +++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProductionPlanMaterialRequestWarehouse(Document): pass diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py index ecab5fbae12..905252da604 100644 --- a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py +++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestProductionPlanMaterialRequestWarehouse(unittest.TestCase): pass diff --git a/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py b/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py index 99c7273a640..ea53a986964 100644 --- a/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py +++ b/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ProductionPlanSalesOrder(Document): pass diff --git a/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py b/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py index 6850a2eb4ed..be0ed1b96a8 100644 --- a/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py +++ b/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProductionPlanSubAssemblyItem(Document): pass diff --git a/erpnext/manufacturing/doctype/routing/routing.py b/erpnext/manufacturing/doctype/routing/routing.py index ece0db717a2..20fb370d942 100644 --- a/erpnext/manufacturing/doctype/routing/routing.py +++ b/erpnext/manufacturing/doctype/routing/routing.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cint, flt from frappe import _ from frappe.model.document import Document +from frappe.utils import cint, flt + class Routing(Document): def validate(self): diff --git a/erpnext/manufacturing/doctype/routing/routing_dashboard.py b/erpnext/manufacturing/doctype/routing/routing_dashboard.py index 50a3fe62da5..9ef6ee57523 100644 --- a/erpnext/manufacturing/doctype/routing/routing_dashboard.py +++ b/erpnext/manufacturing/doctype/routing/routing_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/manufacturing/doctype/routing/test_routing.py b/erpnext/manufacturing/doctype/routing/test_routing.py index 92f26946ab7..b84b2ba1e6d 100644 --- a/erpnext/manufacturing/doctype/routing/test_routing.py +++ b/erpnext/manufacturing/doctype/routing/test_routing.py @@ -4,11 +4,14 @@ from __future__ import unicode_literals import unittest + import frappe from frappe.test_runner import make_test_records -from erpnext.stock.doctype.item.test_item import make_item + from erpnext.manufacturing.doctype.job_card.job_card import OperationSequenceError from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record +from erpnext.stock.doctype.item.test_item import make_item + class TestRouting(unittest.TestCase): @classmethod @@ -91,8 +94,8 @@ class TestRouting(unittest.TestCase): def setup_operations(rows): - from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation from erpnext.manufacturing.doctype.operation.test_operation import make_operation + from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation for row in rows: make_workstation(row) make_operation(row) diff --git a/erpnext/manufacturing/doctype/sub_operation/sub_operation.py b/erpnext/manufacturing/doctype/sub_operation/sub_operation.py index f4b27758e9d..37b64f23d29 100644 --- a/erpnext/manufacturing/doctype/sub_operation/sub_operation.py +++ b/erpnext/manufacturing/doctype/sub_operation/sub_operation.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class SubOperation(Document): pass diff --git a/erpnext/manufacturing/doctype/sub_operation/test_sub_operation.py b/erpnext/manufacturing/doctype/sub_operation/test_sub_operation.py index d3410ca3120..c5749dbc962 100644 --- a/erpnext/manufacturing/doctype/sub_operation/test_sub_operation.py +++ b/erpnext/manufacturing/doctype/sub_operation/test_sub_operation.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestSubOperation(unittest.TestCase): pass diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index c0ed6115340..bb431498636 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -3,18 +3,28 @@ from __future__ import unicode_literals + import unittest + import frappe -from frappe.utils import flt, now, add_months, cint, today, add_to_date -from erpnext.manufacturing.doctype.work_order.work_order import (make_stock_entry, - ItemHasVariantError, stop_unstop, StockOverProductionError, OverProductionError, CapacityError) -from erpnext.stock.doctype.stock_entry import test_stock_entry -from erpnext.stock.utils import get_bin +from frappe.utils import add_months, cint, flt, now, today + +from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError +from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom +from erpnext.manufacturing.doctype.work_order.work_order import ( + CapacityError, + ItemHasVariantError, + OverProductionError, + StockOverProductionError, + make_stock_entry, + stop_unstop, +) from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.stock.doctype.item.test_item import make_item -from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom +from erpnext.stock.doctype.stock_entry import test_stock_entry from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse -from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError +from erpnext.stock.utils import get_bin + class TestWorkOrder(unittest.TestCase): def setUp(self): @@ -696,8 +706,10 @@ class TestWorkOrder(unittest.TestCase): self.assertRaises(frappe.ValidationError, make_stock_entry, wo.name, 'Material Transfer for Manufacture') def test_wo_completion_with_pl_bom(self): - from erpnext.manufacturing.doctype.bom.test_bom import create_process_loss_bom_items - from erpnext.manufacturing.doctype.bom.test_bom import create_bom_with_process_loss_item + from erpnext.manufacturing.doctype.bom.test_bom import ( + create_bom_with_process_loss_item, + create_process_loss_bom_items, + ) qty = 4 scrap_qty = 0.25 # bom item qty = 1, consider as 25% of FG diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 24b33d523e4..e282dd3ecba 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1,25 +1,43 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import frappe import json -import math -from frappe import _ -from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate, get_link_to_form, time_diff_in_hours -from frappe.model.document import Document -from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict, get_bom_item_rate + +import frappe from dateutil.relativedelta import relativedelta -from erpnext.stock.doctype.item.item import validate_end_of_life, get_item_defaults -from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError -from erpnext.projects.doctype.timesheet.timesheet import OverlapError -from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations -from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty -from frappe.utils.csvutils import getlink -from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty -from erpnext.utilities.transaction_base import validate_uom_is_integer +from frappe import _ +from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc +from frappe.utils import ( + cint, + date_diff, + flt, + get_datetime, + get_link_to_form, + getdate, + nowdate, + time_diff_in_hours, +) + +from erpnext.manufacturing.doctype.bom.bom import ( + get_bom_item_rate, + get_bom_items_as_dict, + validate_bom_no, +) +from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import ( + get_mins_between_operations, +) from erpnext.stock.doctype.batch.batch import make_batch -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, get_auto_serial_nos, auto_make_serial_nos +from erpnext.stock.doctype.item.item import get_item_defaults, validate_end_of_life +from erpnext.stock.doctype.serial_no.serial_no import ( + auto_make_serial_nos, + get_auto_serial_nos, + get_serial_nos, +) +from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty +from erpnext.stock.utils import get_bin, get_latest_stock_qty, validate_warehouse_company +from erpnext.utilities.transaction_base import validate_uom_is_integer + class OverProductionError(frappe.ValidationError): pass class CapacityError(frappe.ValidationError): pass diff --git a/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py index 403d46d8d42..f0fc43f1656 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py +++ b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'work_order', diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.py b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py index 9aa53b5e3c3..3f2664b16e9 100644 --- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.py +++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class WorkOrderItem(Document): pass diff --git a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py index 3c20d8e88a0..d25c9f21890 100644 --- a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py +++ b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class WorkOrderOperation(Document): pass diff --git a/erpnext/manufacturing/doctype/workstation/test_workstation.py b/erpnext/manufacturing/doctype/workstation/test_workstation.py index 9b73aca6010..6c6ab77dd8f 100644 --- a/erpnext/manufacturing/doctype/workstation/test_workstation.py +++ b/erpnext/manufacturing/doctype/workstation/test_workstation.py @@ -1,14 +1,20 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors # See license.txt from __future__ import unicode_literals -from erpnext.manufacturing.doctype.operation.test_operation import make_operation + +import unittest import frappe -import unittest -from erpnext.manufacturing.doctype.workstation.workstation import check_if_within_operating_hours, NotInWorkingHoursError, WorkstationHolidayError -from erpnext.manufacturing.doctype.routing.test_routing import setup_bom, create_routing from frappe.test_runner import make_test_records +from erpnext.manufacturing.doctype.operation.test_operation import make_operation +from erpnext.manufacturing.doctype.routing.test_routing import create_routing, setup_bom +from erpnext.manufacturing.doctype.workstation.workstation import ( + NotInWorkingHoursError, + WorkstationHolidayError, + check_if_within_operating_hours, +) + test_dependencies = ["Warehouse"] test_records = frappe.get_test_records('Workstation') make_test_records('Workstation') diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py index f4483f75472..6daf950c5ff 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.py +++ b/erpnext/manufacturing/doctype/workstation/workstation.py @@ -2,13 +2,23 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from erpnext.support.doctype.issue.issue import get_holidays -from frappe.utils import (flt, cint, getdate, formatdate, - comma_and, time_diff_in_seconds, to_timedelta, add_days) from frappe.model.document import Document -from dateutil.parser import parse +from frappe.utils import ( + add_days, + cint, + comma_and, + flt, + formatdate, + getdate, + time_diff_in_seconds, + to_timedelta, +) + +from erpnext.support.doctype.issue.issue import get_holidays + class WorkstationHolidayError(frappe.ValidationError): pass class NotInWorkingHoursError(frappe.ValidationError): pass diff --git a/erpnext/manufacturing/doctype/workstation/workstation_dashboard.py b/erpnext/manufacturing/doctype/workstation/workstation_dashboard.py index 3ddbe731700..3e4b38aae85 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation_dashboard.py +++ b/erpnext/manufacturing/doctype/workstation/workstation_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'workstation', diff --git a/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py b/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py index 215df4c9b5d..719d83db51a 100644 --- a/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py +++ b/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class WorkstationWorkingHour(Document): pass diff --git a/erpnext/manufacturing/notification/material_request_receipt_notification/material_request_receipt_notification.py b/erpnext/manufacturing/notification/material_request_receipt_notification/material_request_receipt_notification.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/manufacturing/notification/material_request_receipt_notification/material_request_receipt_notification.py +++ b/erpnext/manufacturing/notification/material_request_receipt_notification/material_request_receipt_notification.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py index 858b5546b02..c122fa9b614 100644 --- a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py +++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from pprint import pprint + def execute(filters=None): data = [] diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py index 8778d9ba557..3c2d2153697 100644 --- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py +++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): data = get_data(filters) columns = get_columns(filters) diff --git a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py index ffd9242e1b8..c085990acc3 100644 --- a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py +++ b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py @@ -2,12 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils.data import comma_and + def execute(filters=None): -# if not filters: filters = {} + # if not filters: filters = {} columns = get_columns() summ_data = [] diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py index ed8b93929a1..b8ef68dbb68 100644 --- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py +++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py index dc424b7605c..bbf503718f9 100644 --- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py +++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns, data = [], [] columns = get_columns(filters) diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py index b4db98c3d7e..0dcad448d79 100644 --- a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py +++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.py b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.py index 74c794b5dd0..a1c6fd12622 100644 --- a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.py +++ b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt from frappe import _ +from frappe.utils import flt + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py index 9a6c764c609..f014e7f9b57 100644 --- a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py +++ b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py @@ -2,12 +2,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt, nowdate, add_years, cint, getdate +from frappe.utils import add_years, cint, flt, getdate + +import erpnext from erpnext.accounts.report.financial_statements import get_period_list from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses + def execute(filters=None): return ForecastingReport(filters).execute_report() diff --git a/erpnext/manufacturing/report/job_card_summary/job_card_summary.py b/erpnext/manufacturing/report/job_card_summary/job_card_summary.py index a8939051523..a7aec315ff2 100644 --- a/erpnext/manufacturing/report/job_card_summary/job_card_summary.py +++ b/erpnext/manufacturing/report/job_card_summary/job_card_summary.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate, flt -from erpnext.stock.report.stock_analytics.stock_analytics import (get_period_date_ranges, get_period) +from frappe.utils import getdate + +from erpnext.stock.report.stock_analytics.stock_analytics import get_period, get_period_date_ranges + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.py b/erpnext/manufacturing/report/production_analytics/production_analytics.py index 42c9d97cb5e..9e0978aee7f 100644 --- a/erpnext/manufacturing/report/production_analytics/production_analytics.py +++ b/erpnext/manufacturing/report/production_analytics/production_analytics.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _, scrub from frappe.utils import getdate -from erpnext.stock.report.stock_analytics.stock_analytics import (get_period_date_ranges, get_period) + +from erpnext.stock.report.stock_analytics.stock_analytics import get_period, get_period_date_ranges + def execute(filters=None): columns = get_columns(filters) diff --git a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py index 81b1791ae81..9a4d0c42db4 100644 --- a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py +++ b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.utils import flt + def execute(filters=None): columns, data = [], [] data = get_data(filters) diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py index 806d268ffde..e27270ae8b9 100644 --- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py +++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses # and bom_no is not null and bom_no !='' diff --git a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py index a12ac7f9d91..54df208346c 100644 --- a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py +++ b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns, data = [], [] data = get_data(filters) diff --git a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py index 599a738f6f6..5b2e2620fd7 100644 --- a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py +++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.utils import cint + import frappe +from frappe.utils import cint + def execute(filters=None): wo_list = get_work_orders() diff --git a/erpnext/manufacturing/report/work_order_summary/work_order_summary.py b/erpnext/manufacturing/report/work_order_summary/work_order_summary.py index d0766f9abe5..b65af33cec5 100644 --- a/erpnext/manufacturing/report/work_order_summary/work_order_summary.py +++ b/erpnext/manufacturing/report/work_order_summary/work_order_summary.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import date_diff, today, getdate, flt from frappe import _ -from erpnext.stock.report.stock_analytics.stock_analytics import (get_period_date_ranges, get_period) +from frappe.utils import date_diff, flt, getdate, today + +from erpnext.stock.report.stock_analytics.stock_analytics import get_period, get_period_date_ranges + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/modules.txt b/erpnext/modules.txt index 62f5dce8460..3ffa5f292cc 100644 --- a/erpnext/modules.txt +++ b/erpnext/modules.txt @@ -9,7 +9,6 @@ Manufacturing Stock Support Utilities -Shopping Cart Assets Portal Maintenance @@ -26,4 +25,5 @@ Quality Management Communication Loan Management Payroll -Telephony \ No newline at end of file +Telephony +E-commerce \ No newline at end of file diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.py b/erpnext/non_profit/doctype/certification_application/certification_application.py index d4fc76bbfa5..ff400c81ae3 100644 --- a/erpnext/non_profit/doctype/certification_application/certification_application.py +++ b/erpnext/non_profit/doctype/certification_application/certification_application.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CertificationApplication(Document): pass diff --git a/erpnext/non_profit/doctype/certification_application/test_certification_application.py b/erpnext/non_profit/doctype/certification_application/test_certification_application.py index 30cb8c0acdf..5e1cbf85961 100644 --- a/erpnext/non_profit/doctype/certification_application/test_certification_application.py +++ b/erpnext/non_profit/doctype/certification_application/test_certification_application.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCertificationApplication(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py index 3bc6ed74c26..0cbc2088c96 100644 --- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py +++ b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CertifiedConsultant(Document): pass diff --git a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py index 19b485db1fb..29a73881a58 100644 --- a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py +++ b/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCertifiedConsultant(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/chapter/chapter.py b/erpnext/non_profit/doctype/chapter/chapter.py index e9554b1f55c..c5c9569e74e 100644 --- a/erpnext/non_profit/doctype/chapter/chapter.py +++ b/erpnext/non_profit/doctype/chapter/chapter.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.website.website_generator import WebsiteGenerator + class Chapter(WebsiteGenerator): _website = frappe._dict( condition_field = "published", diff --git a/erpnext/non_profit/doctype/chapter/test_chapter.py b/erpnext/non_profit/doctype/chapter/test_chapter.py index d757a1f9159..04cdc277475 100644 --- a/erpnext/non_profit/doctype/chapter/test_chapter.py +++ b/erpnext/non_profit/doctype/chapter/test_chapter.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestChapter(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/chapter_member/chapter_member.py b/erpnext/non_profit/doctype/chapter_member/chapter_member.py index a1b25f2d4e2..1638294de12 100644 --- a/erpnext/non_profit/doctype/chapter_member/chapter_member.py +++ b/erpnext/non_profit/doctype/chapter_member/chapter_member.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class ChapterMember(Document): pass diff --git a/erpnext/non_profit/doctype/donation/donation.py b/erpnext/non_profit/doctype/donation/donation.py index 9aa7e13433c..e4e2b4e7d65 100644 --- a/erpnext/non_profit/doctype/donation/donation.py +++ b/erpnext/non_profit/doctype/donation/donation.py @@ -3,15 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import json + import frappe import six -import json -from frappe.model.document import Document from frappe import _ -from frappe.utils import getdate, flt, get_link_to_form from frappe.email import sendmail_to_system_managers +from frappe.model.document import Document +from frappe.utils import flt, get_link_to_form, getdate + from erpnext.non_profit.doctype.membership.membership import verify_signature + class Donation(Document): def validate(self): if not self.donor or not frappe.db.exists('Donor', self.donor): diff --git a/erpnext/non_profit/doctype/donation/donation_dashboard.py b/erpnext/non_profit/doctype/donation/donation_dashboard.py index 3da89423d37..4a16077ef47 100644 --- a/erpnext/non_profit/doctype/donation/donation_dashboard.py +++ b/erpnext/non_profit/doctype/donation/donation_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'donation', diff --git a/erpnext/non_profit/doctype/donation/test_donation.py b/erpnext/non_profit/doctype/donation/test_donation.py index b206f54523e..6b9ade9185c 100644 --- a/erpnext/non_profit/doctype/donation/test_donation.py +++ b/erpnext/non_profit/doctype/donation/test_donation.py @@ -3,10 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.non_profit.doctype.donation.donation import create_donation + class TestDonation(unittest.TestCase): def setUp(self): create_donor_type() diff --git a/erpnext/non_profit/doctype/donor/donor.py b/erpnext/non_profit/doctype/donor/donor.py index ab6a197ed51..a46163a0128 100644 --- a/erpnext/non_profit/doctype/donor/donor.py +++ b/erpnext/non_profit/doctype/donor/donor.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + from frappe.contacts.address_and_contact import load_address_and_contact +from frappe.model.document import Document + class Donor(Document): def onload(self): diff --git a/erpnext/non_profit/doctype/donor/test_donor.py b/erpnext/non_profit/doctype/donor/test_donor.py index 3b6724eb63a..5ce01998bc3 100644 --- a/erpnext/non_profit/doctype/donor/test_donor.py +++ b/erpnext/non_profit/doctype/donor/test_donor.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestDonor(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.py b/erpnext/non_profit/doctype/donor_type/donor_type.py index e9262ac2a52..4d34725d024 100644 --- a/erpnext/non_profit/doctype/donor_type/donor_type.py +++ b/erpnext/non_profit/doctype/donor_type/donor_type.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DonorType(Document): pass diff --git a/erpnext/non_profit/doctype/donor_type/test_donor_type.py b/erpnext/non_profit/doctype/donor_type/test_donor_type.py index e7939136b71..7857ec5ad21 100644 --- a/erpnext/non_profit/doctype/donor_type/test_donor_type.py +++ b/erpnext/non_profit/doctype/donor_type/test_donor_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals - import unittest + class TestDonorType(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.py b/erpnext/non_profit/doctype/grant_application/grant_application.py index b810fd027af..92a62563ab9 100644 --- a/erpnext/non_profit/doctype/grant_application/grant_application.py +++ b/erpnext/non_profit/doctype/grant_application/grant_application.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.website.website_generator import WebsiteGenerator from frappe.contacts.address_and_contact import load_address_and_contact from frappe.utils import get_url +from frappe.website.website_generator import WebsiteGenerator + class GrantApplication(WebsiteGenerator): _website = frappe._dict( diff --git a/erpnext/non_profit/doctype/grant_application/test_grant_application.py b/erpnext/non_profit/doctype/grant_application/test_grant_application.py index da16acfaacb..d15809112ab 100644 --- a/erpnext/non_profit/doctype/grant_application/test_grant_application.py +++ b/erpnext/non_profit/doctype/grant_application/test_grant_application.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestGrantApplication(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py index 67828d6efc8..f7e7f105d55 100644 --- a/erpnext/non_profit/doctype/member/member.py +++ b/erpnext/non_profit/doctype/member/member.py @@ -3,14 +3,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.utils import cint, get_link_to_form from frappe.integrations.utils import get_payment_gateway_controller +from frappe.model.document import Document +from frappe.utils import cint, get_link_to_form + from erpnext.non_profit.doctype.membership_type.membership_type import get_membership_type + class Member(Document): def onload(self): """Load address and contacts in `__onload`""" diff --git a/erpnext/non_profit/doctype/member/member_dashboard.py b/erpnext/non_profit/doctype/member/member_dashboard.py index 743db2513af..ff929a59093 100644 --- a/erpnext/non_profit/doctype/member/member_dashboard.py +++ b/erpnext/non_profit/doctype/member/member_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/non_profit/doctype/member/test_member.py b/erpnext/non_profit/doctype/member/test_member.py index 748a500deec..38ad87f2f67 100644 --- a/erpnext/non_profit/doctype/member/test_member.py +++ b/erpnext/non_profit/doctype/member/test_member.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestMember(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py index b584116df3c..b65dc8e1e37 100644 --- a/erpnext/non_profit/doctype/membership/membership.py +++ b/erpnext/non_profit/doctype/membership/membership.py @@ -3,17 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals + import json +from datetime import datetime + import frappe import six -import os -from datetime import datetime -from frappe.model.document import Document -from frappe.email import sendmail_to_system_managers -from frappe.utils import add_days, add_years, nowdate, getdate, add_months, get_link_to_form -from erpnext.non_profit.doctype.member.member import create_member from frappe import _ +from frappe.email import sendmail_to_system_managers +from frappe.model.document import Document +from frappe.utils import add_days, add_months, add_years, get_link_to_form, getdate, nowdate + import erpnext +from erpnext.non_profit.doctype.member.member import create_member + class Membership(Document): def validate(self): @@ -207,7 +210,7 @@ def get_member_based_on_subscription(subscription_id, email=None, customer_id=No try: return frappe.get_doc("Member", members[0]["name"]) - except: + except Exception: return None @@ -393,7 +396,7 @@ def notify_failure(log): """.format(get_link_to_form("Error Log", log.name)) sendmail_to_system_managers("[Important] [ERPNext] Razorpay membership webhook failed , please check.", content) - except: + except Exception: pass @@ -402,7 +405,7 @@ def get_plan_from_razorpay_id(plan_id): try: return plan[0]["name"] - except: + except Exception: return None diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py index 5ad2088fc31..5f52cdaca81 100644 --- a/erpnext/non_profit/doctype/membership/test_membership.py +++ b/erpnext/non_profit/doctype/membership/test_membership.py @@ -2,12 +2,16 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + import frappe +from frappe.utils import add_months, nowdate + import erpnext from erpnext.non_profit.doctype.member.member import create_member from erpnext.non_profit.doctype.membership.membership import update_halted_razorpay_subscription -from frappe.utils import nowdate, add_months + class TestMembership(unittest.TestCase): def setUp(self): diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.py b/erpnext/non_profit/doctype/membership_type/membership_type.py index c712b99c3b8..1b847d94b99 100644 --- a/erpnext/non_profit/doctype/membership_type/membership_type.py +++ b/erpnext/non_profit/doctype/membership_type/membership_type.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + import frappe from frappe import _ +from frappe.model.document import Document + class MembershipType(Document): def validate(self): diff --git a/erpnext/non_profit/doctype/membership_type/test_membership_type.py b/erpnext/non_profit/doctype/membership_type/test_membership_type.py index d2c9beed0df..2503ba17d1c 100644 --- a/erpnext/non_profit/doctype/membership_type/test_membership_type.py +++ b/erpnext/non_profit/doctype/membership_type/test_membership_type.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestMembershipType(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py index 50c93516adc..cb365cb6c10 100644 --- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py +++ b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.integrations.utils import get_payment_gateway_controller from frappe.model.document import Document + class NonProfitSettings(Document): @frappe.whitelist() def generate_webhook_secret(self, field="membership_webhook_secret"): diff --git a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py index 3f0ede32e59..a0a54030cc9 100644 --- a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py +++ b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestNonProfitSettings(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/volunteer/test_volunteer.py b/erpnext/non_profit/doctype/volunteer/test_volunteer.py index 6f3bee0edd9..346eac56770 100644 --- a/erpnext/non_profit/doctype/volunteer/test_volunteer.py +++ b/erpnext/non_profit/doctype/volunteer/test_volunteer.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestVolunteer(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.py b/erpnext/non_profit/doctype/volunteer/volunteer.py index 699868aeb79..6c9232b0ea1 100644 --- a/erpnext/non_profit/doctype/volunteer/volunteer.py +++ b/erpnext/non_profit/doctype/volunteer/volunteer.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + from frappe.contacts.address_and_contact import load_address_and_contact +from frappe.model.document import Document + class Volunteer(Document): def onload(self): diff --git a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py index dc9f8231944..3422ec2dec3 100644 --- a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py +++ b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class VolunteerSkill(Document): pass diff --git a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py index 78f65c731a2..2c64d21bba4 100644 --- a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py +++ b/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestVolunteerType(unittest.TestCase): pass diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py index 9776402a43f..116f5d8b52f 100644 --- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py +++ b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class VolunteerType(Document): pass diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py index 122db45ea4e..2167b651c34 100644 --- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py +++ b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import _,msgprint +from frappe import _ + def execute(filters=None): columns = get_columns(filters) diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.py b/erpnext/non_profit/web_form/certification_application/certification_application.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/non_profit/web_form/certification_application/certification_application.py +++ b/erpnext/non_profit/web_form/certification_application/certification_application.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py +++ b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.py b/erpnext/non_profit/web_form/grant_application/grant_application.py index 186722a8bf0..dab0e9fda85 100644 --- a/erpnext/non_profit/web_form/grant_application/grant_application.py +++ b/erpnext/non_profit/web_form/grant_application/grant_application.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_context(context): context.no_cache = True context.parents = [dict(label='View All ', diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e04b19a1cc2..fc178350337 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -292,6 +292,7 @@ erpnext.patches.v13_0.rename_issue_status_hold_to_on_hold erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice erpnext.patches.v13_0.update_job_card_details erpnext.patches.v13_0.update_level_in_bom #1234sswef +erpnext.patches.v13_0.create_gst_payment_entry_fields erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry erpnext.patches.v13_0.update_subscription_status_in_memberships erpnext.patches.v13_0.update_amt_in_work_order_required_items @@ -308,3 +309,6 @@ erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.custom_fields_for_taxjar_integration erpnext.patches.v13_0.set_operation_time_based_on_operating_cost erpnext.patches.v13_0.validate_options_for_data_field +erpnext.patches.v13_0.create_website_items +erpnext.patches.v13_0.populate_e_commerce_settings +erpnext.patches.v13_0.make_homepage_products_website_items diff --git a/erpnext/patches/v10_0/add_default_cash_flow_mappers.py b/erpnext/patches/v10_0/add_default_cash_flow_mappers.py index d607b2f745e..5c28597faad 100644 --- a/erpnext/patches/v10_0/add_default_cash_flow_mappers.py +++ b/erpnext/patches/v10_0/add_default_cash_flow_mappers.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe + from erpnext.setup.install import create_default_cash_flow_mapper_templates diff --git a/erpnext/patches/v10_0/delete_hub_documents.py b/erpnext/patches/v10_0/delete_hub_documents.py index f6a14998956..16c7abfc978 100644 --- a/erpnext/patches/v10_0/delete_hub_documents.py +++ b/erpnext/patches/v10_0/delete_hub_documents.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals import frappe -from frappe.model.utils.rename_field import rename_field + def execute(): for dt, dn in (("Page", "Hub"), ("DocType", "Hub Settings"), ("DocType", "Hub Category")): diff --git a/erpnext/patches/v10_0/fichier_des_ecritures_comptables_for_france.py b/erpnext/patches/v10_0/fichier_des_ecritures_comptables_for_france.py index 0315ae72a7d..a3e49577a33 100644 --- a/erpnext/patches/v10_0/fichier_des_ecritures_comptables_for_france.py +++ b/erpnext/patches/v10_0/fichier_des_ecritures_comptables_for_france.py @@ -2,9 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + from erpnext.setup.doctype.company.company import install_country_fixtures + def execute(): frappe.reload_doc('regional', 'report', 'fichier_des_ecritures_comptables_[fec]') for d in frappe.get_all('Company', filters = {'country': 'France'}): diff --git a/erpnext/patches/v10_0/migrate_daily_work_summary_settings_to_daily_work_summary_group.py b/erpnext/patches/v10_0/migrate_daily_work_summary_settings_to_daily_work_summary_group.py index daa258e8825..a3c61a5294a 100644 --- a/erpnext/patches/v10_0/migrate_daily_work_summary_settings_to_daily_work_summary_group.py +++ b/erpnext/patches/v10_0/migrate_daily_work_summary_settings_to_daily_work_summary_group.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe diff --git a/erpnext/patches/v10_0/rename_offer_letter_to_job_offer.py b/erpnext/patches/v10_0/rename_offer_letter_to_job_offer.py index f832936b10a..4fc419e302c 100644 --- a/erpnext/patches/v10_0/rename_offer_letter_to_job_offer.py +++ b/erpnext/patches/v10_0/rename_offer_letter_to_job_offer.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.table_exists("Offer Letter") and not frappe.db.table_exists("Job Offer"): frappe.rename_doc("DocType", "Offer Letter", "Job Offer", force=True) diff --git a/erpnext/patches/v10_0/rename_price_to_rate_in_pricing_rule.py b/erpnext/patches/v10_0/rename_price_to_rate_in_pricing_rule.py index a9dd3103100..1b8c6fb7ea5 100644 --- a/erpnext/patches/v10_0/rename_price_to_rate_in_pricing_rule.py +++ b/erpnext/patches/v10_0/rename_price_to_rate_in_pricing_rule.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("accounts", "doctype", "pricing_rule") diff --git a/erpnext/patches/v10_0/set_currency_in_pricing_rule.py b/erpnext/patches/v10_0/set_currency_in_pricing_rule.py index c4139312d9f..2a3f1c03bde 100644 --- a/erpnext/patches/v10_0/set_currency_in_pricing_rule.py +++ b/erpnext/patches/v10_0/set_currency_in_pricing_rule.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doctype("Pricing Rule") diff --git a/erpnext/patches/v10_0/update_translatable_fields.py b/erpnext/patches/v10_0/update_translatable_fields.py index 9d6bda71685..2c55a052173 100644 --- a/erpnext/patches/v10_0/update_translatable_fields.py +++ b/erpnext/patches/v10_0/update_translatable_fields.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe + def execute(): ''' Enable translatable in these fields diff --git a/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py b/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py index 3d1a88e800c..2d5b0c5bd4a 100644 --- a/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py +++ b/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field diff --git a/erpnext/patches/v11_0/add_default_dispatch_notification_template.py b/erpnext/patches/v11_0/add_default_dispatch_notification_template.py index f4c18955390..197b3b72676 100644 --- a/erpnext/patches/v11_0/add_default_dispatch_notification_template.py +++ b/erpnext/patches/v11_0/add_default_dispatch_notification_template.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import os import frappe diff --git a/erpnext/patches/v11_0/add_default_email_template_for_leave.py b/erpnext/patches/v11_0/add_default_email_template_for_leave.py index 0f1e4966231..f8538df2ef2 100644 --- a/erpnext/patches/v11_0/add_default_email_template_for_leave.py +++ b/erpnext/patches/v11_0/add_default_email_template_for_leave.py @@ -1,7 +1,11 @@ from __future__ import unicode_literals -import frappe, os + +import os + +import frappe from frappe import _ + def execute(): frappe.reload_doc("email", "doctype", "email_template") diff --git a/erpnext/patches/v11_0/add_expense_claim_default_account.py b/erpnext/patches/v11_0/add_expense_claim_default_account.py index a613bd88497..74b93efbf80 100644 --- a/erpnext/patches/v11_0/add_expense_claim_default_account.py +++ b/erpnext/patches/v11_0/add_expense_claim_default_account.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("setup", "doctype", "company") diff --git a/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py b/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py index a45f39d4340..9bb91dc14c1 100644 --- a/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py +++ b/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe import _ + def execute(): """ assign lft and rgt appropriately """ if "Healthcare" not in frappe.get_active_domains(): diff --git a/erpnext/patches/v11_0/add_index_on_nestedset_doctypes.py b/erpnext/patches/v11_0/add_index_on_nestedset_doctypes.py index 0243dfb38ed..08ad855e5e2 100644 --- a/erpnext/patches/v11_0/add_index_on_nestedset_doctypes.py +++ b/erpnext/patches/v11_0/add_index_on_nestedset_doctypes.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("assets", "doctype", "Location") for dt in ("Account", "Cost Center", "File", "Employee", "Location", "Task", "Customer Group", "Sales Person", "Territory"): diff --git a/erpnext/patches/v11_0/add_item_group_defaults.py b/erpnext/patches/v11_0/add_item_group_defaults.py index 2a15ad1e2a3..6849b27feee 100644 --- a/erpnext/patches/v11_0/add_item_group_defaults.py +++ b/erpnext/patches/v11_0/add_item_group_defaults.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): ''' diff --git a/erpnext/patches/v11_0/add_market_segments.py b/erpnext/patches/v11_0/add_market_segments.py index a8841ef3a44..e7cc7d1117c 100644 --- a/erpnext/patches/v11_0/add_market_segments.py +++ b/erpnext/patches/v11_0/add_market_segments.py @@ -1,9 +1,10 @@ from __future__ import unicode_literals import frappe -from frappe import _ + from erpnext.setup.setup_wizard.operations.install_fixtures import add_market_segments + def execute(): frappe.reload_doc('crm', 'doctype', 'market_segment') diff --git a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py index 83b2a4cc09e..9df1b586e30 100644 --- a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py +++ b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py @@ -1,6 +1,8 @@ import frappe + from erpnext.regional.india.setup import add_permissions + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v11_0/add_sales_stages.py b/erpnext/patches/v11_0/add_sales_stages.py index d06c6889ff7..23e48747b82 100644 --- a/erpnext/patches/v11_0/add_sales_stages.py +++ b/erpnext/patches/v11_0/add_sales_stages.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals + import frappe -from frappe import _ + from erpnext.setup.setup_wizard.operations.install_fixtures import add_sale_stages + def execute(): frappe.reload_doc('crm', 'doctype', 'sales_stage') diff --git a/erpnext/patches/v11_0/check_buying_selling_in_currency_exchange.py b/erpnext/patches/v11_0/check_buying_selling_in_currency_exchange.py index 0a1a36007e5..5eaf21220bd 100644 --- a/erpnext/patches/v11_0/check_buying_selling_in_currency_exchange.py +++ b/erpnext/patches/v11_0/check_buying_selling_in_currency_exchange.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('setup', 'doctype', 'currency_exchange') frappe.db.sql("""update `tabCurrency Exchange` set for_buying = 1, for_selling = 1""") diff --git a/erpnext/patches/v11_0/create_default_success_action.py b/erpnext/patches/v11_0/create_default_success_action.py index 31feff25b93..4a598371f82 100644 --- a/erpnext/patches/v11_0/create_default_success_action.py +++ b/erpnext/patches/v11_0/create_default_success_action.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.setup.install import create_default_success_action + def execute(): frappe.reload_doc("core", "doctype", "success_action") create_default_success_action() diff --git a/erpnext/patches/v11_0/create_department_records_for_each_company.py b/erpnext/patches/v11_0/create_department_records_for_each_company.py index e9b5950a133..7799a650405 100644 --- a/erpnext/patches/v11_0/create_department_records_for_each_company.py +++ b/erpnext/patches/v11_0/create_department_records_for_each_company.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils.nestedset import rebuild_tree + def execute(): frappe.local.lang = frappe.db.get_default("lang") or 'en' diff --git a/erpnext/patches/v11_0/create_salary_structure_assignments.py b/erpnext/patches/v11_0/create_salary_structure_assignments.py index d3ea7a3c1c0..c3cc9b6d309 100644 --- a/erpnext/patches/v11_0/create_salary_structure_assignments.py +++ b/erpnext/patches/v11_0/create_salary_structure_assignments.py @@ -2,10 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from datetime import datetime + +import frappe from frappe.utils import getdate -from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import DuplicateAssignment + +from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import ( + DuplicateAssignment, +) + def execute(): frappe.reload_doc('Payroll', 'doctype', 'Salary Structure') diff --git a/erpnext/patches/v11_0/drop_column_max_days_allowed.py b/erpnext/patches/v11_0/drop_column_max_days_allowed.py index 029f75a2258..e45d01cef58 100644 --- a/erpnext/patches/v11_0/drop_column_max_days_allowed.py +++ b/erpnext/patches/v11_0/drop_column_max_days_allowed.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists("DocType", "Leave Type"): if 'max_days_allowed' in frappe.db.get_table_columns("Leave Type"): diff --git a/erpnext/patches/v11_0/ewaybill_fields_gst_india.py b/erpnext/patches/v11_0/ewaybill_fields_gst_india.py index 4247c788e33..a59291ce420 100644 --- a/erpnext/patches/v11_0/ewaybill_fields_gst_india.py +++ b/erpnext/patches/v11_0/ewaybill_fields_gst_india.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v11_0/hr_ux_cleanups.py b/erpnext/patches/v11_0/hr_ux_cleanups.py index 8d187965011..b09f4a7e7f2 100644 --- a/erpnext/patches/v11_0/hr_ux_cleanups.py +++ b/erpnext/patches/v11_0/hr_ux_cleanups.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doctype('Employee') frappe.db.sql('update tabEmployee set first_name = employee_name') diff --git a/erpnext/patches/v11_0/inter_state_field_for_gst.py b/erpnext/patches/v11_0/inter_state_field_for_gst.py index 730eebc01ce..fa83af00655 100644 --- a/erpnext/patches/v11_0/inter_state_field_for_gst.py +++ b/erpnext/patches/v11_0/inter_state_field_for_gst.py @@ -1,6 +1,9 @@ from __future__ import unicode_literals + import frappe -from erpnext.regional.india.setup import make_custom_fields + +from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py b/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py index dfcf5ab2886..1d3f8c1204d 100644 --- a/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py +++ b/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils.nestedset import rebuild_tree + def execute(): frappe.reload_doc('assets', 'doctype', 'asset_finance_book') diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py index 29d25c9a2d4..994df721c25 100644 --- a/erpnext/patches/v11_0/make_italian_localization_fields.py +++ b/erpnext/patches/v11_0/make_italian_localization_fields.py @@ -2,10 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -from erpnext.regional.italy.setup import make_custom_fields, setup_report -from erpnext.regional.italy import state_codes + import frappe +from erpnext.regional.italy import state_codes +from erpnext.regional.italy.setup import make_custom_fields, setup_report + + def execute(): company = frappe.get_all('Company', filters = {'country': 'Italy'}) if not company: diff --git a/erpnext/patches/v11_0/make_job_card.py b/erpnext/patches/v11_0/make_job_card.py index 9c41c0b991f..e361d5a8381 100644 --- a/erpnext/patches/v11_0/make_job_card.py +++ b/erpnext/patches/v11_0/make_job_card.py @@ -2,9 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + from erpnext.manufacturing.doctype.work_order.work_order import create_job_card + def execute(): frappe.reload_doc('manufacturing', 'doctype', 'work_order') frappe.reload_doc('manufacturing', 'doctype', 'work_order_item') diff --git a/erpnext/patches/v11_0/make_location_from_warehouse.py b/erpnext/patches/v11_0/make_location_from_warehouse.py index 8c92b5180d9..e855b3ee5e1 100644 --- a/erpnext/patches/v11_0/make_location_from_warehouse.py +++ b/erpnext/patches/v11_0/make_location_from_warehouse.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils.nestedset import rebuild_tree + def execute(): if not frappe.db.get_value('Asset', {'docstatus': ('<', 2) }, 'name'): return frappe.reload_doc('assets', 'doctype', 'location') diff --git a/erpnext/patches/v11_0/make_quality_inspection_template.py b/erpnext/patches/v11_0/make_quality_inspection_template.py index 9720af41219..1c3d34ee208 100644 --- a/erpnext/patches/v11_0/make_quality_inspection_template.py +++ b/erpnext/patches/v11_0/make_quality_inspection_template.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'quality_inspection_template') frappe.reload_doc('stock', 'doctype', 'item') diff --git a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py index 6da70b4ce38..42fdf1358ad 100644 --- a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py +++ b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): ''' @@ -30,7 +32,7 @@ def execute(): buying_cost_center, selling_cost_center, expense_account, income_account, default_supplier FROM `tabItem`; ''', companies[0].name) - except: + except Exception: pass else: item_details = frappe.db.sql(""" SELECT name, default_warehouse, diff --git a/erpnext/patches/v11_0/move_leave_approvers_from_employee.py b/erpnext/patches/v11_0/move_leave_approvers_from_employee.py index ef703d0ea71..accfa5ecb39 100644 --- a/erpnext/patches/v11_0/move_leave_approvers_from_employee.py +++ b/erpnext/patches/v11_0/move_leave_approvers_from_employee.py @@ -1,8 +1,9 @@ from __future__ import unicode_literals + import frappe -from frappe import _ from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("hr", "doctype", "department_approver") frappe.reload_doc("hr", "doctype", "employee") diff --git a/erpnext/patches/v11_0/rebuild_tree_for_company.py b/erpnext/patches/v11_0/rebuild_tree_for_company.py index 4cb74c7256c..6caca4730c2 100644 --- a/erpnext/patches/v11_0/rebuild_tree_for_company.py +++ b/erpnext/patches/v11_0/rebuild_tree_for_company.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.utils.nestedset import rebuild_tree + def execute(): frappe.reload_doc("setup", "doctype", "company") rebuild_tree('Company', 'parent_company') diff --git a/erpnext/patches/v11_0/redesign_healthcare_billing_work_flow.py b/erpnext/patches/v11_0/redesign_healthcare_billing_work_flow.py index 7c8a822fa22..b1ed0f598c6 100644 --- a/erpnext/patches/v11_0/redesign_healthcare_billing_work_flow.py +++ b/erpnext/patches/v11_0/redesign_healthcare_billing_work_flow.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from frappe.modules import get_doctype_module, scrub + from erpnext.domains.healthcare import data -from frappe.modules import scrub, get_doctype_module sales_invoice_referenced_doc = { "Patient Appointment": "sales_invoice", diff --git a/erpnext/patches/v11_0/refactor_erpnext_shopify.py b/erpnext/patches/v11_0/refactor_erpnext_shopify.py index 340e9fc8bf7..2add7211090 100644 --- a/erpnext/patches/v11_0/refactor_erpnext_shopify.py +++ b/erpnext/patches/v11_0/refactor_erpnext_shopify.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.installer import remove_from_installed_apps + def execute(): frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_settings') frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_tax_account') diff --git a/erpnext/patches/v11_0/remove_barcodes_field_from_copy_fields_to_variants.py b/erpnext/patches/v11_0/remove_barcodes_field_from_copy_fields_to_variants.py index 97ddd41ddb6..caf74f578de 100644 --- a/erpnext/patches/v11_0/remove_barcodes_field_from_copy_fields_to_variants.py +++ b/erpnext/patches/v11_0/remove_barcodes_field_from_copy_fields_to_variants.py @@ -1,5 +1,6 @@ import frappe + def execute(): '''Remove barcodes field from "Copy Fields to Variants" table because barcodes must be unique''' diff --git a/erpnext/patches/v11_0/remove_modules_setup_page.py b/erpnext/patches/v11_0/remove_modules_setup_page.py index bb0bdf59da1..eab3237878e 100644 --- a/erpnext/patches/v11_0/remove_modules_setup_page.py +++ b/erpnext/patches/v11_0/remove_modules_setup_page.py @@ -2,7 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.delete_doc("Page", "modules_setup") diff --git a/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py b/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py index 8eb70167447..5b2c2863f2f 100644 --- a/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py +++ b/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe # this patch should have been included with this PR https://github.com/frappe/erpnext/pull/14302 diff --git a/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py b/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py index 923b23048df..707dff75e24 100644 --- a/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py +++ b/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe diff --git a/erpnext/patches/v11_0/rename_bom_wo_fields.py b/erpnext/patches/v11_0/rename_bom_wo_fields.py index 0e6036b0740..4ad6ea9999d 100644 --- a/erpnext/patches/v11_0/rename_bom_wo_fields.py +++ b/erpnext/patches/v11_0/rename_bom_wo_fields.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): # updating column value to handle field change from Data to Currency changed_field = "base_scrap_material_cost" diff --git a/erpnext/patches/v11_0/rename_duplicate_item_code_values.py b/erpnext/patches/v11_0/rename_duplicate_item_code_values.py index 00ab562c353..61f3856e8eb 100644 --- a/erpnext/patches/v11_0/rename_duplicate_item_code_values.py +++ b/erpnext/patches/v11_0/rename_duplicate_item_code_values.py @@ -1,5 +1,6 @@ import frappe + def execute(): items = [] items = frappe.db.sql("""select item_code from `tabItem` group by item_code having count(*) > 1""", as_dict=True) diff --git a/erpnext/patches/v11_0/rename_field_max_days_allowed.py b/erpnext/patches/v11_0/rename_field_max_days_allowed.py index 4e99fac8224..48f73fb2f41 100644 --- a/erpnext/patches/v11_0/rename_field_max_days_allowed.py +++ b/erpnext/patches/v11_0/rename_field_max_days_allowed.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.db.sql(""" UPDATE `tabLeave Type` diff --git a/erpnext/patches/v11_0/rename_health_insurance.py b/erpnext/patches/v11_0/rename_health_insurance.py index 06fc6151675..a4f53b078e1 100644 --- a/erpnext/patches/v11_0/rename_health_insurance.py +++ b/erpnext/patches/v11_0/rename_health_insurance.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.rename_doc('DocType', 'Health Insurance', 'Employee Health Insurance', force=True) frappe.reload_doc('hr', 'doctype', 'employee_health_insurance') diff --git a/erpnext/patches/v11_0/rename_healthcare_doctype_and_fields.py b/erpnext/patches/v11_0/rename_healthcare_doctype_and_fields.py index 9705681b33f..7a8c52f102f 100644 --- a/erpnext/patches/v11_0/rename_healthcare_doctype_and_fields.py +++ b/erpnext/patches/v11_0/rename_healthcare_doctype_and_fields.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module +from frappe.modules import get_doctype_module, scrub field_rename_map = { "Patient Encounter": [ diff --git a/erpnext/patches/v11_0/rename_healthcare_fields.py b/erpnext/patches/v11_0/rename_healthcare_fields.py index 9aeb433cff8..5c96367a737 100644 --- a/erpnext/patches/v11_0/rename_healthcare_fields.py +++ b/erpnext/patches/v11_0/rename_healthcare_fields.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module +from frappe.modules import get_doctype_module, scrub lab_test_name = ["test_name", "lab_test_name"] lab_test_code = ["test_code", "lab_test_code"] diff --git a/erpnext/patches/v11_0/rename_members_with_naming_series.py b/erpnext/patches/v11_0/rename_members_with_naming_series.py index 84f5518926f..a3d7970aa1f 100644 --- a/erpnext/patches/v11_0/rename_members_with_naming_series.py +++ b/erpnext/patches/v11_0/rename_members_with_naming_series.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("non_profit", "doctype", "member") old_named_members = frappe.get_all("Member", filters = {"name": ("not like", "MEM-%")}) diff --git a/erpnext/patches/v11_0/rename_overproduction_percent_field.py b/erpnext/patches/v11_0/rename_overproduction_percent_field.py index fbf925d955c..c7124af2e45 100644 --- a/erpnext/patches/v11_0/rename_overproduction_percent_field.py +++ b/erpnext/patches/v11_0/rename_overproduction_percent_field.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -from frappe.model.utils.rename_field import rename_field + import frappe +from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc('manufacturing', 'doctype', 'manufacturing_settings') diff --git a/erpnext/patches/v11_0/rename_production_order_to_work_order.py b/erpnext/patches/v11_0/rename_production_order_to_work_order.py index 2f620f413ba..995f1affe4e 100644 --- a/erpnext/patches/v11_0/rename_production_order_to_work_order.py +++ b/erpnext/patches/v11_0/rename_production_order_to_work_order.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.rename_doc('DocType', 'Production Order', 'Work Order', force=True) frappe.reload_doc('manufacturing', 'doctype', 'work_order') diff --git a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py index c4b3838c71d..2e53fb832fe 100644 --- a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py +++ b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py @@ -1,9 +1,11 @@ from __future__ import unicode_literals + import frappe -from frappe.model.utils.rename_field import rename_field from frappe import _ +from frappe.model.utils.rename_field import rename_field from frappe.utils.nestedset import rebuild_tree + def execute(): if frappe.db.table_exists("Supplier Group"): frappe.reload_doc('setup', 'doctype', 'supplier_group') diff --git a/erpnext/patches/v11_0/renamed_from_to_fields_in_project.py b/erpnext/patches/v11_0/renamed_from_to_fields_in_project.py index d5ca4cc5749..894aaee5f0b 100644 --- a/erpnext/patches/v11_0/renamed_from_to_fields_in_project.py +++ b/erpnext/patches/v11_0/renamed_from_to_fields_in_project.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc('projects', 'doctype', 'project') diff --git a/erpnext/patches/v11_0/reset_publish_in_hub_for_all_items.py b/erpnext/patches/v11_0/reset_publish_in_hub_for_all_items.py index 56e95e03286..a664baf6dd6 100644 --- a/erpnext/patches/v11_0/reset_publish_in_hub_for_all_items.py +++ b/erpnext/patches/v11_0/reset_publish_in_hub_for_all_items.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'item') frappe.db.sql("""update `tabItem` set publish_in_hub = 0""") diff --git a/erpnext/patches/v11_0/set_default_email_template_in_hr.py b/erpnext/patches/v11_0/set_default_email_template_in_hr.py index 46223761095..ff754247fba 100644 --- a/erpnext/patches/v11_0/set_default_email_template_in_hr.py +++ b/erpnext/patches/v11_0/set_default_email_template_in_hr.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals -from frappe import _ + import frappe +from frappe import _ + def execute(): hr_settings = frappe.get_single("HR Settings") diff --git a/erpnext/patches/v11_0/set_department_for_doctypes.py b/erpnext/patches/v11_0/set_department_for_doctypes.py index 175d2a189f3..c9699655db3 100644 --- a/erpnext/patches/v11_0/set_department_for_doctypes.py +++ b/erpnext/patches/v11_0/set_department_for_doctypes.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe # Set department value based on employee value diff --git a/erpnext/patches/v11_0/set_missing_gst_hsn_code.py b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py index 8f8a545c410..7a0a9890252 100644 --- a/erpnext/patches/v11_0/set_missing_gst_hsn_code.py +++ b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html + def execute(): company = frappe.db.sql_list("select name from tabCompany where country = 'India'") if not company: diff --git a/erpnext/patches/v11_0/set_salary_component_properties.py b/erpnext/patches/v11_0/set_salary_component_properties.py index d8ce31f3076..b70dc357aa7 100644 --- a/erpnext/patches/v11_0/set_salary_component_properties.py +++ b/erpnext/patches/v11_0/set_salary_component_properties.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('Payroll', 'doctype', 'salary_detail') frappe.reload_doc('Payroll', 'doctype', 'salary_component') diff --git a/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py b/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py index d0cabb38359..da4d4bd943a 100644 --- a/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py +++ b/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.workflow import get_workflow_name + def execute(): for doctype in ['Expense Claim', 'Leave Application']: diff --git a/erpnext/patches/v11_0/set_user_permissions_for_department.py b/erpnext/patches/v11_0/set_user_permissions_for_department.py index 2f90f14db3e..7840d5e0feb 100644 --- a/erpnext/patches/v11_0/set_user_permissions_for_department.py +++ b/erpnext/patches/v11_0/set_user_permissions_for_department.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): user_permissions = frappe.db.sql("""select name, for_value from `tabUser Permission` where allow='Department'""", as_dict=1) diff --git a/erpnext/patches/v11_0/skip_user_permission_check_for_department.py b/erpnext/patches/v11_0/skip_user_permission_check_for_department.py index 4e72917547b..66d1b6b40ab 100644 --- a/erpnext/patches/v11_0/skip_user_permission_check_for_department.py +++ b/erpnext/patches/v11_0/skip_user_permission_check_for_department.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe from frappe.desk.form.linked_with import get_linked_doctypes diff --git a/erpnext/patches/v11_0/uom_conversion_data.py b/erpnext/patches/v11_0/uom_conversion_data.py index 91470b3558a..a408d86b9a7 100644 --- a/erpnext/patches/v11_0/uom_conversion_data.py +++ b/erpnext/patches/v11_0/uom_conversion_data.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals -import frappe, json + +import frappe + def execute(): from erpnext.setup.setup_wizard.operations.install_fixtures import add_uom_data diff --git a/erpnext/patches/v11_0/update_account_type_in_party_type.py b/erpnext/patches/v11_0/update_account_type_in_party_type.py index dabaeffc94a..e51874f48a0 100644 --- a/erpnext/patches/v11_0/update_account_type_in_party_type.py +++ b/erpnext/patches/v11_0/update_account_type_in_party_type.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('setup', 'doctype', 'party_type') party_types = {'Customer': 'Receivable', 'Supplier': 'Payable', diff --git a/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py b/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py index 799e91a3e22..bfcfc9f6f44 100644 --- a/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py +++ b/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'item') frappe.db.sql(""" update `tabItem` set include_item_in_manufacturing = 1 diff --git a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py index 37a616c7021..c3b18bd9817 100644 --- a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py +++ b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('buying', 'doctype', 'buying_settings') frappe.db.set_value('Buying Settings', None, 'backflush_raw_materials_of_subcontract_based_on', 'BOM') diff --git a/erpnext/patches/v11_0/update_brand_in_item_price.py b/erpnext/patches/v11_0/update_brand_in_item_price.py index 977d84fefe8..a489378895d 100644 --- a/erpnext/patches/v11_0/update_brand_in_item_price.py +++ b/erpnext/patches/v11_0/update_brand_in_item_price.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'item_price') diff --git a/erpnext/patches/v11_0/update_delivery_trip_status.py b/erpnext/patches/v11_0/update_delivery_trip_status.py index 42f017e04d2..da259582747 100755 --- a/erpnext/patches/v11_0/update_delivery_trip_status.py +++ b/erpnext/patches/v11_0/update_delivery_trip_status.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('setup', 'doctype', 'global_defaults', force=True) frappe.reload_doc('stock', 'doctype', 'delivery_trip') diff --git a/erpnext/patches/v11_0/update_department_lft_rgt.py b/erpnext/patches/v11_0/update_department_lft_rgt.py index 2b382037109..f7ecf6e4523 100644 --- a/erpnext/patches/v11_0/update_department_lft_rgt.py +++ b/erpnext/patches/v11_0/update_department_lft_rgt.py @@ -4,6 +4,7 @@ import frappe from frappe import _ from frappe.utils.nestedset import rebuild_tree + def execute(): """ assign lft and rgt appropriately """ frappe.reload_doc("hr", "doctype", "department") diff --git a/erpnext/patches/v11_0/update_hub_url.py b/erpnext/patches/v11_0/update_hub_url.py index 6c6ca3c5c28..c89b9b50607 100644 --- a/erpnext/patches/v11_0/update_hub_url.py +++ b/erpnext/patches/v11_0/update_hub_url.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('hub_node', 'doctype', 'Marketplace Settings') frappe.db.set_value('Marketplace Settings', 'Marketplace Settings', 'marketplace_url', 'https://hubmarket.org') diff --git a/erpnext/patches/v11_0/update_sales_partner_type.py b/erpnext/patches/v11_0/update_sales_partner_type.py index b393926b237..1369805349d 100644 --- a/erpnext/patches/v11_0/update_sales_partner_type.py +++ b/erpnext/patches/v11_0/update_sales_partner_type.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe import _ + def execute(): from erpnext.setup.setup_wizard.operations.install_fixtures import default_sales_partner_type diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py index 9407256acfa..e79a5f9e6bc 100644 --- a/erpnext/patches/v11_0/update_total_qty_field.py +++ b/erpnext/patches/v11_0/update_total_qty_field.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('buying', 'doctype', 'purchase_order') frappe.reload_doc('buying', 'doctype', 'supplier_quotation') diff --git a/erpnext/patches/v11_1/delete_bom_browser.py b/erpnext/patches/v11_1/delete_bom_browser.py index 2892674d374..aad3df267c8 100644 --- a/erpnext/patches/v11_1/delete_bom_browser.py +++ b/erpnext/patches/v11_1/delete_bom_browser.py @@ -2,7 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.delete_doc_if_exists('Page', 'bom-browser') diff --git a/erpnext/patches/v11_1/delete_scheduling_tool.py b/erpnext/patches/v11_1/delete_scheduling_tool.py index b7ad28a3fd6..56d0dbf1a1f 100644 --- a/erpnext/patches/v11_1/delete_scheduling_tool.py +++ b/erpnext/patches/v11_1/delete_scheduling_tool.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists("DocType", "Scheduling Tool"): frappe.delete_doc("DocType", "Scheduling Tool", ignore_permissions=True) diff --git a/erpnext/patches/v11_1/make_job_card_time_logs.py b/erpnext/patches/v11_1/make_job_card_time_logs.py index b706e5c1ffb..db0c3454c74 100644 --- a/erpnext/patches/v11_1/make_job_card_time_logs.py +++ b/erpnext/patches/v11_1/make_job_card_time_logs.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('manufacturing', 'doctype', 'job_card_time_log') diff --git a/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py b/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py index fc3ec74083a..9ea6cd82c9c 100644 --- a/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py +++ b/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doctype("Quotation") frappe.db.sql(""" UPDATE `tabQuotation` set party_name = lead WHERE quotation_to = 'Lead' """) diff --git a/erpnext/patches/v11_1/rename_depends_on_lwp.py b/erpnext/patches/v11_1/rename_depends_on_lwp.py index 4c4b14fd4e7..95a8225832c 100644 --- a/erpnext/patches/v11_1/rename_depends_on_lwp.py +++ b/erpnext/patches/v11_1/rename_depends_on_lwp.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import scrub from frappe.model.utils.rename_field import rename_field + def execute(): for doctype in ("Salary Component", "Salary Detail"): if "depends_on_lwp" in frappe.db.get_table_columns(doctype): diff --git a/erpnext/patches/v11_1/renamed_delayed_item_report.py b/erpnext/patches/v11_1/renamed_delayed_item_report.py index 8e8725c8af6..21285637c4e 100644 --- a/erpnext/patches/v11_1/renamed_delayed_item_report.py +++ b/erpnext/patches/v11_1/renamed_delayed_item_report.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): for report in ["Delayed Order Item Summary", "Delayed Order Summary"]: if frappe.db.exists("Report", report): diff --git a/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py b/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py index b13239f7d12..4325490c793 100644 --- a/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py +++ b/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): stock_settings = frappe.get_doc('Stock Settings') if stock_settings.default_warehouse and not frappe.db.exists("Warehouse", stock_settings.default_warehouse): diff --git a/erpnext/patches/v11_1/set_missing_opportunity_from.py b/erpnext/patches/v11_1/set_missing_opportunity_from.py index cb444b2e5dd..6569200a14c 100644 --- a/erpnext/patches/v11_1/set_missing_opportunity_from.py +++ b/erpnext/patches/v11_1/set_missing_opportunity_from.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doctype("Opportunity") diff --git a/erpnext/patches/v11_1/set_missing_title_for_quotation.py b/erpnext/patches/v11_1/set_missing_title_for_quotation.py index e2ef3433d3e..93d9f0e7d89 100644 --- a/erpnext/patches/v11_1/set_missing_title_for_quotation.py +++ b/erpnext/patches/v11_1/set_missing_title_for_quotation.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doctype("Quotation") # update customer_name from Customer document if quotation_to is set to Customer diff --git a/erpnext/patches/v11_1/set_salary_details_submittable.py b/erpnext/patches/v11_1/set_salary_details_submittable.py index 6d847ec3d05..4a4cf302575 100644 --- a/erpnext/patches/v11_1/set_salary_details_submittable.py +++ b/erpnext/patches/v11_1/set_salary_details_submittable.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql(""" update `tabSalary Structure` ss, `tabSalary Detail` sd diff --git a/erpnext/patches/v11_1/set_status_for_material_request_type_manufacture.py b/erpnext/patches/v11_1/set_status_for_material_request_type_manufacture.py index ec01fbb642e..64db97e92bc 100644 --- a/erpnext/patches/v11_1/set_status_for_material_request_type_manufacture.py +++ b/erpnext/patches/v11_1/set_status_for_material_request_type_manufacture.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql(""" update `tabMaterial Request` diff --git a/erpnext/patches/v11_1/set_variant_based_on.py b/erpnext/patches/v11_1/set_variant_based_on.py index 49a9a177246..b69767d7ea4 100644 --- a/erpnext/patches/v11_1/set_variant_based_on.py +++ b/erpnext/patches/v11_1/set_variant_based_on.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql("""update tabItem set variant_based_on = 'Item Attribute' where ifnull(variant_based_on, '') = '' diff --git a/erpnext/patches/v11_1/setup_guardian_role.py b/erpnext/patches/v11_1/setup_guardian_role.py index 6ccfed9617c..bb33f19e9cf 100644 --- a/erpnext/patches/v11_1/setup_guardian_role.py +++ b/erpnext/patches/v11_1/setup_guardian_role.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if 'Education' in frappe.get_active_domains() and not frappe.db.exists("Role", "Guardian"): doc = frappe.new_doc("Role") diff --git a/erpnext/patches/v11_1/update_bank_transaction_status.py b/erpnext/patches/v11_1/update_bank_transaction_status.py index 354e636c9b0..33007afcd8c 100644 --- a/erpnext/patches/v11_1/update_bank_transaction_status.py +++ b/erpnext/patches/v11_1/update_bank_transaction_status.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "bank_transaction") diff --git a/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py b/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py index 8c360ad9353..22dabae7d2e 100644 --- a/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py +++ b/erpnext/patches/v11_1/update_default_supplier_in_item_defaults.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): ''' default supplier was not set in the item defaults for multi company instance, diff --git a/erpnext/patches/v11_1/woocommerce_set_creation_user.py b/erpnext/patches/v11_1/woocommerce_set_creation_user.py index 074b904002c..e7218b1ade5 100644 --- a/erpnext/patches/v11_1/woocommerce_set_creation_user.py +++ b/erpnext/patches/v11_1/woocommerce_set_creation_user.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.utils import cint + def execute(): frappe.reload_doc("erpnext_integrations", "doctype","woocommerce_settings") doc = frappe.get_doc("Woocommerce Settings") diff --git a/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py b/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py index 712eb4f61c2..98e7d1db7a6 100644 --- a/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py +++ b/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py b/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py index 855d21dd992..384a1f5022a 100644 --- a/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py +++ b/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("setup", "doctype", "company") if frappe.db.has_column('Company', 'default_terms'): diff --git a/erpnext/patches/v12_0/add_document_type_field_for_italy_einvoicing.py b/erpnext/patches/v12_0/add_document_type_field_for_italy_einvoicing.py index 6fe578dbd95..7f39dfef59d 100644 --- a/erpnext/patches/v12_0/add_document_type_field_for_italy_einvoicing.py +++ b/erpnext/patches/v12_0/add_document_type_field_for_italy_einvoicing.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'Italy'}) diff --git a/erpnext/patches/v12_0/add_einvoice_status_field.py b/erpnext/patches/v12_0/add_einvoice_status_field.py index 2dfd30714c8..aeff9ca8413 100644 --- a/erpnext/patches/v12_0/add_einvoice_status_field.py +++ b/erpnext/patches/v12_0/add_einvoice_status_field.py @@ -1,8 +1,11 @@ from __future__ import unicode_literals + import json + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py b/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py index c1c11e26006..e837786138f 100644 --- a/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py +++ b/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/add_eway_bill_in_delivery_note.py b/erpnext/patches/v12_0/add_eway_bill_in_delivery_note.py index cf1ed3676bf..973da895623 100644 --- a/erpnext/patches/v12_0/add_eway_bill_in_delivery_note.py +++ b/erpnext/patches/v12_0/add_eway_bill_in_delivery_note.py @@ -1,6 +1,7 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/add_ewaybill_validity_field.py b/erpnext/patches/v12_0/add_ewaybill_validity_field.py index f29b71437e8..247140d21d0 100644 --- a/erpnext/patches/v12_0/add_ewaybill_validity_field.py +++ b/erpnext/patches/v12_0/add_ewaybill_validity_field.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py index a0b1f87d61b..e05c8211c03 100644 --- a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py +++ b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/add_gst_category_in_delivery_note.py b/erpnext/patches/v12_0/add_gst_category_in_delivery_note.py index c90819238c8..30e47cb333c 100644 --- a/erpnext/patches/v12_0/add_gst_category_in_delivery_note.py +++ b/erpnext/patches/v12_0/add_gst_category_in_delivery_note.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/add_permission_in_lower_deduction.py b/erpnext/patches/v12_0/add_permission_in_lower_deduction.py index 2e42368b152..1d77e5ad3d1 100644 --- a/erpnext/patches/v12_0/add_permission_in_lower_deduction.py +++ b/erpnext/patches/v12_0/add_permission_in_lower_deduction.py @@ -1,6 +1,7 @@ import frappe from frappe.permissions import add_permission, update_permission_property + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/add_state_code_for_ladakh.py b/erpnext/patches/v12_0/add_state_code_for_ladakh.py index 29a7b4bd602..6722b7bcef0 100644 --- a/erpnext/patches/v12_0/add_state_code_for_ladakh.py +++ b/erpnext/patches/v12_0/add_state_code_for_ladakh.py @@ -1,6 +1,8 @@ import frappe + from erpnext.regional.india import states + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/add_taxjar_integration_field.py b/erpnext/patches/v12_0/add_taxjar_integration_field.py index 4c823e13bdf..d10a6d79f29 100644 --- a/erpnext/patches/v12_0/add_taxjar_integration_field.py +++ b/erpnext/patches/v12_0/add_taxjar_integration_field.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import frappe + from erpnext.regional.united_states.setup import make_custom_fields diff --git a/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py index 893f7a4909e..c3a422c49e5 100644 --- a/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py +++ b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'item_variant_attribute') frappe.db.sql(''' 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 index f171542df16..02fbe62837a 100644 --- a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -1,7 +1,9 @@ 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') diff --git a/erpnext/patches/v12_0/create_default_energy_point_rules.py b/erpnext/patches/v12_0/create_default_energy_point_rules.py index 93d2576bb6d..35eaca7f400 100644 --- a/erpnext/patches/v12_0/create_default_energy_point_rules.py +++ b/erpnext/patches/v12_0/create_default_energy_point_rules.py @@ -1,6 +1,8 @@ import frappe + from erpnext.setup.install import create_default_energy_point_rules + def execute(): frappe.reload_doc('social', 'doctype', 'energy_point_rule') create_default_energy_point_rules() diff --git a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py index 23a8f24d780..65265c4c8e8 100644 --- a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py +++ b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.regional.united_states.setup import make_custom_fields + def execute(): frappe.reload_doc('accounts', 'doctype', 'allowed_to_transact_with', force=True) diff --git a/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py b/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py index a6230f42771..9267ebffb27 100644 --- a/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py +++ b/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py @@ -1,9 +1,12 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.custom.doctype.property_setter.property_setter import make_property_setter + from erpnext.regional.india.utils import get_gst_accounts + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}, fields=['name']) if not company: diff --git a/erpnext/patches/v12_0/create_taxable_value_field.py b/erpnext/patches/v12_0/create_taxable_value_field.py index b9ee81df50e..40de8d8aef2 100644 --- a/erpnext/patches/v12_0/create_taxable_value_field.py +++ b/erpnext/patches/v12_0/create_taxable_value_field.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/delete_priority_property_setter.py b/erpnext/patches/v12_0/delete_priority_property_setter.py index 163855729df..cacc463d4b4 100644 --- a/erpnext/patches/v12_0/delete_priority_property_setter.py +++ b/erpnext/patches/v12_0/delete_priority_property_setter.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.db.sql(""" DELETE FROM `tabProperty Setter` diff --git a/erpnext/patches/v12_0/fix_percent_complete_for_projects.py b/erpnext/patches/v12_0/fix_percent_complete_for_projects.py index 3622df6bc81..36f51bca60d 100644 --- a/erpnext/patches/v12_0/fix_percent_complete_for_projects.py +++ b/erpnext/patches/v12_0/fix_percent_complete_for_projects.py @@ -1,6 +1,7 @@ import frappe from frappe.utils import flt + def execute(): for project in frappe.get_all("Project", fields=["name", "percent_complete_method"]): total = frappe.db.count('Task', dict(project=project.name)) diff --git a/erpnext/patches/v12_0/fix_quotation_expired_status.py b/erpnext/patches/v12_0/fix_quotation_expired_status.py index ac7e82d2d0d..e5c4b8c524f 100644 --- a/erpnext/patches/v12_0/fix_quotation_expired_status.py +++ b/erpnext/patches/v12_0/fix_quotation_expired_status.py @@ -1,5 +1,6 @@ import frappe + def execute(): # fixes status of quotations which have status 'Expired' despite having valid sales order created diff --git a/erpnext/patches/v12_0/generate_leave_ledger_entries.py b/erpnext/patches/v12_0/generate_leave_ledger_entries.py index fe072d7eb96..aed56d621b8 100644 --- a/erpnext/patches/v12_0/generate_leave_ledger_entries.py +++ b/erpnext/patches/v12_0/generate_leave_ledger_entries.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils import getdate, today + def execute(): """ Generates leave ledger entries for leave allocation/application/encashment for last allocation """ diff --git a/erpnext/patches/v12_0/make_item_manufacturer.py b/erpnext/patches/v12_0/make_item_manufacturer.py index ebc28320aea..cfc2472e9e2 100644 --- a/erpnext/patches/v12_0/make_item_manufacturer.py +++ b/erpnext/patches/v12_0/make_item_manufacturer.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("stock", "doctype", "item_manufacturer") diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py index a670adebfd6..3e9d429ed18 100644 --- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py +++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('accounts', 'doctype', 'bank', force=1) diff --git a/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py index c9293b9b63c..2662632b52b 100644 --- a/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py +++ b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): ''' Move credit limit and bypass credit limit to the child table of customer credit limit ''' frappe.reload_doc("Selling", "doctype", "Customer Credit Limit") diff --git a/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py b/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py index 6013eaa29c6..55f5cd52a35 100644 --- a/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py +++ b/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): ''' Move from due_advance_amount to pending_amount ''' diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index 5c3fa5991c9..677a564af0d 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -1,7 +1,9 @@ -import frappe import json -from six import iteritems + +import frappe from frappe.model.naming import make_autoname +from six import iteritems + def execute(): if "tax_type" not in frappe.db.get_table_columns("Item Tax"): diff --git a/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py b/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py index d2bcb12070c..dafea280c28 100644 --- a/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py +++ b/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe diff --git a/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py index 97badf355d9..72f4df5cabc 100644 --- a/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py +++ b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("setup", "doctype", "target_detail") diff --git a/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py b/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py index 46794bebe70..a19e9a96dba 100644 --- a/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py +++ b/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py @@ -1,6 +1,9 @@ from __future__ import unicode_literals + import frappe -from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty + +from erpnext.stock.stock_balance import get_indented_qty, update_bin_qty + def execute(): bin_details = frappe.db.sql(""" diff --git a/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py b/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py index be884f94d15..fba41184159 100644 --- a/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py +++ b/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals + import frappe -from erpnext.regional.india.setup import make_custom_fields + def execute(): frappe.reload_doc("accounts", "doctype", "tax_category") diff --git a/erpnext/patches/v12_0/remove_denied_leaves_from_leave_ledger.py b/erpnext/patches/v12_0/remove_denied_leaves_from_leave_ledger.py index 4fcffb702a4..f6a1984e17a 100644 --- a/erpnext/patches/v12_0/remove_denied_leaves_from_leave_ledger.py +++ b/erpnext/patches/v12_0/remove_denied_leaves_from_leave_ledger.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import getdate, today + def execute(): ''' Delete leave ledger entry created diff --git a/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py b/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py index 6b1b601db19..6fa1c04dad3 100644 --- a/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py +++ b/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): """Delete duplicate leave ledger entries of type allocation created.""" frappe.reload_doc('hr', 'doctype', 'leave_ledger_entry') diff --git a/erpnext/patches/v12_0/remove_patient_medical_record_page.py b/erpnext/patches/v12_0/remove_patient_medical_record_page.py index 904bfe4bf19..bf71c4810ff 100644 --- a/erpnext/patches/v12_0/remove_patient_medical_record_page.py +++ b/erpnext/patches/v12_0/remove_patient_medical_record_page.py @@ -1,7 +1,9 @@ # Copyright (c) 2019 from __future__ import unicode_literals + import frappe + def execute(): frappe.delete_doc("Page", "medical_record") diff --git a/erpnext/patches/v12_0/rename_account_type_doctype.py b/erpnext/patches/v12_0/rename_account_type_doctype.py index 9a08ad45213..27357a8ef15 100644 --- a/erpnext/patches/v12_0/rename_account_type_doctype.py +++ b/erpnext/patches/v12_0/rename_account_type_doctype.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.rename_doc('DocType', 'Account Type', 'Bank Account Type', force=True) frappe.rename_doc('DocType', 'Account Subtype', 'Bank Account Subtype', force=True) diff --git a/erpnext/patches/v12_0/rename_bank_account_field_in_journal_entry_account.py b/erpnext/patches/v12_0/rename_bank_account_field_in_journal_entry_account.py index 7489ea30a09..7e02fff4d82 100644 --- a/erpnext/patches/v12_0/rename_bank_account_field_in_journal_entry_account.py +++ b/erpnext/patches/v12_0/rename_bank_account_field_in_journal_entry_account.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): ''' Change the fieldname from bank_account_no to bank_account ''' if not frappe.get_meta("Journal Entry Account").has_field("bank_account"): diff --git a/erpnext/patches/v12_0/rename_bank_reconciliation.py b/erpnext/patches/v12_0/rename_bank_reconciliation.py index 2efa854fba9..5c79ce2a81b 100644 --- a/erpnext/patches/v12_0/rename_bank_reconciliation.py +++ b/erpnext/patches/v12_0/rename_bank_reconciliation.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.table_exists("Bank Reconciliation"): frappe.rename_doc('DocType', 'Bank Reconciliation', 'Bank Clearance', force=True) diff --git a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py index 978b1c92b96..629cd5bda66 100644 --- a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py +++ b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py @@ -3,6 +3,7 @@ import frappe + def _rename_single_field(**kwargs): count = frappe.db.sql("SELECT COUNT(*) FROM tabSingles WHERE doctype='{doctype}' AND field='{new_name}';".format(**kwargs))[0][0] #nosec if count == 0: diff --git a/erpnext/patches/v12_0/rename_lost_reason_detail.py b/erpnext/patches/v12_0/rename_lost_reason_detail.py index c71b91c9256..337302a3c18 100644 --- a/erpnext/patches/v12_0/rename_lost_reason_detail.py +++ b/erpnext/patches/v12_0/rename_lost_reason_detail.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists("DocType", "Lost Reason Detail"): frappe.reload_doc("crm", "doctype", "opportunity_lost_reason") diff --git a/erpnext/patches/v12_0/rename_mws_settings_fields.py b/erpnext/patches/v12_0/rename_mws_settings_fields.py index e08e3769153..d5bf38d204d 100644 --- a/erpnext/patches/v12_0/rename_mws_settings_fields.py +++ b/erpnext/patches/v12_0/rename_mws_settings_fields.py @@ -3,6 +3,7 @@ import frappe + def execute(): count = frappe.db.sql("SELECT COUNT(*) FROM `tabSingles` WHERE doctype='Amazon MWS Settings' AND field='enable_sync';")[0][0] if count == 0: diff --git a/erpnext/patches/v12_0/rename_pos_closing_doctype.py b/erpnext/patches/v12_0/rename_pos_closing_doctype.py index 9d8626b8527..e6fb1f31e16 100644 --- a/erpnext/patches/v12_0/rename_pos_closing_doctype.py +++ b/erpnext/patches/v12_0/rename_pos_closing_doctype.py @@ -1,8 +1,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.table_exists("POS Closing Voucher"): if not frappe.db.exists("DocType", "POS Closing Entry"): diff --git a/erpnext/patches/v12_0/rename_pricing_rule_child_doctypes.py b/erpnext/patches/v12_0/rename_pricing_rule_child_doctypes.py index b9ad622b0ea..4bf3840b783 100644 --- a/erpnext/patches/v12_0/rename_pricing_rule_child_doctypes.py +++ b/erpnext/patches/v12_0/rename_pricing_rule_child_doctypes.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe doctypes = { diff --git a/erpnext/patches/v12_0/rename_tolerance_fields.py b/erpnext/patches/v12_0/rename_tolerance_fields.py index 20b096331ed..ca2427bc3dd 100644 --- a/erpnext/patches/v12_0/rename_tolerance_fields.py +++ b/erpnext/patches/v12_0/rename_tolerance_fields.py @@ -1,6 +1,7 @@ import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("stock", "doctype", "item") frappe.reload_doc("stock", "doctype", "stock_settings") diff --git a/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py b/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py index f88a22f6c9d..ff332f771d3 100644 --- a/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py +++ b/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.db.sql("""UPDATE `tabUser` SET `home_settings` = REPLACE(`home_settings`, 'Accounting', 'Accounts')""") frappe.cache().delete_key('home_settings') diff --git a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py index c52f380d8c2..5150430dbb9 100644 --- a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py +++ b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): warehouse_perm = frappe.get_all("User Permission", fields=["count(*) as p_count", "is_default", "user"], filters={"allow": "Warehouse"}, group_by="user") diff --git a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py index 85202bff4d6..b76e34abe13 100644 --- a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py +++ b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc('selling', 'doctype', 'sales_order_item', force=True) diff --git a/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py index b5d7e3dcb9e..849e96e9665 100644 --- a/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py +++ b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "accounts_settings") diff --git a/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py b/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py index 4415cfeaba9..d3045a1a576 100644 --- a/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py +++ b/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py @@ -1,4 +1,6 @@ import frappe + + def execute(): frappe.reload_doc('hr', 'doctype', 'expense_claim_detail') frappe.db.sql(""" diff --git a/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py b/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py index 13110dfe03f..e363c26a86f 100644 --- a/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py +++ b/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe from frappe.utils import cint diff --git a/erpnext/patches/v12_0/set_default_homepage_type.py b/erpnext/patches/v12_0/set_default_homepage_type.py index a290e31cf24..1e4333aa466 100644 --- a/erpnext/patches/v12_0/set_default_homepage_type.py +++ b/erpnext/patches/v12_0/set_default_homepage_type.py @@ -1,4 +1,5 @@ import frappe + def execute(): frappe.db.set_value('Homepage', 'Homepage', 'hero_section_based_on', 'Default') diff --git a/erpnext/patches/v12_0/set_default_payroll_based_on.py b/erpnext/patches/v12_0/set_default_payroll_based_on.py index 038bd6d21ae..85112f2a540 100644 --- a/erpnext/patches/v12_0/set_default_payroll_based_on.py +++ b/erpnext/patches/v12_0/set_default_payroll_based_on.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("hr", "doctype", "hr_settings") frappe.db.set_value("HR Settings", None, "payroll_based_on", "Leave") diff --git a/erpnext/patches/v12_0/set_default_shopify_app_type.py b/erpnext/patches/v12_0/set_default_shopify_app_type.py index 65958a25afd..621564a939d 100644 --- a/erpnext/patches/v12_0/set_default_shopify_app_type.py +++ b/erpnext/patches/v12_0/set_default_shopify_app_type.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_settings') frappe.db.set_value('Shopify Settings', None, 'app_type', 'Private') diff --git a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py b/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py index a27c7b24a8c..49b3bff0f82 100644 --- a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py +++ b/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from six import iteritems + def execute(): frappe.reload_doctype('Landed Cost Taxes and Charges') diff --git a/erpnext/patches/v12_0/set_gst_category.py b/erpnext/patches/v12_0/set_gst_category.py index cc093953bf4..094e2a3134b 100644 --- a/erpnext/patches/v12_0/set_gst_category.py +++ b/erpnext/patches/v12_0/set_gst_category.py @@ -1,6 +1,8 @@ import frappe + from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/set_italian_import_supplier_invoice_permissions.py b/erpnext/patches/v12_0/set_italian_import_supplier_invoice_permissions.py index 8fdc73b8ff1..a991b3c15df 100644 --- a/erpnext/patches/v12_0/set_italian_import_supplier_invoice_permissions.py +++ b/erpnext/patches/v12_0/set_italian_import_supplier_invoice_permissions.py @@ -2,9 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + from erpnext.regional.italy.setup import add_permissions + def execute(): countries = frappe.get_all("Company", fields="country") countries = [country["country"] for country in countries] diff --git a/erpnext/patches/v12_0/set_multi_uom_in_rfq.py b/erpnext/patches/v12_0/set_multi_uom_in_rfq.py index a5c8f7524a7..fada5f08fb0 100644 --- a/erpnext/patches/v12_0/set_multi_uom_in_rfq.py +++ b/erpnext/patches/v12_0/set_multi_uom_in_rfq.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt -from erpnext.stock.get_item_details import get_conversion_factor + def execute(): frappe.reload_doc('buying', 'doctype', 'request_for_quotation_item') diff --git a/erpnext/patches/v12_0/set_payment_entry_status.py b/erpnext/patches/v12_0/set_payment_entry_status.py index 84645a38639..f8792952d8b 100644 --- a/erpnext/patches/v12_0/set_payment_entry_status.py +++ b/erpnext/patches/v12_0/set_payment_entry_status.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doctype("Payment Entry") frappe.db.sql("""update `tabPayment Entry` set status = CASE diff --git a/erpnext/patches/v12_0/set_permission_einvoicing.py b/erpnext/patches/v12_0/set_permission_einvoicing.py index e2235105f94..01cab14db9d 100644 --- a/erpnext/patches/v12_0/set_permission_einvoicing.py +++ b/erpnext/patches/v12_0/set_permission_einvoicing.py @@ -1,7 +1,9 @@ import frappe -from erpnext.regional.italy.setup import make_custom_fields from frappe.permissions import add_permission, update_permission_property +from erpnext.regional.italy.setup import make_custom_fields + + def execute(): company = frappe.get_all('Company', filters = {'country': 'Italy'}) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 66696bee541..6d7d0993460 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc("support", "doctype", "issue_priority") frappe.reload_doc("support", "doctype", "service_level_priority") diff --git a/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py b/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py index 6c11cb415f9..9c851ddcee1 100644 --- a/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py +++ b/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py @@ -1,7 +1,8 @@ import frappe -from frappe.utils import flt + from erpnext.selling.doctype.sales_order.sales_order import update_produced_qty_in_so_item + def execute(): frappe.reload_doctype('Sales Order Item') frappe.reload_doctype('Sales Order') diff --git a/erpnext/patches/v12_0/set_production_capacity_in_workstation.py b/erpnext/patches/v12_0/set_production_capacity_in_workstation.py index babaebeaefc..248d33504e1 100644 --- a/erpnext/patches/v12_0/set_production_capacity_in_workstation.py +++ b/erpnext/patches/v12_0/set_production_capacity_in_workstation.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("manufacturing", "doctype", "workstation") diff --git a/erpnext/patches/v12_0/set_published_in_hub_tracked_item.py b/erpnext/patches/v12_0/set_published_in_hub_tracked_item.py index e54c7f315c6..73c6ce8220e 100644 --- a/erpnext/patches/v12_0/set_published_in_hub_tracked_item.py +++ b/erpnext/patches/v12_0/set_published_in_hub_tracked_item.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("Hub Node", "doctype", "Hub Tracked Item") if not frappe.db.a_row_exists("Hub Tracked Item"): diff --git a/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py index 52c9a2d7b3c..cad947fadcd 100644 --- a/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py +++ b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals -import frappe + from collections import defaultdict +import frappe + + def execute(): frappe.reload_doc('stock', 'doctype', 'delivery_note_item', force=True) diff --git a/erpnext/patches/v12_0/set_quotation_status.py b/erpnext/patches/v12_0/set_quotation_status.py index 87643a23545..bb172769ebb 100644 --- a/erpnext/patches/v12_0/set_quotation_status.py +++ b/erpnext/patches/v12_0/set_quotation_status.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql(""" UPDATE `tabQuotation` set status = 'Open' diff --git a/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py b/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py index 88c3e2e3024..f8b510e3c37 100644 --- a/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py +++ b/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): purchase_receipts = frappe.db.sql(""" SELECT diff --git a/erpnext/patches/v12_0/set_serial_no_status.py b/erpnext/patches/v12_0/set_serial_no_status.py index 3b5f5ef3407..9a05e707a65 100644 --- a/erpnext/patches/v12_0/set_serial_no_status.py +++ b/erpnext/patches/v12_0/set_serial_no_status.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.utils import getdate, nowdate + def execute(): frappe.reload_doc('stock', 'doctype', 'serial_no') diff --git a/erpnext/patches/v12_0/set_task_status.py b/erpnext/patches/v12_0/set_task_status.py index dbd7e5a8181..1b4955a75be 100644 --- a/erpnext/patches/v12_0/set_task_status.py +++ b/erpnext/patches/v12_0/set_task_status.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doctype('Task') diff --git a/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py b/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py index 1cc37caba42..21ee23b2072 100644 --- a/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py +++ b/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): frappe.reload_doc("stock", "doctype", "pick_list") frappe.db.sql("""UPDATE `tabPick List` set purpose = 'Delivery' diff --git a/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py b/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py index 4a6e2288564..72d5521f44d 100644 --- a/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py +++ b/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("buying", "doctype", "supplier_quotation") frappe.db.sql("""UPDATE `tabSupplier Quotation` diff --git a/erpnext/patches/v12_0/setup_einvoice_fields.py b/erpnext/patches/v12_0/setup_einvoice_fields.py index 82b14fc9d60..c17666add18 100644 --- a/erpnext/patches/v12_0/setup_einvoice_fields.py +++ b/erpnext/patches/v12_0/setup_einvoice_fields.py @@ -1,8 +1,11 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + from erpnext.regional.india.setup import add_permissions, add_print_formats + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py b/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py index 2319c17b34c..3f90a03020f 100644 --- a/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py +++ b/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v12_0/stock_entry_enhancements.py b/erpnext/patches/v12_0/stock_entry_enhancements.py index 17fdcd9395a..b99501d942d 100644 --- a/erpnext/patches/v12_0/stock_entry_enhancements.py +++ b/erpnext/patches/v12_0/stock_entry_enhancements.py @@ -3,9 +3,11 @@ from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def execute(): create_stock_entry_types() diff --git a/erpnext/patches/v12_0/unhide_cost_center_field.py b/erpnext/patches/v12_0/unhide_cost_center_field.py index 3474a34af4b..823dd226372 100644 --- a/erpnext/patches/v12_0/unhide_cost_center_field.py +++ b/erpnext/patches/v12_0/unhide_cost_center_field.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql(""" DELETE FROM `tabProperty Setter` diff --git a/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py b/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py index b8efb210a03..61c4c601b55 100644 --- a/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py +++ b/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe diff --git a/erpnext/patches/v12_0/update_address_template_for_india.py b/erpnext/patches/v12_0/update_address_template_for_india.py index 0d582da4b5c..d41aae2a876 100644 --- a/erpnext/patches/v12_0/update_address_template_for_india.py +++ b/erpnext/patches/v12_0/update_address_template_for_india.py @@ -2,9 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + from erpnext.regional.address_template.setup import set_up_address_templates + def execute(): if frappe.db.get_value('Company', {'country': 'India'}, 'name'): address_template = frappe.db.get_value('Address Template', 'India', 'template') diff --git a/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py b/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py index f4516649610..024cb2b7630 100644 --- a/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py +++ b/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py @@ -1,5 +1,6 @@ import frappe + def execute(): job = frappe.db.exists('Scheduled Job Type', 'patient_appointment.send_appointment_reminder') if job: diff --git a/erpnext/patches/v12_0/update_bom_in_so_mr.py b/erpnext/patches/v12_0/update_bom_in_so_mr.py index 8a871718133..283407567f2 100644 --- a/erpnext/patches/v12_0/update_bom_in_so_mr.py +++ b/erpnext/patches/v12_0/update_bom_in_so_mr.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("stock", "doctype", "material_request_item") frappe.reload_doc("selling", "doctype", "sales_order_item") diff --git a/erpnext/patches/v12_0/update_due_date_in_gle.py b/erpnext/patches/v12_0/update_due_date_in_gle.py index 34848725cec..60ad3251146 100644 --- a/erpnext/patches/v12_0/update_due_date_in_gle.py +++ b/erpnext/patches/v12_0/update_due_date_in_gle.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "gl_entry") diff --git a/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py index c45f6221f93..208076b1496 100644 --- a/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py +++ b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.utils import add_days, getdate, today + def execute(): if frappe.db.exists('DocType', 'Email Campaign'): email_campaign = frappe.get_all('Email Campaign') diff --git a/erpnext/patches/v12_0/update_ewaybill_field_position.py b/erpnext/patches/v12_0/update_ewaybill_field_position.py index 9e5f599d2c8..520b5d04b4b 100644 --- a/erpnext/patches/v12_0/update_ewaybill_field_position.py +++ b/erpnext/patches/v12_0/update_ewaybill_field_position.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals + import frappe -from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/update_gst_category.py b/erpnext/patches/v12_0/update_gst_category.py index 1a54216b885..bee89199316 100644 --- a/erpnext/patches/v12_0/update_gst_category.py +++ b/erpnext/patches/v12_0/update_gst_category.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/update_healthcare_refactored_changes.py b/erpnext/patches/v12_0/update_healthcare_refactored_changes.py index d0b04433979..bfad3ddcba7 100644 --- a/erpnext/patches/v12_0/update_healthcare_refactored_changes.py +++ b/erpnext/patches/v12_0/update_healthcare_refactored_changes.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module +from frappe.modules import get_doctype_module, scrub field_rename_map = { 'Healthcare Settings': [ diff --git a/erpnext/patches/v12_0/update_is_cancelled_field.py b/erpnext/patches/v12_0/update_is_cancelled_field.py index 4bbec44aa42..3e7c37f0d19 100644 --- a/erpnext/patches/v12_0/update_is_cancelled_field.py +++ b/erpnext/patches/v12_0/update_is_cancelled_field.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): try: frappe.db.sql("UPDATE `tabStock Ledger Entry` SET is_cancelled = 0 where is_cancelled in ('', NULL, 'No')") @@ -11,5 +13,5 @@ def execute(): frappe.reload_doc("stock", "doctype", "stock_ledger_entry") frappe.reload_doc("stock", "doctype", "serial_no") - except: + except Exception: pass diff --git a/erpnext/patches/v12_0/update_item_tax_template_company.py b/erpnext/patches/v12_0/update_item_tax_template_company.py index e15894df890..3ad983d686f 100644 --- a/erpnext/patches/v12_0/update_item_tax_template_company.py +++ b/erpnext/patches/v12_0/update_item_tax_template_company.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('accounts', 'doctype', 'item_tax_template') diff --git a/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py b/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py index 6ebaf48e0e8..09e2319eb80 100644 --- a/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py +++ b/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py @@ -1,6 +1,11 @@ from __future__ import unicode_literals + import frappe -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_doctypes_with_dimensions + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_doctypes_with_dimensions, +) + def execute(): accounting_dimensions = frappe.db.sql("""select fieldname from diff --git a/erpnext/patches/v12_0/update_price_list_currency_in_bom.py b/erpnext/patches/v12_0/update_price_list_currency_in_bom.py index 09f07074299..e4c10089235 100644 --- a/erpnext/patches/v12_0/update_price_list_currency_in_bom.py +++ b/erpnext/patches/v12_0/update_price_list_currency_in_bom.py @@ -1,8 +1,11 @@ from __future__ import unicode_literals + import frappe -from frappe.utils import getdate, flt +from frappe.utils import getdate + from erpnext.setup.utils import get_exchange_rate + def execute(): frappe.reload_doc("manufacturing", "doctype", "bom") frappe.reload_doc("manufacturing", "doctype", "bom_item") diff --git a/erpnext/patches/v12_0/update_price_or_product_discount.py b/erpnext/patches/v12_0/update_price_or_product_discount.py index 3a8cd43e302..4ff39257688 100644 --- a/erpnext/patches/v12_0/update_price_or_product_discount.py +++ b/erpnext/patches/v12_0/update_price_or_product_discount.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "pricing_rule") diff --git a/erpnext/patches/v12_0/update_pricing_rule_fields.py b/erpnext/patches/v12_0/update_pricing_rule_fields.py index 985613a9739..6f102e9b42b 100644 --- a/erpnext/patches/v12_0/update_pricing_rule_fields.py +++ b/erpnext/patches/v12_0/update_pricing_rule_fields.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe parentfield = { diff --git a/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py index 8dbfa1866d3..25cf6b97e3b 100644 --- a/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py +++ b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py @@ -1,6 +1,8 @@ import frappe + from erpnext.regional.india import states + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v12_0/update_uom_conversion_factor.py b/erpnext/patches/v12_0/update_uom_conversion_factor.py index 24914fd13bc..7c7477a6739 100644 --- a/erpnext/patches/v12_0/update_uom_conversion_factor.py +++ b/erpnext/patches/v12_0/update_uom_conversion_factor.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals -import frappe, json + +import frappe + def execute(): from erpnext.setup.setup_wizard.operations.install_fixtures import add_uom_data diff --git a/erpnext/patches/v12_0/update_vehicle_no_reqd_condition.py b/erpnext/patches/v12_0/update_vehicle_no_reqd_condition.py index 01a4ae04add..69bfaaa2cb1 100644 --- a/erpnext/patches/v12_0/update_vehicle_no_reqd_condition.py +++ b/erpnext/patches/v12_0/update_vehicle_no_reqd_condition.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc('custom', 'doctype', 'custom_field') company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v13_0/add_custom_field_for_south_africa.py b/erpnext/patches/v13_0/add_custom_field_for_south_africa.py index 73ff1cad5b6..b34b5c1801f 100644 --- a/erpnext/patches/v13_0/add_custom_field_for_south_africa.py +++ b/erpnext/patches/v13_0/add_custom_field_for_south_africa.py @@ -1,14 +1,19 @@ # Copyright (c) 2020, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe -from erpnext.regional.south_africa.setup import make_custom_fields, add_permissions + +from erpnext.regional.south_africa.setup import add_permissions, make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'South Africa'}) if not company: return + frappe.reload_doc('regional', 'doctype', 'south_africa_vat_settings') + frappe.reload_doc('regional', 'report', 'vat_audit_report') + frappe.reload_doc('accounts', 'doctype', 'south_africa_vat_account') + make_custom_fields() add_permissions() diff --git a/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py index 0d8109c41ad..bd18b9bd173 100644 --- a/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py +++ b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt import frappe -from frappe.utils import cstr, flt, cint -from erpnext.stock.stock_ledger import make_sl_entries +from frappe.utils import cint, cstr, flt + from erpnext.controllers.stock_controller import create_repost_item_valuation_entry +from erpnext.stock.stock_ledger import make_sl_entries + def execute(): if not frappe.db.has_column('Work Order', 'has_batch_no'): diff --git a/erpnext/patches/v13_0/add_naming_series_to_old_projects.py b/erpnext/patches/v13_0/add_naming_series_to_old_projects.py index a7b66f0d2bb..f029f75accd 100644 --- a/erpnext/patches/v13_0/add_naming_series_to_old_projects.py +++ b/erpnext/patches/v13_0/add_naming_series_to_old_projects.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals + import frappe -from frappe.custom.doctype.property_setter.property_setter import make_property_setter, delete_property_setter + def execute(): frappe.reload_doc("projects", "doctype", "project") diff --git a/erpnext/patches/v13_0/add_po_to_global_search.py b/erpnext/patches/v13_0/add_po_to_global_search.py index 1c60b18e5b2..15b7c71dc2c 100644 --- a/erpnext/patches/v13_0/add_po_to_global_search.py +++ b/erpnext/patches/v13_0/add_po_to_global_search.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe diff --git a/erpnext/patches/v13_0/add_standard_navbar_items.py b/erpnext/patches/v13_0/add_standard_navbar_items.py index d05b258db0c..699c480c872 100644 --- a/erpnext/patches/v13_0/add_standard_navbar_items.py +++ b/erpnext/patches/v13_0/add_standard_navbar_items.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + # import frappe from erpnext.setup.install import add_standard_navbar_items + def execute(): # Add standard navbar items for ERPNext in Navbar Settings add_standard_navbar_items() diff --git a/erpnext/patches/v13_0/bill_for_rejected_quantity_in_purchase_invoice.py b/erpnext/patches/v13_0/bill_for_rejected_quantity_in_purchase_invoice.py index 7de9fa1e23e..07d1cee64f8 100644 --- a/erpnext/patches/v13_0/bill_for_rejected_quantity_in_purchase_invoice.py +++ b/erpnext/patches/v13_0/bill_for_rejected_quantity_in_purchase_invoice.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doctype("Buying Settings") buying_settings = frappe.get_single("Buying Settings") diff --git a/erpnext/patches/v13_0/change_default_pos_print_format.py b/erpnext/patches/v13_0/change_default_pos_print_format.py index 1e4f383dda6..5a0320a7eb2 100644 --- a/erpnext/patches/v13_0/change_default_pos_print_format.py +++ b/erpnext/patches/v13_0/change_default_pos_print_format.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.db.sql( """UPDATE `tabPOS Profile` profile diff --git a/erpnext/patches/v13_0/check_is_income_tax_component.py b/erpnext/patches/v13_0/check_is_income_tax_component.py index 7a52dc88d21..aac87ba36fa 100644 --- a/erpnext/patches/v13_0/check_is_income_tax_component.py +++ b/erpnext/patches/v13_0/check_is_income_tax_component.py @@ -3,9 +3,12 @@ from __future__ import unicode_literals -import frappe, erpnext +import frappe + +import erpnext from erpnext.regional.india.setup import setup + def execute(): doctypes = ['salary_component', diff --git a/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py b/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py index 341955aa35f..66ac62fdc4c 100644 --- a/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py +++ b/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('stock', 'doctype', 'quality_inspection_parameter') diff --git a/erpnext/patches/v13_0/create_gst_payment_entry_fields.py b/erpnext/patches/v13_0/create_gst_payment_entry_fields.py new file mode 100644 index 00000000000..7e6d67ce931 --- /dev/null +++ b/erpnext/patches/v13_0/create_gst_payment_entry_fields.py @@ -0,0 +1,32 @@ +# Copyright (c) 2021, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + + +def execute(): + frappe.reload_doc('accounts', 'doctype', 'advance_taxes_and_charges') + frappe.reload_doc('accounts', 'doctype', 'payment_entry') + + custom_fields = { + 'Payment Entry': [ + dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', insert_after='deductions', + print_hide=1, collapsible=1), + dict(fieldname='company_address', label='Company Address', fieldtype='Link', insert_after='gst_section', + print_hide=1, options='Address'), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', insert_after='company_address', + fetch_from='company_address.gstin', print_hide=1, read_only=1), + dict(fieldname='place_of_supply', label='Place of Supply', + fieldtype='Data', insert_after='company_gstin', + print_hide=1, read_only=1), + dict(fieldname='customer_address', label='Customer Address', fieldtype='Link', insert_after='place_of_supply', + print_hide=1, options='Address', depends_on = 'eval:doc.party_type == "Customer"'), + dict(fieldname='customer_gstin', label='Customer GSTIN', + fieldtype='Data', insert_after='customer_address', + fetch_from='customer_address.gstin', print_hide=1, read_only=1) + ] + } + + create_custom_fields(custom_fields, update=True) \ No newline at end of file diff --git a/erpnext/patches/v13_0/create_healthcare_custom_fields_in_stock_entry_detail.py b/erpnext/patches/v13_0/create_healthcare_custom_fields_in_stock_entry_detail.py index 08d4876c0d1..543faeb74ac 100644 --- a/erpnext/patches/v13_0/create_healthcare_custom_fields_in_stock_entry_detail.py +++ b/erpnext/patches/v13_0/create_healthcare_custom_fields_in_stock_entry_detail.py @@ -1,7 +1,9 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + from erpnext.domains.healthcare import data + def execute(): if 'Healthcare' not in frappe.get_active_domains(): return diff --git a/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py index 9a354537f7d..b1b5c24adc8 100644 --- a/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py +++ b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): if "leave_policy" in frappe.db.get_table_columns("Employee"): employees_with_leave_policy = frappe.db.sql("SELECT name, leave_policy FROM `tabEmployee` WHERE leave_policy IS NOT NULL and leave_policy != ''", as_dict = 1) diff --git a/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py b/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py index 6ad3402ba02..3bfa78fa282 100644 --- a/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py +++ b/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py @@ -4,8 +4,10 @@ from __future__ import unicode_literals import frappe + from erpnext.regional.united_arab_emirates.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': ['in', ['Saudi Arabia', 'United Arab Emirates']]}) if not company: diff --git a/erpnext/patches/v13_0/create_website_items.py b/erpnext/patches/v13_0/create_website_items.py new file mode 100644 index 00000000000..4a119683934 --- /dev/null +++ b/erpnext/patches/v13_0/create_website_items.py @@ -0,0 +1,72 @@ +import frappe + +from erpnext.e_commerce.doctype.website_item.website_item import make_website_item + + +def execute(): + frappe.reload_doc("e_commerce", "doctype", "website_item") + frappe.reload_doc("e_commerce", "doctype", "website_item_tabbed_section") + frappe.reload_doc("e_commerce", "doctype", "website_offer") + frappe.reload_doc("stock", "doctype", "item") + + item_fields = ["item_code", "item_name", "item_group", "stock_uom", "brand", "image", + "has_variants", "variant_of", "description", "weightage"] + web_fields_to_map = ["route", "slideshow", "website_image_alt", + "website_warehouse", "web_long_description", "website_content"] + + item_table_fields = frappe.db.sql("desc `tabItem`", as_dict=1) + item_table_fields = [d.get('Field') for d in item_table_fields] + + # prepare fields to query from Item, check if the web field exists in Item master + web_query_fields = [] + for web_field in web_fields_to_map: + if web_field in item_table_fields: + web_query_fields.append(web_field) + item_fields.append(web_field) + + # check if the filter fields exist in Item master + or_filters = {} + for field in ["show_in_website", "show_variant_in_website"]: + if field in item_table_fields: + or_filters[field] = 1 + + if not web_query_fields or not or_filters: + # web fields to map are not present in Item master schema + # most likely a fresh installation that doesnt need this patch + return + + items = frappe.db.get_all( + "Item", + fields=item_fields, + or_filters=or_filters + ) + + count = 0 + for item in items: + if frappe.db.exists("Website Item", {"item_code": item.item_code}): + continue + + # make website item from item (publish item) + website_item = make_website_item(item, save=False) + website_item.ranking = item.get("weightage") + for field in web_fields_to_map: + website_item.update({field: item.get(field)}) + website_item.save() + + # move Website Item Group & Website Specification table to Website Item + for doctype in ("Website Item Group", "Item Website Specification"): + web_item, item_code = website_item.name, item.item_code + frappe.db.sql(f""" + Update + `tab{doctype}` + set + parenttype = 'Website Item', + parent = '{web_item}' + where + parenttype = 'Item' + and parent = '{item_code}' + """) + + count += 1 + if count % 20 == 0: # commit after every 20 items + frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v13_0/delete_old_bank_reconciliation_doctypes.py b/erpnext/patches/v13_0/delete_old_bank_reconciliation_doctypes.py index 77a23cfc3f8..089bbe3b48f 100644 --- a/erpnext/patches/v13_0/delete_old_bank_reconciliation_doctypes.py +++ b/erpnext/patches/v13_0/delete_old_bank_reconciliation_doctypes.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field + def execute(): doctypes = [ "Bank Statement Settings", diff --git a/erpnext/patches/v13_0/delete_old_purchase_reports.py b/erpnext/patches/v13_0/delete_old_purchase_reports.py index 57620d3e986..3cb7e120d67 100644 --- a/erpnext/patches/v13_0/delete_old_purchase_reports.py +++ b/erpnext/patches/v13_0/delete_old_purchase_reports.py @@ -4,8 +4,10 @@ from __future__ import unicode_literals import frappe + from erpnext.accounts.utils import check_and_delete_linked_reports + def execute(): reports_to_delete = ["Requested Items To Be Ordered", "Purchase Order Items To Be Received or Billed","Purchase Order Items To Be Received", diff --git a/erpnext/patches/v13_0/delete_old_sales_reports.py b/erpnext/patches/v13_0/delete_old_sales_reports.py index 905a42c0c4c..c9a366655ce 100644 --- a/erpnext/patches/v13_0/delete_old_sales_reports.py +++ b/erpnext/patches/v13_0/delete_old_sales_reports.py @@ -4,8 +4,10 @@ from __future__ import unicode_literals import frappe + from erpnext.accounts.utils import check_and_delete_linked_reports + def execute(): reports_to_delete = ["Ordered Items To Be Delivered", "Ordered Items To Be Billed"] diff --git a/erpnext/patches/v13_0/delete_orphaned_tables.py b/erpnext/patches/v13_0/delete_orphaned_tables.py index 50a4a0efcbe..1ea22d63561 100644 --- a/erpnext/patches/v13_0/delete_orphaned_tables.py +++ b/erpnext/patches/v13_0/delete_orphaned_tables.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import getdate + def execute(): frappe.reload_doc('setup', 'doctype', 'transaction_deletion_record') diff --git a/erpnext/patches/v13_0/delete_report_requested_items_to_order.py b/erpnext/patches/v13_0/delete_report_requested_items_to_order.py index 8d6340d44ef..87565f0fe42 100644 --- a/erpnext/patches/v13_0/delete_report_requested_items_to_order.py +++ b/erpnext/patches/v13_0/delete_report_requested_items_to_order.py @@ -1,5 +1,6 @@ import frappe + def execute(): """ Check for one or multiple Auto Email Reports and delete """ auto_email_reports = frappe.db.get_values("Auto Email Report", {"report": "Requested Items to Order"}, ["name"]) diff --git a/erpnext/patches/v13_0/drop_razorpay_payload_column.py b/erpnext/patches/v13_0/drop_razorpay_payload_column.py index 76b8041cd94..a7aee521983 100644 --- a/erpnext/patches/v13_0/drop_razorpay_payload_column.py +++ b/erpnext/patches/v13_0/drop_razorpay_payload_column.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists("DocType", "Membership"): if 'webhook_payload' in frappe.db.get_table_columns("Membership"): diff --git a/erpnext/patches/v13_0/fix_non_unique_represents_company.py b/erpnext/patches/v13_0/fix_non_unique_represents_company.py index f20c73ae102..e91c1db4dd4 100644 --- a/erpnext/patches/v13_0/fix_non_unique_represents_company.py +++ b/erpnext/patches/v13_0/fix_non_unique_represents_company.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.db.sql(""" update tabCustomer diff --git a/erpnext/patches/v13_0/germany_make_custom_fields.py b/erpnext/patches/v13_0/germany_make_custom_fields.py index 41ab945eb12..86ad1885990 100644 --- a/erpnext/patches/v13_0/germany_make_custom_fields.py +++ b/erpnext/patches/v13_0/germany_make_custom_fields.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe + from erpnext.regional.germany.setup import make_custom_fields diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py index 2549a1e91ee..f2976544a40 100644 --- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py +++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field diff --git a/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py b/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py index c4ad1b7ff4f..e4cb9ae7cdc 100644 --- a/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py +++ b/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py @@ -1,8 +1,9 @@ import frappe -from frappe import _ -from frappe.utils import getdate, get_time, today -from erpnext.stock.stock_ledger import update_entries_after +from frappe.utils import get_time, getdate, today + from erpnext.accounts.utils import update_gl_entries_after +from erpnext.stock.stock_ledger import update_entries_after + def execute(): for doctype in ('repost_item_valuation', 'stock_entry_detail', 'purchase_receipt_item', diff --git a/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py b/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py index d2228c3bf31..43c6c4941ea 100644 --- a/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py +++ b/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): '''`sales_invoice` field from loyalty point entry is splitted into `invoice_type` & `invoice` fields''' diff --git a/erpnext/patches/v13_0/make_homepage_products_website_items.py b/erpnext/patches/v13_0/make_homepage_products_website_items.py new file mode 100644 index 00000000000..d48d54802c4 --- /dev/null +++ b/erpnext/patches/v13_0/make_homepage_products_website_items.py @@ -0,0 +1,17 @@ +from __future__ import unicode_literals + +import frappe + + +def execute(): + homepage = frappe.get_doc("Homepage") + + for row in homepage.products: + web_item = frappe.db.get_value("Website Item", {"item_code": row.item_code}, "name") + if not web_item: + continue + + row.item_code = web_item + + homepage.flags.ignore_mandatory = True + homepage.save() \ No newline at end of file diff --git a/erpnext/patches/v13_0/make_non_standard_user_type.py b/erpnext/patches/v13_0/make_non_standard_user_type.py index 73361f00262..746e4080b69 100644 --- a/erpnext/patches/v13_0/make_non_standard_user_type.py +++ b/erpnext/patches/v13_0/make_non_standard_user_type.py @@ -2,10 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from six import iteritems + from erpnext.setup.install import add_non_standard_user_types + def execute(): doctype_dict = { 'projects': ['Timesheet'], diff --git a/erpnext/patches/v13_0/move_branch_code_to_bank_account.py b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py index 24d9196d29f..9116f5835a1 100644 --- a/erpnext/patches/v13_0/move_branch_code_to_bank_account.py +++ b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): frappe.reload_doc('accounts', 'doctype', 'bank_account') diff --git a/erpnext/patches/v13_0/move_doctype_reports_and_notification_from_hr_to_payroll.py b/erpnext/patches/v13_0/move_doctype_reports_and_notification_from_hr_to_payroll.py index 4d7c85ce2d1..064e8d71a04 100644 --- a/erpnext/patches/v13_0/move_doctype_reports_and_notification_from_hr_to_payroll.py +++ b/erpnext/patches/v13_0/move_doctype_reports_and_notification_from_hr_to_payroll.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): frappe.db.sql("""UPDATE `tabPrint Format` SET module = 'Payroll' diff --git a/erpnext/patches/v13_0/move_payroll_setting_separately_from_hr_settings.py b/erpnext/patches/v13_0/move_payroll_setting_separately_from_hr_settings.py index a901064b889..85d5109248d 100644 --- a/erpnext/patches/v13_0/move_payroll_setting_separately_from_hr_settings.py +++ b/erpnext/patches/v13_0/move_payroll_setting_separately_from_hr_settings.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): data = frappe.db.sql('''SELECT * FROM `tabSingles` diff --git a/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py b/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py index 1a91d218ba3..e73fa7b9ecd 100644 --- a/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py +++ b/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from frappe.model.utils.rename_field import rename_field + def execute(): if not (frappe.db.table_exists("Payroll Period") and frappe.db.table_exists("Taxable Salary Slab")): @@ -86,7 +86,7 @@ def execute(): try: employee_other_income.submit() migrated.append([proof.employee, proof.payroll_period]) - except: + except Exception: pass if not frappe.db.table_exists("Employee Tax Exemption Declaration"): @@ -108,5 +108,5 @@ def execute(): try: employee_other_income.submit() - except: + except Exception: pass diff --git a/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py b/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py index 15aeb76e53f..bb539a7962c 100644 --- a/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py +++ b/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe + def execute(): if not frappe.db.table_exists("Additional Salary"): return diff --git a/erpnext/patches/v13_0/populate_e_commerce_settings.py b/erpnext/patches/v13_0/populate_e_commerce_settings.py new file mode 100644 index 00000000000..4466de817a7 --- /dev/null +++ b/erpnext/patches/v13_0/populate_e_commerce_settings.py @@ -0,0 +1,62 @@ +from __future__ import unicode_literals + +import frappe +from frappe.utils import cint + + +def execute(): + frappe.reload_doc("e_commerce", "doctype", "e_commerce_settings") + frappe.reload_doc("portal", "doctype", "website_filter_field") + frappe.reload_doc("portal", "doctype", "website_attribute") + + products_settings_fields = [ + "hide_variants", "products_per_page", + "enable_attribute_filters", "enable_field_filters" + ] + + shopping_cart_settings_fields = [ + "enabled", "show_attachments", "show_price", + "show_stock_availability", "enable_variants", "show_contact_us_button", + "show_quantity_in_website", "show_apply_coupon_code_in_website", + "allow_items_not_in_stock", "company", "price_list", "default_customer_group", + "quotation_series", "enable_checkout", "payment_success_url", + "payment_gateway_account", "save_quotations_as_draft" + ] + + settings = frappe.get_doc("E Commerce Settings") + + def map_into_e_commerce_settings(doctype, fields): + data = frappe.db.sql(""" + Select + field, value + from `tabSingles` + where + doctype='{doctype}' + and field in ({fields}) + """.format( + doctype=doctype, + fields=(",").join(['%s'] * len(fields)) + ), tuple(fields), as_dict=1) + + # {'enable_attribute_filters': '1', ...} + mapper = {row.field: row.value for row in data} + + for key, value in mapper.items(): + value = cint(value) if (value and value.isdigit()) else value + settings.update({key: value}) + + settings.save() + + # shift data to E Commerce Settings + map_into_e_commerce_settings("Products Settings", products_settings_fields) + map_into_e_commerce_settings("Shopping Cart Settings", shopping_cart_settings_fields) + + # move filters and attributes tables to E Commerce Settings from Products Settings + for doctype in ("Website Filter Field", "Website Attribute"): + frappe.db.sql("""Update `tab{doctype}` + set + parenttype = 'E Commerce Settings', + parent = 'E Commerce Settings' + where + parent = 'Products Settings' + """.format(doctype=doctype)) \ No newline at end of file diff --git a/erpnext/patches/v13_0/print_uom_after_quantity_patch.py b/erpnext/patches/v13_0/print_uom_after_quantity_patch.py index 0de3728f5c6..f2022b28b8b 100644 --- a/erpnext/patches/v13_0/print_uom_after_quantity_patch.py +++ b/erpnext/patches/v13_0/print_uom_after_quantity_patch.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals -import frappe from erpnext.setup.install import create_print_uom_after_qty_custom_field + def execute(): create_print_uom_after_qty_custom_field() diff --git a/erpnext/patches/v13_0/remove_attribute_field_from_item_variant_setting.py b/erpnext/patches/v13_0/remove_attribute_field_from_item_variant_setting.py index 53da7006b98..bbe3eb5815b 100644 --- a/erpnext/patches/v13_0/remove_attribute_field_from_item_variant_setting.py +++ b/erpnext/patches/v13_0/remove_attribute_field_from_item_variant_setting.py @@ -1,5 +1,6 @@ import frappe + def execute(): """Remove has_variants and attribute fields from item variant settings.""" frappe.reload_doc("stock", "doctype", "Item Variant Settings") diff --git a/erpnext/patches/v13_0/rename_discharge_date_in_ip_record.py b/erpnext/patches/v13_0/rename_discharge_date_in_ip_record.py index 491dc82f784..2a04211a407 100644 --- a/erpnext/patches/v13_0/rename_discharge_date_in_ip_record.py +++ b/erpnext/patches/v13_0/rename_discharge_date_in_ip_record.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("Healthcare", "doctype", "Inpatient Record") if frappe.db.has_column("Inpatient Record", "discharge_date"): diff --git a/erpnext/patches/v13_0/rename_discharge_ordered_date_in_ip_record.py b/erpnext/patches/v13_0/rename_discharge_ordered_date_in_ip_record.py index 52a5885fc2f..cf5cae438e6 100644 --- a/erpnext/patches/v13_0/rename_discharge_ordered_date_in_ip_record.py +++ b/erpnext/patches/v13_0/rename_discharge_ordered_date_in_ip_record.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("Healthcare", "doctype", "Inpatient Record") if frappe.db.has_column("Inpatient Record", "discharge_ordered_date"): diff --git a/erpnext/patches/v13_0/rename_issue_doctype_fields.py b/erpnext/patches/v13_0/rename_issue_doctype_fields.py index 4885c0b7afa..4aeafeabe74 100644 --- a/erpnext/patches/v13_0/rename_issue_doctype_fields.py +++ b/erpnext/patches/v13_0/rename_issue_doctype_fields.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): if frappe.db.exists('DocType', 'Issue'): issues = frappe.db.get_all('Issue', fields=['name', 'response_by_variance', 'resolution_by_variance', 'mins_to_first_response'], diff --git a/erpnext/patches/v13_0/rename_issue_status_hold_to_on_hold.py b/erpnext/patches/v13_0/rename_issue_status_hold_to_on_hold.py index 4ef04ad9b1b..1d245db4d59 100644 --- a/erpnext/patches/v13_0/rename_issue_status_hold_to_on_hold.py +++ b/erpnext/patches/v13_0/rename_issue_status_hold_to_on_hold.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists('DocType', 'Issue'): frappe.reload_doc("support", "doctype", "issue") diff --git a/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py b/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py index f60567b6b21..23a782a1e82 100644 --- a/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py +++ b/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): if frappe.db.table_exists("Membership Settings"): frappe.rename_doc("DocType", "Membership Settings", "Non Profit Settings") diff --git a/erpnext/patches/v13_0/rename_stop_to_send_birthday_reminders.py b/erpnext/patches/v13_0/rename_stop_to_send_birthday_reminders.py index 1787a560254..28054317ad3 100644 --- a/erpnext/patches/v13_0/rename_stop_to_send_birthday_reminders.py +++ b/erpnext/patches/v13_0/rename_stop_to_send_birthday_reminders.py @@ -1,23 +1,24 @@ import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc('hr', 'doctype', 'hr_settings') try: # Rename the field rename_field('HR Settings', 'stop_birthday_reminders', 'send_birthday_reminders') - + # Reverse the value old_value = frappe.db.get_single_value('HR Settings', 'send_birthday_reminders') frappe.db.set_value( - 'HR Settings', - 'HR Settings', - 'send_birthday_reminders', + 'HR Settings', + 'HR Settings', + 'send_birthday_reminders', 1 if old_value == 0 else 0 ) - + except Exception as e: if e.args[0] != 1054: raise \ No newline at end of file diff --git a/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py index d8bcd7f0775..989f1a0a281 100644 --- a/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py +++ b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): if frappe.db.exists("Page", "point-of-sale"): frappe.rename_doc("Page", "pos", "point-of-sale", 1, 1) diff --git a/erpnext/patches/v13_0/replace_pos_payment_mode_table.py b/erpnext/patches/v13_0/replace_pos_payment_mode_table.py index bc1fc98e4da..103c79177f1 100644 --- a/erpnext/patches/v13_0/replace_pos_payment_mode_table.py +++ b/erpnext/patches/v13_0/replace_pos_payment_mode_table.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "pos_payment_method") pos_profiles = frappe.get_all("POS Profile") diff --git a/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py b/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py index 1da5275761b..f8c4c1031a0 100644 --- a/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py +++ b/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): """ Reset Clearance Date for Payment Entries of type Internal Transfer that have only been reconciled with one Bank Transaction. @@ -35,10 +36,10 @@ def get_reconciled_bank_transactions(intra_company_pe): for payment_entry in intra_company_pe: reconciled_bank_transactions[payment_entry] = frappe.get_all( - 'Bank Transaction Payments', + 'Bank Transaction Payments', filters = { 'payment_entry': payment_entry - }, + }, pluck='parent' ) diff --git a/erpnext/patches/v13_0/set_app_name.py b/erpnext/patches/v13_0/set_app_name.py index 3f886f1d159..4a88442bcdc 100644 --- a/erpnext/patches/v13_0/set_app_name.py +++ b/erpnext/patches/v13_0/set_app_name.py @@ -1,5 +1,5 @@ import frappe -from frappe import _ + def execute(): frappe.reload_doctype("System Settings") diff --git a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py index a5b93f63071..e9396c2df29 100644 --- a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py +++ b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): company = frappe.db.get_single_value('Global Defaults', 'default_company') doctypes = ['Clinical Procedure', 'Inpatient Record', 'Lab Test', 'Sample Collection', 'Patient Appointment', 'Patient Encounter', 'Vital Signs', 'Therapy Session', 'Therapy Plan', 'Patient Assessment'] diff --git a/erpnext/patches/v13_0/set_company_in_leave_ledger_entry.py b/erpnext/patches/v13_0/set_company_in_leave_ledger_entry.py index 13ec41ec55e..c744f35b72f 100644 --- a/erpnext/patches/v13_0/set_company_in_leave_ledger_entry.py +++ b/erpnext/patches/v13_0/set_company_in_leave_ledger_entry.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc('HR', 'doctype', 'Leave Allocation') frappe.reload_doc('HR', 'doctype', 'Leave Ledger Entry') diff --git a/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py b/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py index 4acbdd63a00..0366d4902dc 100644 --- a/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py +++ b/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc('manufacturing', 'doctype', 'bom') frappe.reload_doc('manufacturing', 'doctype', 'bom_operation') diff --git a/erpnext/patches/v13_0/set_payment_channel_in_payment_gateway_account.py b/erpnext/patches/v13_0/set_payment_channel_in_payment_gateway_account.py index 7f75946af9f..da889e61bab 100644 --- a/erpnext/patches/v13_0/set_payment_channel_in_payment_gateway_account.py +++ b/erpnext/patches/v13_0/set_payment_channel_in_payment_gateway_account.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): """Set the payment gateway account as Email for all the existing payment channel.""" doc_meta = frappe.get_meta("Payment Gateway Account") diff --git a/erpnext/patches/v13_0/set_pos_closing_as_failed.py b/erpnext/patches/v13_0/set_pos_closing_as_failed.py index 7968e74f50f..8c7f5088b74 100644 --- a/erpnext/patches/v13_0/set_pos_closing_as_failed.py +++ b/erpnext/patches/v13_0/set_pos_closing_as_failed.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('accounts', 'doctype', 'pos_closing_entry') diff --git a/erpnext/patches/v13_0/set_training_event_attendance.py b/erpnext/patches/v13_0/set_training_event_attendance.py index 3db183fb2ab..4e3d8f5e6a5 100644 --- a/erpnext/patches/v13_0/set_training_event_attendance.py +++ b/erpnext/patches/v13_0/set_training_event_attendance.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('hr', 'doctype', 'training_event') frappe.reload_doc('hr', 'doctype', 'training_event_employee') diff --git a/erpnext/patches/v13_0/set_youtube_video_id.py b/erpnext/patches/v13_0/set_youtube_video_id.py index f6104d1579f..1594e52e4e5 100644 --- a/erpnext/patches/v13_0/set_youtube_video_id.py +++ b/erpnext/patches/v13_0/set_youtube_video_id.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.utilities.doctype.video.video import get_id_from_url + def execute(): frappe.reload_doc("utilities", "doctype","video") diff --git a/erpnext/patches/v13_0/setting_custom_roles_for_some_regional_reports.py b/erpnext/patches/v13_0/setting_custom_roles_for_some_regional_reports.py index c8c160fae71..a6a3ff3be4b 100644 --- a/erpnext/patches/v13_0/setting_custom_roles_for_some_regional_reports.py +++ b/erpnext/patches/v13_0/setting_custom_roles_for_some_regional_reports.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.regional.india.setup import add_custom_roles_for_reports + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py b/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py index 833c355d5f8..7a2a2539670 100644 --- a/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py +++ b/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py @@ -1,6 +1,8 @@ import frappe + from erpnext.regional.india.setup import make_custom_fields + def execute(): if frappe.get_all('Company', filters = {'country': 'India'}): make_custom_fields() diff --git a/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py index 01fd6a158e9..01e75a6009b 100644 --- a/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py +++ b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('payroll', 'doctype', 'gratuity_rule') frappe.reload_doc('payroll', 'doctype', 'gratuity_rule_slab') diff --git a/erpnext/patches/v13_0/setup_patient_history_settings_for_standard_doctypes.py b/erpnext/patches/v13_0/setup_patient_history_settings_for_standard_doctypes.py index 83581dd4144..80622d46096 100644 --- a/erpnext/patches/v13_0/setup_patient_history_settings_for_standard_doctypes.py +++ b/erpnext/patches/v13_0/setup_patient_history_settings_for_standard_doctypes.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals + import frappe + from erpnext.healthcare.setup import setup_patient_history_settings + def execute(): if "Healthcare" not in frappe.get_active_domains(): return diff --git a/erpnext/patches/v13_0/setup_uae_vat_fields.py b/erpnext/patches/v13_0/setup_uae_vat_fields.py index 1830bab02ba..d89e0521d8d 100644 --- a/erpnext/patches/v13_0/setup_uae_vat_fields.py +++ b/erpnext/patches/v13_0/setup_uae_vat_fields.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt import frappe + from erpnext.regional.united_arab_emirates.setup import setup + def execute(): company = frappe.get_all('Company', filters = {'country': 'United Arab Emirates'}) if not company: diff --git a/erpnext/patches/v13_0/stock_entry_enhancements.py b/erpnext/patches/v13_0/stock_entry_enhancements.py index 7b93ce35768..5fcd6a3a625 100644 --- a/erpnext/patches/v13_0/stock_entry_enhancements.py +++ b/erpnext/patches/v13_0/stock_entry_enhancements.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3.See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("stock", "doctype", "stock_entry") if frappe.db.has_column("Stock Entry", "add_to_transit"): diff --git a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py index 50f233deef4..dd87a5302d2 100644 --- a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py +++ b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import add_to_date + def execute(): frappe.reload_doc("manufacturing", "doctype", "work_order") frappe.reload_doc("manufacturing", "doctype", "work_order_item") diff --git a/erpnext/patches/v13_0/update_amt_in_work_order_required_items.py b/erpnext/patches/v13_0/update_amt_in_work_order_required_items.py index dc9ed18eade..dc973a9d451 100644 --- a/erpnext/patches/v13_0/update_amt_in_work_order_required_items.py +++ b/erpnext/patches/v13_0/update_amt_in_work_order_required_items.py @@ -1,5 +1,6 @@ import frappe + def execute(): """ Correct amount in child table of required items table.""" diff --git a/erpnext/patches/v13_0/update_custom_fields_for_shopify.py b/erpnext/patches/v13_0/update_custom_fields_for_shopify.py index f1d2ea2d747..828bde69cf9 100644 --- a/erpnext/patches/v13_0/update_custom_fields_for_shopify.py +++ b/erpnext/patches/v13_0/update_custom_fields_for_shopify.py @@ -2,8 +2,13 @@ # MIT License. See license.txt from __future__ import unicode_literals + import frappe -from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import setup_custom_fields + +from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import ( + setup_custom_fields, +) + def execute(): if frappe.db.get_single_value('Shopify Settings', 'enable_shopify'): diff --git a/erpnext/patches/v13_0/update_deferred_settings.py b/erpnext/patches/v13_0/update_deferred_settings.py index bcc09527a29..54059318c75 100644 --- a/erpnext/patches/v13_0/update_deferred_settings.py +++ b/erpnext/patches/v13_0/update_deferred_settings.py @@ -1,8 +1,10 @@ # Copyright (c) 2019, Frappe and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings.book_deferred_entries_based_on = 'Days' diff --git a/erpnext/patches/v13_0/update_export_type_for_gst.py b/erpnext/patches/v13_0/update_export_type_for_gst.py index ef70b55d94c..de578612f7d 100644 --- a/erpnext/patches/v13_0/update_export_type_for_gst.py +++ b/erpnext/patches/v13_0/update_export_type_for_gst.py @@ -1,5 +1,6 @@ import frappe + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: diff --git a/erpnext/patches/v13_0/update_job_card_details.py b/erpnext/patches/v13_0/update_job_card_details.py index 733b3a960cf..a0405e50396 100644 --- a/erpnext/patches/v13_0/update_job_card_details.py +++ b/erpnext/patches/v13_0/update_job_card_details.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("manufacturing", "doctype", "job_card") frappe.reload_doc("manufacturing", "doctype", "job_card_item") diff --git a/erpnext/patches/v13_0/update_level_in_bom.py b/erpnext/patches/v13_0/update_level_in_bom.py index 0d03c42e980..6223500e6b6 100644 --- a/erpnext/patches/v13_0/update_level_in_bom.py +++ b/erpnext/patches/v13_0/update_level_in_bom.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): for document in ["bom", "bom_item", "bom_explosion_item"]: frappe.reload_doc('manufacturing', 'doctype', document) diff --git a/erpnext/patches/v13_0/update_member_email_address.py b/erpnext/patches/v13_0/update_member_email_address.py index 4056f84069c..769658e2b8a 100644 --- a/erpnext/patches/v13_0/update_member_email_address.py +++ b/erpnext/patches/v13_0/update_member_email_address.py @@ -2,9 +2,11 @@ # MIT License. See license.txt from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): """add value to email_id column from email""" diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py index 8cf09aa6925..b01a87722ef 100644 --- a/erpnext/patches/v13_0/update_old_loans.py +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -1,12 +1,18 @@ from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import nowdate, flt -from erpnext.accounts.doctype.account.test_account import create_account -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans -from erpnext.loan_management.doctype.loan.loan import make_repayment_entry -from erpnext.loan_management.doctype.loan_repayment.loan_repayment import get_accrued_interest_entries from frappe.model.naming import make_autoname +from frappe.utils import flt, nowdate + +from erpnext.accounts.doctype.account.test_account import create_account +from erpnext.loan_management.doctype.loan_repayment.loan_repayment import ( + get_accrued_interest_entries, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_term_loans, +) + def execute(): diff --git a/erpnext/patches/v13_0/update_payment_terms_outstanding.py b/erpnext/patches/v13_0/update_payment_terms_outstanding.py index 4816b40250e..c9e920b7cb5 100644 --- a/erpnext/patches/v13_0/update_payment_terms_outstanding.py +++ b/erpnext/patches/v13_0/update_payment_terms_outstanding.py @@ -2,8 +2,10 @@ # MIT License. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "Payment Schedule") if frappe.db.count('Payment Schedule'): diff --git a/erpnext/patches/v13_0/update_pos_closing_entry_in_merge_log.py b/erpnext/patches/v13_0/update_pos_closing_entry_in_merge_log.py index 262e38dd056..71fe9ed6805 100644 --- a/erpnext/patches/v13_0/update_pos_closing_entry_in_merge_log.py +++ b/erpnext/patches/v13_0/update_pos_closing_entry_in_merge_log.py @@ -2,8 +2,10 @@ # MIT License. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("accounts", "doctype", "POS Invoice Merge Log") frappe.reload_doc("accounts", "doctype", "POS Closing Entry") diff --git a/erpnext/patches/v13_0/update_project_template_tasks.py b/erpnext/patches/v13_0/update_project_template_tasks.py index b41b74205c7..f0d0a5a7ef5 100644 --- a/erpnext/patches/v13_0/update_project_template_tasks.py +++ b/erpnext/patches/v13_0/update_project_template_tasks.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("projects", "doctype", "project_template") frappe.reload_doc("projects", "doctype", "project_template_task") diff --git a/erpnext/patches/v13_0/update_reason_for_resignation_in_employee.py b/erpnext/patches/v13_0/update_reason_for_resignation_in_employee.py index ccdc334f306..84075024a47 100644 --- a/erpnext/patches/v13_0/update_reason_for_resignation_in_employee.py +++ b/erpnext/patches/v13_0/update_reason_for_resignation_in_employee.py @@ -2,8 +2,10 @@ # MIT License. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("hr", "doctype", "employee") diff --git a/erpnext/patches/v13_0/update_recipient_email_digest.py b/erpnext/patches/v13_0/update_recipient_email_digest.py index ed90e126670..6cd27dc609c 100644 --- a/erpnext/patches/v13_0/update_recipient_email_digest.py +++ b/erpnext/patches/v13_0/update_recipient_email_digest.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc("setup", "doctype", "Email Digest") frappe.reload_doc("setup", "doctype", "Email Digest Recipient") diff --git a/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py b/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py index a5769d2957c..efb3a5961f9 100644 --- a/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py +++ b/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py @@ -1,8 +1,10 @@ # Copyright (c) 2021, Frappe and Contributors # License: GNU General Public License v3. See license.txt import frappe + from erpnext.controllers.status_updater import OverAllowanceError + def execute(): frappe.reload_doc('stock', 'doctype', 'purchase_receipt') frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item') diff --git a/erpnext/patches/v13_0/update_shipment_status.py b/erpnext/patches/v13_0/update_shipment_status.py index c425599e26b..f2d7d1d1e3f 100644 --- a/erpnext/patches/v13_0/update_shipment_status.py +++ b/erpnext/patches/v13_0/update_shipment_status.py @@ -1,5 +1,6 @@ import frappe + def execute(): frappe.reload_doc("stock", "doctype", "shipment") diff --git a/erpnext/patches/v13_0/update_sla_enhancements.py b/erpnext/patches/v13_0/update_sla_enhancements.py index c156ba95772..bcfbf8b24cb 100644 --- a/erpnext/patches/v13_0/update_sla_enhancements.py +++ b/erpnext/patches/v13_0/update_sla_enhancements.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): # add holiday list and employee group fields in SLA # change response and resolution time in priorities child table diff --git a/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py b/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py index 0f521cb57a8..bcdf72ec69c 100644 --- a/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py +++ b/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe + def execute(): frappe.reload_doc('hr', 'doctype', 'shift_assignment') if frappe.db.has_column('Shift Assignment', 'date'): diff --git a/erpnext/patches/v13_0/update_subscription.py b/erpnext/patches/v13_0/update_subscription.py index d25e9c805b7..e0ea78fa4d9 100644 --- a/erpnext/patches/v13_0/update_subscription.py +++ b/erpnext/patches/v13_0/update_subscription.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from six import iteritems + def execute(): frappe.reload_doc('accounts', 'doctype', 'subscription') diff --git a/erpnext/patches/v13_0/update_subscription_status_in_memberships.py b/erpnext/patches/v13_0/update_subscription_status_in_memberships.py index d9c3e453d47..e21fe578212 100644 --- a/erpnext/patches/v13_0/update_subscription_status_in_memberships.py +++ b/erpnext/patches/v13_0/update_subscription_status_in_memberships.py @@ -1,5 +1,6 @@ import frappe + def execute(): if frappe.db.exists('DocType', 'Member'): frappe.reload_doc('Non Profit', 'doctype', 'Member') diff --git a/erpnext/patches/v13_0/update_tds_check_field.py b/erpnext/patches/v13_0/update_tds_check_field.py index 341b0e8e2e2..436d2e6a6da 100644 --- a/erpnext/patches/v13_0/update_tds_check_field.py +++ b/erpnext/patches/v13_0/update_tds_check_field.py @@ -1,5 +1,6 @@ import frappe + def execute(): if frappe.db.has_table("Tax Withholding Category") \ and frappe.db.has_column("Tax Withholding Category", "round_off_tax_amount"): diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py index a36c84ea6e2..d993d54191f 100644 --- a/erpnext/patches/v13_0/update_timesheet_changes.py +++ b/erpnext/patches/v13_0/update_timesheet_changes.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc("projects", "doctype", "timesheet") frappe.reload_doc("projects", "doctype", "timesheet_detail") diff --git a/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py b/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py index 7d344f9cd7e..c760a6a52f1 100644 --- a/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py +++ b/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py @@ -5,6 +5,7 @@ import frappe from frappe import _ from frappe.model.utils.rename_field import rename_field + def execute(): frappe.reload_doc('Accounts', 'doctype', 'Salary Component Account') diff --git a/erpnext/patches/v13_0/validate_options_for_data_field.py b/erpnext/patches/v13_0/validate_options_for_data_field.py index 568d1a4b0cb..41a38fe29c1 100644 --- a/erpnext/patches/v13_0/validate_options_for_data_field.py +++ b/erpnext/patches/v13_0/validate_options_for_data_field.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.model import data_field_options +from frappe.model import data_field_options + def execute(): - for field in frappe.get_all('Custom Field', + for field in frappe.get_all('Custom Field', fields = ['name'], filters = { 'fieldtype': 'Data', @@ -16,7 +18,7 @@ def execute(): if field not in data_field_options: frappe.db.sql(""" - UPDATE + UPDATE `tabCustom Field` SET options=NULL diff --git a/erpnext/patches/v4_2/repost_reserved_qty.py b/erpnext/patches/v4_2/repost_reserved_qty.py index 36117aad8cc..4fa3b468719 100644 --- a/erpnext/patches/v4_2/repost_reserved_qty.py +++ b/erpnext/patches/v4_2/repost_reserved_qty.py @@ -2,8 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty + +from erpnext.stock.stock_balance import get_reserved_qty, update_bin_qty + def execute(): for doctype in ("Sales Order Item", "Bin"): diff --git a/erpnext/patches/v4_2/update_requested_and_ordered_qty.py b/erpnext/patches/v4_2/update_requested_and_ordered_qty.py index 7bb49e64dfe..9330a443bf3 100644 --- a/erpnext/patches/v4_2/update_requested_and_ordered_qty.py +++ b/erpnext/patches/v4_2/update_requested_and_ordered_qty.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): - from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty, get_ordered_qty + from erpnext.stock.stock_balance import get_indented_qty, get_ordered_qty, update_bin_qty count=0 for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse from @@ -20,5 +22,5 @@ def execute(): }) if count % 200 == 0: frappe.db.commit() - except: + except Exception: frappe.db.rollback() diff --git a/erpnext/patches/v5_7/update_item_description_based_on_item_master.py b/erpnext/patches/v5_7/update_item_description_based_on_item_master.py index 2045358ddb2..82b5b1cc2d2 100644 --- a/erpnext/patches/v5_7/update_item_description_based_on_item_master.py +++ b/erpnext/patches/v5_7/update_item_description_based_on_item_master.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + import frappe + def execute(): name = frappe.db.sql(""" select name from `tabPatch Log` \ where \ diff --git a/erpnext/patches/v8_1/removed_roles_from_gst_report_non_indian_account.py b/erpnext/patches/v8_1/removed_roles_from_gst_report_non_indian_account.py index 55f5f8201fb..ecfdc41f9b8 100644 --- a/erpnext/patches/v8_1/removed_roles_from_gst_report_non_indian_account.py +++ b/erpnext/patches/v8_1/removed_roles_from_gst_report_non_indian_account.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def execute(): frappe.reload_doc('core', 'doctype', 'has_role') company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/patches/v8_1/setup_gst_india.py b/erpnext/patches/v8_1/setup_gst_india.py index c214990693c..140b22656b1 100644 --- a/erpnext/patches/v8_1/setup_gst_india.py +++ b/erpnext/patches/v8_1/setup_gst_india.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals + import frappe from frappe.email import sendmail_to_system_managers + def execute(): frappe.reload_doc('stock', 'doctype', 'item') frappe.reload_doc("stock", "doctype", "customs_tariff_number") diff --git a/erpnext/patches/v8_7/sync_india_custom_fields.py b/erpnext/patches/v8_7/sync_india_custom_fields.py index eb24a90f013..65ec14e8826 100644 --- a/erpnext/patches/v8_7/sync_india_custom_fields.py +++ b/erpnext/patches/v8_7/sync_india_custom_fields.py @@ -1,6 +1,9 @@ from __future__ import unicode_literals + import frappe -from erpnext.regional.india.setup import make_custom_fields + +from erpnext.regional.india.setup import make_custom_fields + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py index 381f399e9fa..ed10f2bc67a 100644 --- a/erpnext/payroll/doctype/additional_salary/additional_salary.py +++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _, bold -from frappe.utils import getdate, date_diff, comma_and, formatdate +from frappe.model.document import Document +from frappe.utils import comma_and, date_diff, formatdate, getdate + from erpnext.hr.utils import validate_active_employee + class AdditionalSalary(Document): def on_submit(self): if self.ref_doctype == "Employee Advance" and self.ref_docname: diff --git a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py index 2a9c56179e7..2ad4afef251 100644 --- a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py +++ b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py @@ -2,12 +2,19 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest -import frappe, erpnext -from frappe.utils import nowdate, add_days + +import frappe +from frappe.utils import add_days, nowdate + +import erpnext from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.payroll.doctype.salary_component.test_salary_component import create_salary_component -from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_employee_salary_slip, setup_test +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + make_employee_salary_slip, + setup_test, +) from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py index a1cde08a74c..9983f012875 100644 --- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py @@ -3,13 +3,26 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import date_diff, getdate, rounded, add_days, cstr, cint, flt from frappe.model.document import Document -from erpnext.payroll.doctype.payroll_period.payroll_period import get_payroll_period_days, get_period_factor -from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure -from erpnext.hr.utils import get_sal_slip_total_benefit_given, get_holiday_dates_for_employee, get_previous_claimed_amount, validate_active_employee +from frappe.utils import add_days, cint, cstr, date_diff, getdate, rounded + +from erpnext.hr.utils import ( + get_holiday_dates_for_employee, + get_previous_claimed_amount, + get_sal_slip_total_benefit_given, + validate_active_employee, +) +from erpnext.payroll.doctype.payroll_period.payroll_period import ( + get_payroll_period_days, + get_period_factor, +) +from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import ( + get_assigned_salary_structure, +) + class EmployeeBenefitApplication(Document): def validate(self): diff --git a/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.py index 34e1a8fbc1d..ea05e0e0e05 100644 --- a/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.py +++ b/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.py @@ -2,7 +2,9 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestEmployeeBenefitApplication(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.py b/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.py index 65405feaf19..ddcbaa20619 100644 --- a/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.py +++ b/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeBenefitApplicationDetail(Document): pass diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py index c6713f3aa46..7898e04cf44 100644 --- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -3,14 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt from frappe.model.document import Document -from erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits +from frappe.utils import flt + from erpnext.hr.utils import get_previous_claimed_amount, validate_active_employee +from erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application import ( + get_max_benefits, +) from erpnext.payroll.doctype.payroll_period.payroll_period import get_payroll_period -from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure +from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import ( + get_assigned_salary_structure, +) + class EmployeeBenefitClaim(Document): def validate(self): diff --git a/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.py b/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.py index aff73e5c816..f3f2229fb2e 100644 --- a/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.py +++ b/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.py @@ -2,7 +2,9 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + import unittest + class TestEmployeeBenefitClaim(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py index 6b918ba76d1..74d073668d7 100644 --- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py +++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + from erpnext.hr.utils import validate_active_employee + class EmployeeIncentive(Document): def validate(self): validate_active_employee(self.employee) diff --git a/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.py b/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.py index f7597ad6057..3c95fa80ec0 100644 --- a/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.py +++ b/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeIncentive(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/employee_other_income/employee_other_income.py b/erpnext/payroll/doctype/employee_other_income/employee_other_income.py index ab63c0de623..73a0321c8fe 100644 --- a/erpnext/payroll/doctype/employee_other_income/employee_other_income.py +++ b/erpnext/payroll/doctype/employee_other_income/employee_other_income.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeOtherIncome(Document): pass diff --git a/erpnext/payroll/doctype/employee_other_income/test_employee_other_income.py b/erpnext/payroll/doctype/employee_other_income/test_employee_other_income.py index 2eeca7a23de..5b735b37a16 100644 --- a/erpnext/payroll/doctype/employee_other_income/test_employee_other_income.py +++ b/erpnext/payroll/doctype/employee_other_income/test_employee_other_income.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestEmployeeOtherIncome(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/employee_tax_exemption_category/employee_tax_exemption_category.py b/erpnext/payroll/doctype/employee_tax_exemption_category/employee_tax_exemption_category.py index 4f705db22e5..f88f551a2ee 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_category/employee_tax_exemption_category.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_category/employee_tax_exemption_category.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class EmployeeTaxExemptionCategory(Document): pass diff --git a/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.py b/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.py index 669fb71f46e..e6bc3abf127 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeTaxExemptionCategory(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py index e11d60a4649..099ab0dcde0 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py @@ -3,13 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document -from frappe import _ -from frappe.utils import flt from frappe.model.mapper import get_mapped_doc -from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, validate_active_employee, \ - calculate_annual_eligible_hra_exemption, validate_duplicate_exemption_for_payroll_period +from frappe.utils import flt + +from erpnext.hr.utils import ( + calculate_annual_eligible_hra_exemption, + get_total_exemption_amount, + validate_active_employee, + validate_duplicate_exemption_for_payroll_period, + validate_tax_declaration, +) + class EmployeeTaxExemptionDeclaration(Document): def validate(self): diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py index 311f3527f6e..b7154a4da15 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py @@ -3,11 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe, erpnext import unittest + +import frappe + +import erpnext from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.hr.utils import DuplicateDeclarationError + class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): def setUp(self): make_employee("employee@taxexepmtion.com") diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.py b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.py index bff747f90de..2923e57333d 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeTaxExemptionDeclarationCategory(Document): pass diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py index 8131ae0fa85..f35fd3caf90 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py @@ -3,12 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document -from frappe import _ from frappe.utils import flt -from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, validate_active_employee, \ - calculate_hra_exemption_for_period, validate_duplicate_exemption_for_payroll_period + +from erpnext.hr.utils import ( + calculate_hra_exemption_for_period, + get_total_exemption_amount, + validate_active_employee, + validate_duplicate_exemption_for_payroll_period, + validate_tax_declaration, +) + class EmployeeTaxExemptionProofSubmission(Document): def validate(self): diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.py b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.py index cb9ed5f971c..aafc0a13211 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.py @@ -3,9 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import create_exemption_category, create_payroll_period + +import frappe + +from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import ( + create_exemption_category, + create_payroll_period, +) + class TestEmployeeTaxExemptionProofSubmission(unittest.TestCase): def setup(self): diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.py b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.py index 0244ae66468..e0a11aec162 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmployeeTaxExemptionProofSubmissionDetail(Document): pass diff --git a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py b/erpnext/payroll/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py index d3f24c93780..5948ef208bf 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt from frappe.model.document import Document +from frappe.utils import flt + class EmployeeTaxExemptionSubCategory(Document): def validate(self): diff --git a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.py b/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.py index 5d705567a2d..0086086bde6 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.py +++ b/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestEmployeeTaxExemptionSubCategory(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/gratuity/gratuity.py b/erpnext/payroll/doctype/gratuity/gratuity.py index 31a6af3a077..1e287729808 100644 --- a/erpnext/payroll/doctype/gratuity/gratuity.py +++ b/erpnext/payroll/doctype/gratuity/gratuity.py @@ -3,12 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from math import floor + import frappe from frappe import _, bold from frappe.utils import flt, get_datetime, get_link_to_form + from erpnext.accounts.general_ledger import make_gl_entries from erpnext.controllers.accounts_controller import AccountsController -from math import floor + class Gratuity(AccountsController): def validate(self): diff --git a/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py b/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py index 483e346a32d..d0fda57016c 100644 --- a/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py +++ b/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'reference_name', diff --git a/erpnext/payroll/doctype/gratuity/test_gratuity.py b/erpnext/payroll/doctype/gratuity/test_gratuity.py index 6c3b6fbae58..66cbbd7d149 100644 --- a/erpnext/payroll/doctype/gratuity/test_gratuity.py +++ b/erpnext/payroll/doctype/gratuity/test_gratuity.py @@ -3,15 +3,20 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe +from frappe.utils import add_days, flt, get_datetime, getdate + from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_employee_salary_slip, make_earning_salary_component, \ - make_deduction_salary_component -from erpnext.payroll.doctype.gratuity.gratuity import get_last_salary_slip -from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account -from frappe.utils import getdate, add_days, get_datetime, flt +from erpnext.payroll.doctype.gratuity.gratuity import get_last_salary_slip +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + make_deduction_salary_component, + make_earning_salary_component, + make_employee_salary_slip, +) +from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule test_dependencies = ["Salary Component", "Salary Slip", "Account"] class TestGratuity(unittest.TestCase): diff --git a/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py index 23e4340b04f..d76b26d05f6 100644 --- a/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py +++ b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class GratuityApplicableComponent(Document): pass diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py index 29a6ebe1a6a..95d2929fffa 100644 --- a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py +++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py @@ -3,16 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class GratuityRule(Document): def validate(self): for current_slab in self.gratuity_rule_slabs: if (current_slab.from_year > current_slab.to_year) and current_slab.to_year != 0: - frappe(_("Row {0}: From (Year) can not be greater than To (Year)").format(current_slab.idx)) + frappe.throw(_("Row {0}: From (Year) can not be greater than To (Year)").format(current_slab.idx)) if current_slab.to_year == 0 and current_slab.from_year == 0 and len(self.gratuity_rule_slabs) > 1: frappe.throw(_("You can not define multiple slabs if you have a slab with no lower and upper limits.")) diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py index 0f27315cfbf..60dcfa45297 100644 --- a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py +++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'gratuity_rule', diff --git a/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py index 1f5dc4e571e..c81d7b7b9e6 100644 --- a/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py +++ b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestGratuityRule(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py index fa468e77beb..dcd7e468655 100644 --- a/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py +++ b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class GratuityRuleSlab(Document): pass diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.py b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.py index 81e364778ca..f778fd90e13 100644 --- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.py +++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.py @@ -3,9 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + +from frappe.model.document import Document + #import frappe import erpnext -from frappe.model.document import Document + class IncomeTaxSlab(Document): def validate(self): diff --git a/erpnext/payroll/doctype/income_tax_slab/test_income_tax_slab.py b/erpnext/payroll/doctype/income_tax_slab/test_income_tax_slab.py index deaaf650a96..d76299049de 100644 --- a/erpnext/payroll/doctype/income_tax_slab/test_income_tax_slab.py +++ b/erpnext/payroll/doctype/income_tax_slab/test_income_tax_slab.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestIncomeTaxSlab(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py index b4098ecbf3e..3314677485f 100644 --- a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py +++ b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class IncomeTaxSlabOtherCharges(Document): pass diff --git a/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.py b/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.py index aeb11fd7e27..074d2232245 100644 --- a/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.py +++ b/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class PayrollEmployeeDetail(Document): pass diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py index 13cc423fc2c..f1557c78a37 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py @@ -3,15 +3,30 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.model.document import Document + +import frappe from dateutil.relativedelta import relativedelta -from frappe.utils import cint, flt, add_days, getdate, add_to_date, DATE_FORMAT, date_diff, comma_and from frappe import _ +from frappe.desk.reportview import get_filters_cond, get_match_cond +from frappe.model.document import Document +from frappe.utils import ( + DATE_FORMAT, + add_days, + add_to_date, + cint, + comma_and, + date_diff, + flt, + getdate, +) + +import erpnext +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) from erpnext.accounts.utils import get_fiscal_year from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee -from frappe.desk.reportview import get_match_cond, get_filters_cond -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions + class PayrollEntry(Document): def onload(self): @@ -529,7 +544,8 @@ def get_end_date(start_date, frequency): def get_month_details(year, month): ysd = frappe.db.get_value("Fiscal Year", year, "year_start_date") if ysd: - import calendar, datetime + import calendar + import datetime diff_mnt = cint(month)-cint(ysd.month) if diff_mnt<0: diff_mnt = 12-int(ysd.month)+cint(month) diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry_dashboard.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry_dashboard.py index 0346a7cc594..16e44d08684 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry_dashboard.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py index b80b32061f3..dd0e1270800 100644 --- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py @@ -1,19 +1,37 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest -import erpnext + import frappe from dateutil.relativedelta import relativedelta -from erpnext.accounts.utils import get_fiscal_year, getdate, nowdate from frappe.utils import add_months -from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_dates, get_end_date + +import erpnext +from erpnext.accounts.utils import get_fiscal_year, getdate, nowdate from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.payroll.doctype.salary_slip.test_salary_slip import get_salary_component_account, \ - make_earning_salary_component, make_deduction_salary_component, create_account, make_employee_salary_slip -from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure, create_salary_structure_assignment -from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry, create_loan_type, create_loan_accounts -from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans +from erpnext.loan_management.doctype.loan.test_loan import ( + create_loan, + create_loan_accounts, + create_loan_type, + make_loan_disbursement_entry, +) +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_term_loans, +) +from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_end_date, get_start_end_dates +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + create_account, + get_salary_component_account, + make_deduction_salary_component, + make_earning_salary_component, + make_employee_salary_slip, +) +from erpnext.payroll.doctype.salary_structure.test_salary_structure import ( + create_salary_structure_assignment, + make_salary_structure, +) test_dependencies = ['Holiday List'] diff --git a/erpnext/payroll/doctype/payroll_period/payroll_period.py b/erpnext/payroll/doctype/payroll_period/payroll_period.py index 66dec075d8f..0de8d63df73 100644 --- a/erpnext/payroll/doctype/payroll_period/payroll_period.py +++ b/erpnext/payroll/doctype/payroll_period/payroll_period.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import date_diff, getdate, formatdate, cint, month_diff, flt, add_months from frappe.model.document import Document +from frappe.utils import add_months, cint, date_diff, flt, formatdate, getdate, month_diff + from erpnext.hr.utils import get_holiday_dates_for_employee + class PayrollPeriod(Document): def validate(self): self.validate_dates() diff --git a/erpnext/payroll/doctype/payroll_period/payroll_period_dashboard.py b/erpnext/payroll/doctype/payroll_period/payroll_period_dashboard.py index e33299559cc..4105d8ee928 100644 --- a/erpnext/payroll/doctype/payroll_period/payroll_period_dashboard.py +++ b/erpnext/payroll/doctype/payroll_period/payroll_period_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/payroll/doctype/payroll_period/test_payroll_period.py b/erpnext/payroll/doctype/payroll_period/test_payroll_period.py index d06dc739a6e..e93c0e524de 100644 --- a/erpnext/payroll/doctype/payroll_period/test_payroll_period.py +++ b/erpnext/payroll/doctype/payroll_period/test_payroll_period.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestPayrollPeriod(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/payroll_period_date/payroll_period_date.py b/erpnext/payroll/doctype/payroll_period_date/payroll_period_date.py index a3ee269d8e6..fa6835da53b 100644 --- a/erpnext/payroll/doctype/payroll_period_date/payroll_period_date.py +++ b/erpnext/payroll/doctype/payroll_period_date/payroll_period_date.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PayrollPeriodDate(Document): pass diff --git a/erpnext/payroll/doctype/payroll_settings/payroll_settings.py b/erpnext/payroll/doctype/payroll_settings/payroll_settings.py index 459b7eacb43..b85d5545d04 100644 --- a/erpnext/payroll/doctype/payroll_settings/payroll_settings.py +++ b/erpnext/payroll/doctype/payroll_settings/payroll_settings.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe +from frappe import _ +from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.model.document import Document from frappe.utils import cint -from frappe.custom.doctype.property_setter.property_setter import make_property_setter -from frappe import _ + class PayrollSettings(Document): def validate(self): diff --git a/erpnext/payroll/doctype/payroll_settings/test_payroll_settings.py b/erpnext/payroll/doctype/payroll_settings/test_payroll_settings.py index 314866e128e..30a6a332b7c 100644 --- a/erpnext/payroll/doctype/payroll_settings/test_payroll_settings.py +++ b/erpnext/payroll/doctype/payroll_settings/test_payroll_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestPayrollSettings(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py index 055bea74108..7e731e7fce1 100644 --- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py +++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document from frappe.utils import getdate + from erpnext.hr.utils import validate_active_employee + + class RetentionBonus(Document): def validate(self): validate_active_employee(self.employee) diff --git a/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.py b/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.py index eef4f1444e1..a380d9fb44a 100644 --- a/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.py +++ b/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestRetentionBonus(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/salary_component/salary_component.py b/erpnext/payroll/doctype/salary_component/salary_component.py index 7c926314a21..761d4436f37 100644 --- a/erpnext/payroll/doctype/salary_component/salary_component.py +++ b/erpnext/payroll/doctype/salary_component/salary_component.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists + class SalaryComponent(Document): def validate(self): self.validate_abbr() diff --git a/erpnext/payroll/doctype/salary_component/test_salary_component.py b/erpnext/payroll/doctype/salary_component/test_salary_component.py index 4f7db0c71ca..939fa4aade1 100644 --- a/erpnext/payroll/doctype/salary_component/test_salary_component.py +++ b/erpnext/payroll/doctype/salary_component/test_salary_component.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + # test_records = frappe.get_test_records('Salary Component') class TestSalaryComponent(unittest.TestCase): diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.py b/erpnext/payroll/doctype/salary_detail/salary_detail.py index 0b187543d48..50d1958caec 100644 --- a/erpnext/payroll/doctype/salary_detail/salary_detail.py +++ b/erpnext/payroll/doctype/salary_detail/salary_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SalaryDetail(Document): pass diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.js b/erpnext/payroll/doctype/salary_slip/salary_slip.js index 5258f3aff9e..3ef9762a839 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.js +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.js @@ -135,15 +135,15 @@ frappe.ui.form.on("Salary Slip", { change_form_labels: function(frm, company_currency) { frm.set_currency_labels(["base_hour_rate", "base_gross_pay", "base_total_deduction", - "base_net_pay", "base_rounded_total", "base_total_in_words", "base_year_to_date", "base_month_to_date"], + "base_net_pay", "base_rounded_total", "base_total_in_words", "base_year_to_date", "base_month_to_date", "gross_base_year_to_date"], company_currency); - frm.set_currency_labels(["hour_rate", "gross_pay", "total_deduction", "net_pay", "rounded_total", "total_in_words", "year_to_date", "month_to_date"], + frm.set_currency_labels(["hour_rate", "gross_pay", "total_deduction", "net_pay", "rounded_total", "total_in_words", "year_to_date", "month_to_date", "gross_year_to_date"], frm.doc.currency); // toggle fields frm.toggle_display(["exchange_rate", "base_hour_rate", "base_gross_pay", "base_total_deduction", - "base_net_pay", "base_rounded_total", "base_total_in_words", "base_year_to_date", "base_month_to_date"], + "base_net_pay", "base_rounded_total", "base_total_in_words", "base_year_to_date", "base_month_to_date", "base_gross_year_to_date"], frm.doc.currency != company_currency); }, diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json index 42a0f290cb4..fbbf86c4a98 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.json +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json @@ -56,6 +56,8 @@ "totals", "gross_pay", "base_gross_pay", + "gross_year_to_date", + "base_gross_year_to_date", "column_break_25", "total_deduction", "base_total_deduction", @@ -625,13 +627,27 @@ "label": "Leave Details", "options": "Salary Slip Leave", "read_only": 1 + }, + { + "fieldname": "gross_year_to_date", + "fieldtype": "Currency", + "label": "Gross Year To Date", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "base_gross_year_to_date", + "fieldtype": "Currency", + "label": "Gross Year To Date(Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 } ], "icon": "fa fa-file-text", "idx": 9, "is_submittable": 1, "links": [], - "modified": "2021-03-31 22:44:09.772331", + "modified": "2021-09-01 10:22:52.374549", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Slip", diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index fbe4742e21c..695aafffb52 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -2,27 +2,51 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -import datetime, math -from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, formatdate, get_first_day +import datetime +import math + +import frappe +from frappe import _, msgprint from frappe.model.naming import make_autoname - -from frappe import msgprint, _ -from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_dates -from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee -from erpnext.hr.utils import get_holiday_dates_for_employee -from erpnext.utilities.transaction_base import TransactionBase +from frappe.utils import ( + add_days, + cint, + cstr, + date_diff, + flt, + formatdate, + get_first_day, + getdate, + money_in_words, + rounded, +) from frappe.utils.background_jobs import enqueue -from erpnext.payroll.doctype.additional_salary.additional_salary import get_additional_salaries -from erpnext.payroll.doctype.payroll_period.payroll_period import get_period_factor, get_payroll_period -from erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application import get_benefit_component_amount -from erpnext.payroll.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount, get_last_payroll_period_benefits -from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts, create_repayment_entry -from erpnext.accounts.utils import get_fiscal_year -from erpnext.hr.utils import validate_active_employee from six import iteritems +import erpnext +from erpnext.accounts.utils import get_fiscal_year +from erpnext.hr.utils import get_holiday_dates_for_employee, validate_active_employee +from erpnext.loan_management.doctype.loan_repayment.loan_repayment import ( + calculate_amounts, + create_repayment_entry, +) +from erpnext.payroll.doctype.additional_salary.additional_salary import get_additional_salaries +from erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application import ( + get_benefit_component_amount, +) +from erpnext.payroll.doctype.employee_benefit_claim.employee_benefit_claim import ( + get_benefit_claim_amount, + get_last_payroll_period_benefits, +) +from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_dates +from erpnext.payroll.doctype.payroll_period.payroll_period import ( + get_payroll_period, + get_period_factor, +) +from erpnext.utilities.transaction_base import TransactionBase + + class SalarySlip(TransactionBase): def __init__(self, *args, **kwargs): super(SalarySlip, self).__init__(*args, **kwargs) @@ -1218,7 +1242,7 @@ class SalarySlip(TransactionBase): period_start_date, period_end_date = self.get_year_to_date_period() salary_slip_sum = frappe.get_list('Salary Slip', - fields = ['sum(net_pay) as sum'], + fields = ['sum(net_pay) as net_sum', 'sum(gross_pay) as gross_sum'], filters = {'employee_name' : self.employee_name, 'start_date' : ['>=', period_start_date], 'end_date' : ['<', period_end_date], @@ -1226,10 +1250,13 @@ class SalarySlip(TransactionBase): 'docstatus': 1 }) - year_to_date = flt(salary_slip_sum[0].sum) if salary_slip_sum else 0.0 + year_to_date = flt(salary_slip_sum[0].net_sum) if salary_slip_sum else 0.0 + gross_year_to_date = flt(salary_slip_sum[0].gross_sum) if salary_slip_sum else 0.0 year_to_date += self.net_pay + gross_year_to_date += self.gross_pay self.year_to_date = year_to_date + self.gross_year_to_date = gross_year_to_date def compute_month_to_date(self): month_to_date = 0 diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index 6e8d3b3f306..07b84b27a33 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -2,20 +2,34 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest -import frappe -import erpnext import calendar import random +import unittest + +import frappe +from frappe.utils import ( + add_days, + add_months, + cstr, + flt, + get_first_day, + get_last_day, + getdate, + nowdate, +) + +import erpnext from erpnext.accounts.utils import get_fiscal_year -from frappe.utils import getdate, nowdate, add_days, add_months, flt, get_first_day, get_last_day, cstr -from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip -from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type -from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration \ - import create_payroll_period, create_exemption_category +from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import ( + create_exemption_category, + create_payroll_period, +) +from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details +from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip + class TestSalarySlip(unittest.TestCase): def setUp(self): @@ -154,7 +168,9 @@ class TestSalarySlip(unittest.TestCase): self.assertEqual(ss.gross_pay, 78000) def test_payment_days(self): - from erpnext.payroll.doctype.salary_structure.test_salary_structure import create_salary_structure_assignment + from erpnext.payroll.doctype.salary_structure.test_salary_structure import ( + create_salary_structure_assignment, + ) no_of_days = self.get_no_of_days() # Holidays not included in working days @@ -231,8 +247,15 @@ class TestSalarySlip(unittest.TestCase): self.assertTrue(email_queue) def test_loan_repayment_salary_slip(self): - from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan, make_loan_disbursement_entry, create_loan_accounts - from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans + from erpnext.loan_management.doctype.loan.test_loan import ( + create_loan, + create_loan_accounts, + create_loan_type, + make_loan_disbursement_entry, + ) + from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import ( + process_loan_interest_accrual_for_term_loans, + ) from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure applicant = make_employee("test_loan_repayment_salary_slip@salary.com", company="_Test Company") @@ -386,8 +409,7 @@ class TestSalarySlip(unittest.TestCase): for doc in delete_docs: frappe.db.sql("delete from `tab%s` where employee='%s'" % (doc, employee)) - from erpnext.payroll.doctype.salary_structure.test_salary_structure import \ - make_salary_structure, create_salary_structure_assignment + from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure salary_structure = make_salary_structure("Stucture to test tax", "Monthly", other_details={"max_benefits": 100000}, test_tax=True, diff --git a/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py index 7a92bf18f76..fc8282b82ba 100644 --- a/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py +++ b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class SalarySlipLeave(Document): pass diff --git a/erpnext/payroll/doctype/salary_slip_timesheet/salary_slip_timesheet.py b/erpnext/payroll/doctype/salary_slip_timesheet/salary_slip_timesheet.py index 7adb12e83a4..79c4c6e5715 100644 --- a/erpnext/payroll/doctype/salary_slip_timesheet/salary_slip_timesheet.py +++ b/erpnext/payroll/doctype/salary_slip_timesheet/salary_slip_timesheet.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class SalarySlipTimesheet(Document): pass diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.py b/erpnext/payroll/doctype/salary_structure/salary_structure.py index 6dfb3a57d5d..ef401b2d1a7 100644 --- a/erpnext/payroll/doctype/salary_structure/salary_structure.py +++ b/erpnext/payroll/doctype/salary_structure/salary_structure.py @@ -2,13 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import flt, cint, cstr +import frappe from frappe import _ -from frappe.model.mapper import get_mapped_doc from frappe.model.document import Document -from six import iteritems +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, cstr, flt + +import erpnext + class SalaryStructure(Document): def validate(self): diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure_dashboard.py b/erpnext/payroll/doctype/salary_structure/salary_structure_dashboard.py index 0159e3530fb..11d9a944096 100644 --- a/erpnext/payroll/doctype/salary_structure/salary_structure_dashboard.py +++ b/erpnext/payroll/doctype/salary_structure/salary_structure_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py index 3957d834d33..ff4a55e29cf 100644 --- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py +++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py @@ -2,17 +2,24 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -import erpnext -from frappe.utils.make_random import get_random -from frappe.utils import nowdate, add_years, get_first_day, date_diff -from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip -from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\ - make_deduction_salary_component, make_employee_salary_slip, create_tax_slab -from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import create_payroll_period +import frappe +from frappe.utils import add_years, date_diff, get_first_day, nowdate +from frappe.utils.make_random import get_random + +import erpnext +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import ( + create_payroll_period, +) +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + create_tax_slab, + make_deduction_salary_component, + make_earning_salary_component, + make_employee_salary_slip, +) +from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip test_dependencies = ["Fiscal Year"] diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py index 5fb3ce2a98e..385cf36b7f5 100644 --- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py +++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate from frappe.model.document import Document +from frappe.utils import getdate + class DuplicateAssignment(frappe.ValidationError): pass diff --git a/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.py b/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.py index a9833bf7338..fbb894c43ed 100644 --- a/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.py +++ b/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestSalaryStructureAssignment(unittest.TestCase): pass diff --git a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.py b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.py index 49c52557dbc..c0827c445db 100644 --- a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.py +++ b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TaxableSalarySlab(Document): pass diff --git a/erpnext/payroll/notification/retention_bonus/retention_bonus.py b/erpnext/payroll/notification/retention_bonus/retention_bonus.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/payroll/notification/retention_bonus/retention_bonus.py +++ b/erpnext/payroll/notification/retention_bonus/retention_bonus.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/payroll/report/bank_remittance/bank_remittance.py b/erpnext/payroll/report/bank_remittance/bank_remittance.py index 05a5366a5c1..d55317e71e4 100644 --- a/erpnext/payroll/report/bank_remittance/bank_remittance.py +++ b/erpnext/payroll/report/bank_remittance/bank_remittance.py @@ -2,11 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import formatdate -import itertools from frappe import _, get_all + def execute(filters=None): columns = [ { diff --git a/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py b/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py index 8a79416edbf..296a7c233f3 100644 --- a/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py +++ b/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py @@ -2,9 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ +import erpnext + + def execute(filters=None): data = get_data(filters) columns = get_columns(filters) if len(data) else [] diff --git a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py index a0dab63654e..57ea1b3c283 100644 --- a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py +++ b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py @@ -2,9 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from erpnext.regional.report.provident_fund_deductions.provident_fund_deductions import get_conditions + +import erpnext +from erpnext.regional.report.provident_fund_deductions.provident_fund_deductions import ( + get_conditions, +) + def execute(filters=None): mode_of_payments = get_payment_modes() diff --git a/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py b/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py index d09745c37bb..bc8fd9d40b2 100644 --- a/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py +++ b/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py @@ -2,9 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ +import erpnext + + def execute(filters=None): columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/payroll/report/salary_register/salary_register.py b/erpnext/payroll/report/salary_register/salary_register.py index a1b1a8c56b5..2a9dad66e25 100644 --- a/erpnext/payroll/report/salary_register/salary_register.py +++ b/erpnext/payroll/report/salary_register/salary_register.py @@ -2,9 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import flt + +import frappe from frappe import _ +from frappe.utils import flt + +import erpnext + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/portal/doctype/homepage/homepage.js b/erpnext/portal/doctype/homepage/homepage.js index c7c66e00556..59f808a3158 100644 --- a/erpnext/portal/doctype/homepage/homepage.js +++ b/erpnext/portal/doctype/homepage/homepage.js @@ -3,9 +3,9 @@ frappe.ui.form.on('Homepage', { setup: function(frm) { - frm.fields_dict["products"].grid.get_field("item_code").get_query = function(){ + frm.fields_dict["products"].grid.get_field("item").get_query = function() { return { - filters: {'show_in_website': 1} + filters: {'published': 1} } } }, @@ -21,11 +21,10 @@ frappe.ui.form.on('Homepage', { }); frappe.ui.form.on('Homepage Featured Product', { - - view: function(frm, cdt, cdn){ - var child= locals[cdt][cdn] - if(child.item_code && frm.doc.products_url){ - window.location.href = frm.doc.products_url + '/' + encodeURIComponent(child.item_code); + view: function(frm, cdt, cdn) { + var child= locals[cdt][cdn]; + if (child.item_code && child.route) { + window.open('/' + child.route, '_blank'); } } }); diff --git a/erpnext/portal/doctype/homepage/homepage.json b/erpnext/portal/doctype/homepage/homepage.json index ad27278dc69..73f816d4d49 100644 --- a/erpnext/portal/doctype/homepage/homepage.json +++ b/erpnext/portal/doctype/homepage/homepage.json @@ -1,518 +1,143 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", + "actions": [], "beta": 1, "creation": "2016-04-22 05:27:52.109319", - "custom": 0, - "docstatus": 0, "doctype": "DocType", "document_type": "Setup", - "editable_grid": 0, "engine": "InnoDB", + "field_order": [ + "company", + "hero_section_based_on", + "column_break_2", + "title", + "section_break_4", + "tag_line", + "description", + "hero_image", + "slideshow", + "hero_section", + "products_section", + "products_url", + "products" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "company", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Company", - "length": 0, - "no_copy": 0, "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "hero_section_based_on", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Hero Section Based On", - "length": 0, - "no_copy": 0, - "options": "Default\nSlideshow\nHomepage Section", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Default\nSlideshow\nHomepage Section" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", "fieldname": "title", "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": "Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Title" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", "fieldname": "section_break_4", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Hero Section", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Hero Section" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.hero_section_based_on === 'Default'", "description": "Company Tagline for website homepage", "fieldname": "tag_line", "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": "Tag Line", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.hero_section_based_on === 'Default'", "description": "Company Description for website homepage", "fieldname": "description", "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.hero_section_based_on === 'Default'", "fieldname": "hero_image", "fieldtype": "Attach Image", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Hero Image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Hero Image" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.hero_section_based_on === 'Slideshow'", - "description": "", "fieldname": "slideshow", "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": "Homepage Slideshow", - "length": 0, - "no_copy": 0, - "options": "Website Slideshow", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Website Slideshow" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.hero_section_based_on === 'Homepage Section'", "fieldname": "hero_section", "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": "Homepage Section", - "length": 0, - "no_copy": 0, - "options": "Homepage Section", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Homepage Section" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", "fieldname": "products_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": "Products", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Products" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "/products", + "default": "/all-products", "fieldname": "products_url", "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": "URL for \"All Products\"", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "URL for \"All Products\"" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "description": "Products to be shown on website homepage", "fieldname": "products", "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": "Products", - "length": 0, - "no_copy": 0, "options": "Homepage Featured Product", - "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, "width": "40px" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-02 23:12:59.676202", + "links": [], + "modified": "2021-02-18 13:29:29.531639", "modified_by": "Administrator", "module": "Portal", "name": "Homepage", - "name_case": "", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, - "report": 0, "role": "System Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, - "report": 0, "role": "Administrator", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "title_field": "company", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py index 54ea7c62df4..74e04894c6f 100644 --- a/erpnext/portal/doctype/homepage/homepage.py +++ b/erpnext/portal/doctype/homepage/homepage.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document from frappe.website.utils import delete_page_cache + class Homepage(Document): def validate(self): if not self.description: @@ -14,12 +16,14 @@ class Homepage(Document): delete_page_cache('home') def setup_items(self): - for d in frappe.get_all('Item', fields=['name', 'item_name', 'description', 'image'], - filters={'show_in_website': 1}, limit=3): + for d in frappe.get_all('Website Item', fields=['name', 'item_name', 'description', 'image', 'route'], + filters={'published': 1}, limit=3): - doc = frappe.get_doc('Item', d.name) + doc = frappe.get_doc('Website Item', d.name) if not doc.route: # set missing route doc.save() self.append('products', dict(item_code=d.name, - item_name=d.item_name, description=d.description, image=d.image)) + item_name=d.item_name, description=d.description, + image=d.image, route=d.route)) + diff --git a/erpnext/portal/doctype/homepage/test_homepage.py b/erpnext/portal/doctype/homepage/test_homepage.py index b717491a821..6f0517867d7 100644 --- a/erpnext/portal/doctype/homepage/test_homepage.py +++ b/erpnext/portal/doctype/homepage/test_homepage.py @@ -3,11 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import set_request from frappe.website.render import render + class TestHomepage(unittest.TestCase): def test_homepage_load(self): set_request(method='GET', path='home') diff --git a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json index 01c32efec9d..63789e35b56 100644 --- a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json +++ b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json @@ -25,10 +25,10 @@ "fieldtype": "Link", "in_filter": 1, "in_list_view": 1, - "label": "Item Code", + "label": "Item", "oldfieldname": "item_code", "oldfieldtype": "Link", - "options": "Item", + "options": "Website Item", "print_width": "150px", "reqd": 1, "search_index": 1, @@ -63,7 +63,7 @@ "collapsible": 1, "fieldname": "section_break_5", "fieldtype": "Section Break", - "label": "Description" + "label": "Details" }, { "fetch_from": "item_code.web_long_description", @@ -89,12 +89,14 @@ "label": "Image" }, { + "fetch_from": "item_code.thumbnail", "fieldname": "thumbnail", "fieldtype": "Attach Image", "hidden": 1, "label": "Thumbnail" }, { + "fetch_from": "item_code.route", "fieldname": "route", "fieldtype": "Small Text", "label": "route", @@ -104,7 +106,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-08-25 15:27:49.573537", + "modified": "2021-02-18 13:05:50.669311", "modified_by": "Administrator", "module": "Portal", "name": "Homepage Featured Product", diff --git a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py index 936e07d34ea..8e8f77605e6 100644 --- a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py +++ b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class HomepageFeaturedProduct(Document): pass diff --git a/erpnext/portal/doctype/homepage_section/homepage_section.py b/erpnext/portal/doctype/homepage_section/homepage_section.py index 1ed703050b8..081786126e7 100644 --- a/erpnext/portal/doctype/homepage_section/homepage_section.py +++ b/erpnext/portal/doctype/homepage_section/homepage_section.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document from frappe.utils import cint + class HomepageSection(Document): @property def column_value(self): diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py index f0aa554858a..75aa5b28f11 100644 --- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py +++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py @@ -3,12 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from bs4 import BeautifulSoup from frappe.utils import set_request from frappe.website.render import render + class TestHomepageSection(unittest.TestCase): def test_homepage_section_card(self): try: diff --git a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py index bd17279f99a..b71045207cc 100644 --- a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py +++ b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class HomepageSectionCard(Document): pass diff --git a/erpnext/portal/doctype/products_settings/products_settings.js b/erpnext/portal/doctype/products_settings/products_settings.js deleted file mode 100644 index 2f8b0371648..00000000000 --- a/erpnext/portal/doctype/products_settings/products_settings.js +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Products Settings', { - refresh: function(frm) { - frappe.model.with_doctype('Item', () => { - const item_meta = frappe.get_meta('Item'); - - const valid_fields = item_meta.fields.filter( - df => ['Link', 'Table MultiSelect'].includes(df.fieldtype) && !df.hidden - ).map(df => ({ label: df.label, value: df.fieldname })); - - frm.fields_dict.filter_fields.grid.update_docfield_property( - 'fieldname', 'fieldtype', 'Select' - ); - frm.fields_dict.filter_fields.grid.update_docfield_property( - 'fieldname', 'options', valid_fields - ); - }); - } -}); diff --git a/erpnext/portal/doctype/products_settings/products_settings.json b/erpnext/portal/doctype/products_settings/products_settings.json deleted file mode 100644 index 2cf8431497c..00000000000 --- a/erpnext/portal/doctype/products_settings/products_settings.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-04-22 09:11:55.272398", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "If checked, the Home page will be the default Item Group for the website", - "fieldname": "home_page_is_products", - "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": "Home Page is Products", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "show_availability_status", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show Availability Status", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "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, - "label": "Product Page", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "6", - "fieldname": "products_per_page", - "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": "Products per Page", - "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 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enable_field_filters", - "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": "Enable Field Filters", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "enable_field_filters", - "fieldname": "filter_fields", - "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": "Item Fields", - "length": 0, - "no_copy": 0, - "options": "Website Filter Field", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enable_attribute_filters", - "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": "Enable Attribute Filters", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "enable_attribute_filters", - "fieldname": "filter_attributes", - "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": "Attributes", - "length": 0, - "no_copy": 0, - "options": "Website Attribute", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "hide_variants", - "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": "Hide Variants", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-07 19:18:31.822309", - "modified_by": "Administrator", - "module": "Portal", - "name": "Products Settings", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "Website Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file diff --git a/erpnext/portal/doctype/products_settings/products_settings.py b/erpnext/portal/doctype/products_settings/products_settings.py deleted file mode 100644 index 9a708924ae0..00000000000 --- a/erpnext/portal/doctype/products_settings/products_settings.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint -from frappe import _ -from frappe.model.document import Document - -class ProductsSettings(Document): - def validate(self): - if self.home_page_is_products: - frappe.db.set_value("Website Settings", None, "home_page", "products") - elif frappe.db.get_single_value("Website Settings", "home_page") == 'products': - frappe.db.set_value("Website Settings", None, "home_page", "home") - - self.validate_field_filters() - self.validate_attribute_filters() - frappe.clear_document_cache("Product Settings", "Product Settings") - - def validate_field_filters(self): - if not (self.enable_field_filters and self.filter_fields): return - - item_meta = frappe.get_meta('Item') - valid_fields = [df.fieldname for df in item_meta.fields if df.fieldtype in ['Link', 'Table MultiSelect']] - - for f in self.filter_fields: - if f.fieldname not in valid_fields: - frappe.throw(_('Filter Fields Row #{0}: Fieldname {1} must be of type "Link" or "Table MultiSelect"').format(f.idx, f.fieldname)) - - def validate_attribute_filters(self): - if not (self.enable_attribute_filters and self.filter_attributes): return - - # if attribute filters are enabled, hide_variants should be disabled - self.hide_variants = 0 - - -def home_page_is_products(doc, method): - '''Called on saving Website Settings''' - home_page_is_products = cint(frappe.db.get_single_value('Products Settings', 'home_page_is_products')) - if home_page_is_products: - doc.home_page = 'products' diff --git a/erpnext/portal/doctype/products_settings/test_products_settings.py b/erpnext/portal/doctype/products_settings/test_products_settings.py deleted file mode 100644 index d04a0098829..00000000000 --- a/erpnext/portal/doctype/products_settings/test_products_settings.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import frappe -import unittest - -class TestProductsSettings(unittest.TestCase): - pass diff --git a/erpnext/portal/doctype/website_attribute/website_attribute.json b/erpnext/portal/doctype/website_attribute/website_attribute.json index 2874dc432c7..eed33ec10e4 100644 --- a/erpnext/portal/doctype/website_attribute/website_attribute.json +++ b/erpnext/portal/doctype/website_attribute/website_attribute.json @@ -1,76 +1,32 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2019-01-01 13:04:54.479079", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "creation": "2019-01-01 13:04:54.479079", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "attribute" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "attribute", - "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": "Attribute", - "length": 0, - "no_copy": 0, - "options": "Item Attribute", - "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": "attribute", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Attribute", + "options": "Item Attribute", + "reqd": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2019-01-01 13:04:59.715572", - "modified_by": "Administrator", - "module": "Portal", - "name": "Website Attribute", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "istable": 1, + "links": [], + "modified": "2021-02-18 13:18:57.810536", + "modified_by": "Administrator", + "module": "Portal", + "name": "Website Attribute", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/portal/doctype/website_attribute/website_attribute.py b/erpnext/portal/doctype/website_attribute/website_attribute.py index b8b667a6135..f9ba733b85d 100644 --- a/erpnext/portal/doctype/website_attribute/website_attribute.py +++ b/erpnext/portal/doctype/website_attribute/website_attribute.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class WebsiteAttribute(Document): pass diff --git a/erpnext/portal/doctype/website_filter_field/website_filter_field.py b/erpnext/portal/doctype/website_filter_field/website_filter_field.py index 2aa8a6f98d4..335d4575b61 100644 --- a/erpnext/portal/doctype/website_filter_field/website_filter_field.py +++ b/erpnext/portal/doctype/website_filter_field/website_filter_field.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class WebsiteFilterField(Document): pass diff --git a/erpnext/portal/product_configurator/test_product_configurator.py b/erpnext/portal/product_configurator/test_product_configurator.py deleted file mode 100644 index 28e064218b1..00000000000 --- a/erpnext/portal/product_configurator/test_product_configurator.py +++ /dev/null @@ -1,144 +0,0 @@ -from __future__ import unicode_literals - -from bs4 import BeautifulSoup -import frappe, unittest -from frappe.utils import set_request, get_html_for_route -from frappe.website.render import render -from erpnext.portal.product_configurator.utils import get_products_for_website -from erpnext.stock.doctype.item.test_item import make_item_variant - -test_dependencies = ["Item"] - -class TestProductConfigurator(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.create_variant_item() - - @classmethod - def create_variant_item(cls): - if not frappe.db.exists('Item', '_Test Variant Item - 2XL'): - frappe.get_doc({ - "description": "_Test Variant Item - 2XL", - "item_code": "_Test Variant Item - 2XL", - "item_name": "_Test Variant Item - 2XL", - "doctype": "Item", - "is_stock_item": 1, - "variant_of": "_Test Variant Item", - "item_group": "_Test Item Group", - "stock_uom": "_Test UOM", - "item_defaults": [{ - "company": "_Test Company", - "default_warehouse": "_Test Warehouse - _TC", - "expense_account": "_Test Account Cost for Goods Sold - _TC", - "buying_cost_center": "_Test Cost Center - _TC", - "selling_cost_center": "_Test Cost Center - _TC", - "income_account": "Sales - _TC" - }], - "attributes": [ - { - "attribute": "Test Size", - "attribute_value": "2XL" - } - ], - "show_variant_in_website": 1 - }).insert() - - def create_regular_web_item(self, name, item_group=None): - if not frappe.db.exists('Item', name): - doc = frappe.get_doc({ - "description": name, - "item_code": name, - "item_name": name, - "doctype": "Item", - "is_stock_item": 1, - "item_group": item_group or "_Test Item Group", - "stock_uom": "_Test UOM", - "item_defaults": [{ - "company": "_Test Company", - "default_warehouse": "_Test Warehouse - _TC", - "expense_account": "_Test Account Cost for Goods Sold - _TC", - "buying_cost_center": "_Test Cost Center - _TC", - "selling_cost_center": "_Test Cost Center - _TC", - "income_account": "Sales - _TC" - }], - "show_in_website": 1 - }).insert() - else: - doc = frappe.get_doc("Item", name) - return doc - - def test_product_list(self): - template_items = frappe.get_all('Item', {'show_in_website': 1}) - variant_items = frappe.get_all('Item', {'show_variant_in_website': 1}) - - products_settings = frappe.get_doc('Products Settings') - products_settings.enable_field_filters = 1 - products_settings.append('filter_fields', {'fieldname': 'item_group'}) - products_settings.append('filter_fields', {'fieldname': 'stock_uom'}) - products_settings.save() - - html = get_html_for_route('all-products') - - soup = BeautifulSoup(html, 'html.parser') - products_list = soup.find(class_='products-list') - items = products_list.find_all(class_='card') - self.assertEqual(len(items), len(template_items + variant_items)) - - items_with_item_group = frappe.get_all('Item', {'item_group': '_Test Item Group Desktops', 'show_in_website': 1}) - variants_with_item_group = frappe.get_all('Item', {'item_group': '_Test Item Group Desktops', 'show_variant_in_website': 1}) - - # mock query params - frappe.form_dict = frappe._dict({ - 'field_filters': '{"item_group":["_Test Item Group Desktops"]}' - }) - html = get_html_for_route('all-products') - soup = BeautifulSoup(html, 'html.parser') - products_list = soup.find(class_='products-list') - items = products_list.find_all(class_='card') - self.assertEqual(len(items), len(items_with_item_group + variants_with_item_group)) - - - def test_get_products_for_website(self): - items = get_products_for_website(attribute_filters={ - 'Test Size': ['2XL'] - }) - self.assertEqual(len(items), 1) - - def test_products_in_multiple_item_groups(self): - """Check if product is visible on multiple item group pages barring its own.""" - from erpnext.shopping_cart.product_query import ProductQuery - - if not frappe.db.exists("Item Group", {"name": "Tech Items"}): - item_group_doc = frappe.get_doc({ - "doctype": "Item Group", - "item_group_name": "Tech Items", - "parent_item_group": "All Item Groups", - "show_in_website": 1 - }).insert() - else: - item_group_doc = frappe.get_doc("Item Group", "Tech Items") - - doc = self.create_regular_web_item("Portal Item", item_group="Tech Items") - if not frappe.db.exists("Website Item Group", {"parent": "Portal Item"}): - doc.append("website_item_groups", { - "item_group": "_Test Item Group Desktops" - }) - doc.save() - - # check if item is visible in its own Item Group's page - engine = ProductQuery() - items = engine.query({}, {"item_group": "Tech Items"}, None, start=0, item_group="Tech Items") - self.assertEqual(len(items), 1) - self.assertEqual(items[0].item_code, "Portal Item") - - # check if item is visible in configured foreign Item Group's page - engine = ProductQuery() - items = engine.query({}, {"item_group": "_Test Item Group Desktops"}, None, start=0, item_group="_Test Item Group Desktops") - item_codes = [row.item_code for row in items] - - self.assertIn(len(items), [2, 3]) - self.assertIn("Portal Item", item_codes) - - # teardown - doc.delete() - item_group_doc.delete() diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py deleted file mode 100644 index d60b1a2b05e..00000000000 --- a/erpnext/portal/product_configurator/utils.py +++ /dev/null @@ -1,444 +0,0 @@ -import frappe -from frappe.utils import cint -from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager -from erpnext.shopping_cart.product_info import get_product_info_for_website -from erpnext.setup.doctype.item_group.item_group import get_child_groups - -def get_field_filter_data(): - product_settings = get_product_settings() - filter_fields = [row.fieldname for row in product_settings.filter_fields] - - meta = frappe.get_meta('Item') - fields = [df for df in meta.fields if df.fieldname in filter_fields] - - filter_data = [] - for f in fields: - doctype = f.get_link_doctype() - - # apply enable/disable/show_in_website filter - meta = frappe.get_meta(doctype) - filters = {} - if meta.has_field('enabled'): - filters['enabled'] = 1 - if meta.has_field('disabled'): - filters['disabled'] = 0 - if meta.has_field('show_in_website'): - filters['show_in_website'] = 1 - - values = [d.name for d in frappe.get_all(doctype, filters)] - filter_data.append([f, values]) - - return filter_data - - -def get_attribute_filter_data(): - product_settings = get_product_settings() - attributes = [row.attribute for row in product_settings.filter_attributes] - attribute_docs = [ - frappe.get_doc('Item Attribute', attribute) for attribute in attributes - ] - - # mark attribute values as checked if they are present in the request url - if frappe.form_dict: - for attr in attribute_docs: - if attr.name in frappe.form_dict: - value = frappe.form_dict[attr.name] - if value: - enabled_values = value.split(',') - else: - enabled_values = [] - - for v in enabled_values: - for item_attribute_row in attr.item_attribute_values: - if v == item_attribute_row.attribute_value: - item_attribute_row.checked = True - - return attribute_docs - - -def get_products_for_website(field_filters=None, attribute_filters=None, search=None): - if attribute_filters: - item_codes = get_item_codes_by_attributes(attribute_filters) - items_by_attributes = get_items([['name', 'in', item_codes]]) - - if field_filters: - items_by_fields = get_items_by_fields(field_filters) - - if attribute_filters and not field_filters: - return items_by_attributes - - if field_filters and not attribute_filters: - return items_by_fields - - if field_filters and attribute_filters: - items_intersection = [] - item_codes_in_attribute = [item.name for item in items_by_attributes] - - for item in items_by_fields: - if item.name in item_codes_in_attribute: - items_intersection.append(item) - - return items_intersection - - if search: - return get_items(search=search) - - return get_items() - - -@frappe.whitelist(allow_guest=True) -def get_products_html_for_website(field_filters=None, attribute_filters=None): - field_filters = frappe.parse_json(field_filters) - attribute_filters = frappe.parse_json(attribute_filters) - set_item_group_filters(field_filters) - - items = get_products_for_website(field_filters, attribute_filters) - html = ''.join(get_html_for_items(items)) - - if not items: - html = frappe.render_template('erpnext/www/all-products/not_found.html', {}) - - return html - -def set_item_group_filters(field_filters): - if field_filters is not None and 'item_group' in field_filters: - field_filters['item_group'] = [ig[0] for ig in get_child_groups(field_filters['item_group'])] - - -def get_item_codes_by_attributes(attribute_filters, template_item_code=None): - items = [] - - for attribute, values in attribute_filters.items(): - attribute_values = values - - if not isinstance(attribute_values, list): - attribute_values = [attribute_values] - - if not attribute_values: continue - - wheres = [] - query_values = [] - for attribute_value in attribute_values: - wheres.append('( attribute = %s and attribute_value = %s )') - query_values += [attribute, attribute_value] - - attribute_query = ' or '.join(wheres) - - if template_item_code: - variant_of_query = 'AND t2.variant_of = %s' - query_values.append(template_item_code) - else: - variant_of_query = '' - - query = ''' - SELECT - t1.parent - FROM - `tabItem Variant Attribute` t1 - WHERE - 1 = 1 - AND ( - {attribute_query} - ) - AND EXISTS ( - SELECT - 1 - FROM - `tabItem` t2 - WHERE - t2.name = t1.parent - {variant_of_query} - ) - GROUP BY - t1.parent - ORDER BY - NULL - '''.format(attribute_query=attribute_query, variant_of_query=variant_of_query) - - item_codes = set([r[0] for r in frappe.db.sql(query, query_values)]) - items.append(item_codes) - - res = list(set.intersection(*items)) - - return res - - -@frappe.whitelist(allow_guest=True) -def get_attributes_and_values(item_code): - '''Build a list of attributes and their possible values. - This will ignore the values upon selection of which there cannot exist one item. - ''' - item_cache = ItemVariantsCacheManager(item_code) - item_variants_data = item_cache.get_item_variants_data() - - attributes = get_item_attributes(item_code) - attribute_list = [a.attribute for a in attributes] - - valid_options = {} - for item_code, attribute, attribute_value in item_variants_data: - if attribute in attribute_list: - valid_options.setdefault(attribute, set()).add(attribute_value) - - item_attribute_values = frappe.db.get_all('Item Attribute Value', - ['parent', 'attribute_value', 'idx'], order_by='parent asc, idx asc') - ordered_attribute_value_map = frappe._dict() - for iv in item_attribute_values: - ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value) - - # build attribute values in idx order - for attr in attributes: - valid_attribute_values = valid_options.get(attr.attribute, []) - ordered_values = ordered_attribute_value_map.get(attr.attribute, []) - attr['values'] = [v for v in ordered_values if v in valid_attribute_values] - - return attributes - - -@frappe.whitelist(allow_guest=True) -def get_next_attribute_and_values(item_code, selected_attributes): - '''Find the count of Items that match the selected attributes. - Also, find the attribute values that are not applicable for further searching. - If less than equal to 10 items are found, return item_codes of those items. - If one item is matched exactly, return item_code of that item. - ''' - selected_attributes = frappe.parse_json(selected_attributes) - - item_cache = ItemVariantsCacheManager(item_code) - item_variants_data = item_cache.get_item_variants_data() - - attributes = get_item_attributes(item_code) - attribute_list = [a.attribute for a in attributes] - filtered_items = get_items_with_selected_attributes(item_code, selected_attributes) - - next_attribute = None - - for attribute in attribute_list: - if attribute not in selected_attributes: - next_attribute = attribute - break - - valid_options_for_attributes = frappe._dict({}) - - for a in attribute_list: - valid_options_for_attributes[a] = set() - - selected_attribute = selected_attributes.get(a, None) - if selected_attribute: - # already selected attribute values are valid options - valid_options_for_attributes[a].add(selected_attribute) - - for row in item_variants_data: - item_code, attribute, attribute_value = row - if item_code in filtered_items and attribute not in selected_attributes and attribute in attribute_list: - valid_options_for_attributes[attribute].add(attribute_value) - - optional_attributes = item_cache.get_optional_attributes() - exact_match = [] - # search for exact match if all selected attributes are required attributes - if len(selected_attributes.keys()) >= (len(attribute_list) - len(optional_attributes)): - item_attribute_value_map = item_cache.get_item_attribute_value_map() - for item_code, attr_dict in item_attribute_value_map.items(): - if item_code in filtered_items and set(attr_dict.keys()) == set(selected_attributes.keys()): - exact_match.append(item_code) - - filtered_items_count = len(filtered_items) - - # get product info if exact match - from erpnext.shopping_cart.product_info import get_product_info_for_website - if exact_match: - data = get_product_info_for_website(exact_match[0]) - product_info = data.product_info - if product_info: - product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock) - if not data.cart_settings.show_price: - product_info = None - else: - product_info = None - - return { - 'next_attribute': next_attribute, - 'valid_options_for_attributes': valid_options_for_attributes, - 'filtered_items_count': filtered_items_count, - 'filtered_items': filtered_items if filtered_items_count < 10 else [], - 'exact_match': exact_match, - 'product_info': product_info - } - - -def get_items_with_selected_attributes(item_code, selected_attributes): - item_cache = ItemVariantsCacheManager(item_code) - attribute_value_item_map = item_cache.get_attribute_value_item_map() - - items = [] - for attribute, value in selected_attributes.items(): - filtered_items = attribute_value_item_map.get((attribute, value), []) - items.append(set(filtered_items)) - - return set.intersection(*items) - - -def get_items_by_fields(field_filters): - meta = frappe.get_meta('Item') - filters = [] - for fieldname, values in field_filters.items(): - if not values: continue - - _doctype = 'Item' - _fieldname = fieldname - - df = meta.get_field(fieldname) - if df.fieldtype == 'Table MultiSelect': - child_doctype = df.options - child_meta = frappe.get_meta(child_doctype) - fields = child_meta.get("fields", { "fieldtype": "Link", "in_list_view": 1 }) - if fields: - _doctype = child_doctype - _fieldname = fields[0].fieldname - - if len(values) == 1: - filters.append([_doctype, _fieldname, '=', values[0]]) - else: - filters.append([_doctype, _fieldname, 'in', values]) - - return get_items(filters) - - -def get_items(filters=None, search=None): - start = frappe.form_dict.get('start', 0) - products_settings = get_product_settings() - page_length = products_settings.products_per_page - - filters = filters or [] - # convert to list of filters - if isinstance(filters, dict): - filters = [['Item', fieldname, '=', value] for fieldname, value in filters.items()] - - enabled_items_filter = get_conditions({ 'disabled': 0 }, 'and') - - show_in_website_condition = '' - if products_settings.hide_variants: - show_in_website_condition = get_conditions({'show_in_website': 1 }, 'and') - else: - show_in_website_condition = get_conditions([ - ['show_in_website', '=', 1], - ['show_variant_in_website', '=', 1] - ], 'or') - - search_condition = '' - if search: - # Default fields to search from - default_fields = {'name', 'item_name', 'description', 'item_group'} - - # Get meta search fields - meta = frappe.get_meta("Item") - meta_fields = set(meta.get_search_fields()) - - # Join the meta fields and default fields set - search_fields = default_fields.union(meta_fields) - try: - if frappe.db.count('Item', cache=True) > 50000: - search_fields.remove('description') - except KeyError: - pass - - # Build or filters for query - search = '%{}%'.format(search) - or_filters = [[field, 'like', search] for field in search_fields] - - search_condition = get_conditions(or_filters, 'or') - - filter_condition = get_conditions(filters, 'and') - - where_conditions = ' and '.join( - [condition for condition in [enabled_items_filter, show_in_website_condition, \ - search_condition, filter_condition] if condition] - ) - - left_joins = [] - for f in filters: - if len(f) == 4 and f[0] != 'Item': - left_joins.append(f[0]) - - left_join = ' '.join(['LEFT JOIN `tab{0}` on (`tab{0}`.parent = `tabItem`.name)'.format(l) for l in left_joins]) - - results = frappe.db.sql(''' - SELECT - `tabItem`.`name`, `tabItem`.`item_name`, `tabItem`.`item_code`, - `tabItem`.`website_image`, `tabItem`.`image`, - `tabItem`.`web_long_description`, `tabItem`.`description`, - `tabItem`.`route`, `tabItem`.`item_group` - FROM - `tabItem` - {left_join} - WHERE - {where_conditions} - GROUP BY - `tabItem`.`name` - ORDER BY - `tabItem`.`weightage` DESC - LIMIT - {page_length} - OFFSET - {start} - '''.format( - where_conditions=where_conditions, - start=start, - page_length=page_length, - left_join=left_join - ) - , as_dict=1) - - for r in results: - r.description = r.web_long_description or r.description - r.image = r.website_image or r.image - product_info = get_product_info_for_website(r.item_code, skip_quotation_creation=True).get('product_info') - if product_info: - r.formatted_price = product_info['price'].get('formatted_price') if product_info['price'] else None - - return results - - -def get_conditions(filter_list, and_or='and'): - from frappe.model.db_query import DatabaseQuery - - if not filter_list: - return '' - - conditions = [] - DatabaseQuery('Item').build_filter_conditions(filter_list, conditions, ignore_permissions=True) - join_by = ' {0} '.format(and_or) - - return '(' + join_by.join(conditions) + ')' - -# utilities - -def get_item_attributes(item_code): - attributes = frappe.db.get_all('Item Variant Attribute', - fields=['attribute'], - filters={ - 'parenttype': 'Item', - 'parent': item_code - }, - order_by='idx asc' - ) - - optional_attributes = ItemVariantsCacheManager(item_code).get_optional_attributes() - - for a in attributes: - if a.attribute in optional_attributes: - a.optional = True - - return attributes - -def get_html_for_items(items): - html = [] - for item in items: - html.append(frappe.render_template('erpnext/www/all-products/item_row.html', { - 'item': item - })) - return html - -def get_product_settings(): - doc = frappe.get_cached_doc('Products Settings') - doc.products_per_page = doc.products_per_page or 20 - return doc diff --git a/erpnext/portal/utils.py b/erpnext/portal/utils.py index d6d44694203..84c862b052a 100644 --- a/erpnext/portal/utils.py +++ b/erpnext/portal/utils.py @@ -1,9 +1,14 @@ from __future__ import unicode_literals + import frappe -from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings -from erpnext.shopping_cart.cart import get_debtors_account from frappe.utils.nestedset import get_root_of +from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + get_shopping_cart_settings, +) +from erpnext.e_commerce.shopping_cart.cart import get_debtors_account + + def set_default_role(doc, method): '''Set customer, supplier, student, guardian based on email''' if frappe.flags.setting_role or frappe.flags.in_migrate: diff --git a/erpnext/projects/doctype/activity_cost/activity_cost.py b/erpnext/projects/doctype/activity_cost/activity_cost.py index 99226ea581c..e210324862b 100644 --- a/erpnext/projects/doctype/activity_cost/activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/activity_cost.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class DuplicationError(frappe.ValidationError): pass class ActivityCost(Document): diff --git a/erpnext/projects/doctype/activity_cost/test_activity_cost.py b/erpnext/projects/doctype/activity_cost/test_activity_cost.py index 5f35f299b36..c031f3cedab 100644 --- a/erpnext/projects/doctype/activity_cost/test_activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/test_activity_cost.py @@ -3,11 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + from erpnext.projects.doctype.activity_cost.activity_cost import DuplicationError + class TestActivityCost(unittest.TestCase): def test_duplication(self): frappe.db.sql("delete from `tabActivity Cost`") diff --git a/erpnext/projects/doctype/activity_type/activity_type.py b/erpnext/projects/doctype/activity_type/activity_type.py index 50e18ef4de9..4c94fe45650 100644 --- a/erpnext/projects/doctype/activity_type/activity_type.py +++ b/erpnext/projects/doctype/activity_type/activity_type.py @@ -2,7 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class ActivityType(Document): pass diff --git a/erpnext/projects/doctype/activity_type/test_activity_type.py b/erpnext/projects/doctype/activity_type/test_activity_type.py index dcb01018de0..02619af7abd 100644 --- a/erpnext/projects/doctype/activity_type/test_activity_type.py +++ b/erpnext/projects/doctype/activity_type/test_activity_type.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Activity Type') diff --git a/erpnext/projects/doctype/dependent_task/dependent_task.py b/erpnext/projects/doctype/dependent_task/dependent_task.py index 90a96ac1b7c..3f62cef7056 100644 --- a/erpnext/projects/doctype/dependent_task/dependent_task.py +++ b/erpnext/projects/doctype/dependent_task/dependent_task.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class DependentTask(Document): pass diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index c8fbe0bf7be..59488e60123 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -2,18 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe import _ -from six import iteritems from email_reply_parser import EmailReplyParser -from frappe.utils import (flt, getdate, get_url, now, - nowtime, get_time, today, get_datetime, add_days) -from erpnext.controllers.queries import get_filters_cond +from frappe import _ from frappe.desk.reportview import get_match_cond +from frappe.model.document import Document +from frappe.utils import add_days, flt, get_datetime, get_time, get_url, nowtime, today + +from erpnext.controllers.queries import get_filters_cond +from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_users_email from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday -from frappe.model.document import Document -from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list + class Project(Document): def get_feed(self): diff --git a/erpnext/projects/doctype/project/project_dashboard.py b/erpnext/projects/doctype/project/project_dashboard.py index 39cf016d61f..64fbbf5ebab 100644 --- a/erpnext/projects/doctype/project/project_dashboard.py +++ b/erpnext/projects/doctype/project/project_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py index 70139c6da84..ebc132626ca 100644 --- a/erpnext/projects/doctype/project/test_project.py +++ b/erpnext/projects/doctype/project/test_project.py @@ -2,9 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals +import unittest -import frappe, unittest -from frappe.utils import getdate, nowdate, add_days +import frappe +from frappe.utils import add_days, getdate, nowdate from erpnext.projects.doctype.project_template.test_project_template import make_project_template from erpnext.projects.doctype.task.test_task import create_task diff --git a/erpnext/projects/doctype/project_template/project_template.py b/erpnext/projects/doctype/project_template/project_template.py index 2426fd2af89..493ce5b07cb 100644 --- a/erpnext/projects/doctype/project_template/project_template.py +++ b/erpnext/projects/doctype/project_template/project_template.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document from frappe.utils import get_link_to_form + class ProjectTemplate(Document): def validate(self): diff --git a/erpnext/projects/doctype/project_template/project_template_dashboard.py b/erpnext/projects/doctype/project_template/project_template_dashboard.py index 67f74f54f06..8eeaa8d6bd8 100644 --- a/erpnext/projects/doctype/project_template/project_template_dashboard.py +++ b/erpnext/projects/doctype/project_template/project_template_dashboard.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals + def get_data(): return { 'fieldname': 'project_template', diff --git a/erpnext/projects/doctype/project_template/test_project_template.py b/erpnext/projects/doctype/project_template/test_project_template.py index d546fd09a30..f71984f3a41 100644 --- a/erpnext/projects/doctype/project_template/test_project_template.py +++ b/erpnext/projects/doctype/project_template/test_project_template.py @@ -3,10 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.projects.doctype.task.test_task import create_task + class TestProjectTemplate(unittest.TestCase): pass diff --git a/erpnext/projects/doctype/project_template_task/project_template_task.py b/erpnext/projects/doctype/project_template_task/project_template_task.py index 57bc4f1835e..e0861419886 100644 --- a/erpnext/projects/doctype/project_template_task/project_template_task.py +++ b/erpnext/projects/doctype/project_template_task/project_template_task.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ProjectTemplateTask(Document): pass diff --git a/erpnext/projects/doctype/project_type/project_type.py b/erpnext/projects/doctype/project_type/project_type.py index 36137ca0186..1089483cb3f 100644 --- a/erpnext/projects/doctype/project_type/project_type.py +++ b/erpnext/projects/doctype/project_type/project_type.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.model.document import Document + import frappe from frappe import _ +from frappe.model.document import Document + class ProjectType(Document): def on_trash(self): diff --git a/erpnext/projects/doctype/project_type/test_project_type.py b/erpnext/projects/doctype/project_type/test_project_type.py index ee23390f53f..a79020f14ff 100644 --- a/erpnext/projects/doctype/project_type/test_project_type.py +++ b/erpnext/projects/doctype/project_type/test_project_type.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestProjectType(unittest.TestCase): pass diff --git a/erpnext/projects/doctype/project_update/project_update.py b/erpnext/projects/doctype/project_update/project_update.py index 2e1ec746ed6..147e591f8fd 100644 --- a/erpnext/projects/doctype/project_update/project_update.py +++ b/erpnext/projects/doctype/project_update/project_update.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class ProjectUpdate(Document): pass diff --git a/erpnext/projects/doctype/project_update/test_project_update.py b/erpnext/projects/doctype/project_update/test_project_update.py index 2edd2f85a31..15966039799 100644 --- a/erpnext/projects/doctype/project_update/test_project_update.py +++ b/erpnext/projects/doctype/project_update/test_project_update.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestProjectUpdate(unittest.TestCase): pass diff --git a/erpnext/projects/doctype/project_user/project_user.py b/erpnext/projects/doctype/project_user/project_user.py index 3198f3b0893..7abe9459f24 100644 --- a/erpnext/projects/doctype/project_user/project_user.py +++ b/erpnext/projects/doctype/project_user/project_user.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProjectUser(Document): pass diff --git a/erpnext/projects/doctype/projects_settings/projects_settings.py b/erpnext/projects/doctype/projects_settings/projects_settings.py index 9dcac14f9ad..88bb247a3c6 100644 --- a/erpnext/projects/doctype/projects_settings/projects_settings.py +++ b/erpnext/projects/doctype/projects_settings/projects_settings.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProjectsSettings(Document): pass diff --git a/erpnext/projects/doctype/projects_settings/test_projects_settings.py b/erpnext/projects/doctype/projects_settings/test_projects_settings.py index d671da73b77..326624686da 100644 --- a/erpnext/projects/doctype/projects_settings/test_projects_settings.py +++ b/erpnext/projects/doctype/projects_settings/test_projects_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestProjectsSettings(unittest.TestCase): pass diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 39a6024e2cc..e0f32811645 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -9,7 +9,7 @@ import frappe from frappe import _, throw from frappe.desk.form.assign_to import clear, close_all_assignments from frappe.model.mapper import get_mapped_doc -from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate, today, flt +from frappe.utils import add_days, cstr, date_diff, flt, get_link_to_form, getdate, today from frappe.utils.nestedset import NestedSet diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 0fad5e88074..41a9c168dfa 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -1,12 +1,15 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import unittest -from frappe.utils import getdate, nowdate, add_days + +import frappe +from frappe.utils import add_days, getdate, nowdate from erpnext.projects.doctype.task.task import CircularReferenceError + class TestTask(unittest.TestCase): def test_circular_reference(self): task1 = create_task("_Test Task 1", add_days(nowdate(), -15), add_days(nowdate(), -10)) diff --git a/erpnext/projects/doctype/task_depends_on/task_depends_on.py b/erpnext/projects/doctype/task_depends_on/task_depends_on.py index 723a0fc339b..ddb67ee30cb 100644 --- a/erpnext/projects/doctype/task_depends_on/task_depends_on.py +++ b/erpnext/projects/doctype/task_depends_on/task_depends_on.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TaskDependsOn(Document): pass diff --git a/erpnext/projects/doctype/task_type/task_type.py b/erpnext/projects/doctype/task_type/task_type.py index 9c0b5325c64..5aacf8a2395 100644 --- a/erpnext/projects/doctype/task_type/task_type.py +++ b/erpnext/projects/doctype/task_type/task_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TaskType(Document): pass diff --git a/erpnext/projects/doctype/task_type/test_task_type.py b/erpnext/projects/doctype/task_type/test_task_type.py index 1db6e27ed74..7690c3775af 100644 --- a/erpnext/projects/doctype/task_type/test_task_type.py +++ b/erpnext/projects/doctype/task_type/test_task_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestTaskType(unittest.TestCase): pass diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 2b0c3abdd77..6b32c66dfe5 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -3,21 +3,28 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest import datetime -from frappe.utils.make_random import get_random -from frappe.utils import now_datetime, nowdate, add_days, add_months -from erpnext.projects.doctype.timesheet.timesheet import OverlapError -from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice +import unittest + +import frappe +from frappe.utils import add_months, now_datetime, nowdate + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.payroll.doctype.salary_structure.test_salary_structure \ - import make_salary_structure, create_salary_structure_assignment -from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( - make_earning_salary_component, - make_deduction_salary_component -) from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + make_deduction_salary_component, + make_earning_salary_component, +) +from erpnext.payroll.doctype.salary_structure.test_salary_structure import ( + create_salary_structure_assignment, + make_salary_structure, +) +from erpnext.projects.doctype.timesheet.timesheet import ( + OverlapError, + make_salary_slip, + make_sales_invoice, +) + class TestTimesheet(unittest.TestCase): @classmethod diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 3a3d9e2c2a5..9155f45184f 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -3,19 +3,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import _ import json -from datetime import timedelta -from erpnext.controllers.queries import get_match_cond -from frappe.utils import flt, time_diff_in_hours, get_datetime, getdate, cint, date_diff, add_to_date + +import frappe +from frappe import _ from frappe.model.document import Document -from erpnext.manufacturing.doctype.workstation.workstation import (check_if_within_operating_hours, - WorkstationHolidayError) -from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations -from erpnext.setup.utils import get_exchange_rate +from frappe.utils import flt, getdate, time_diff_in_hours + +from erpnext.controllers.queries import get_match_cond from erpnext.hr.utils import validate_active_employee +from erpnext.setup.utils import get_exchange_rate + class OverlapError(frappe.ValidationError): pass class OverWorkLoggedError(frappe.ValidationError): pass diff --git a/erpnext/projects/doctype/timesheet/timesheet_dashboard.py b/erpnext/projects/doctype/timesheet/timesheet_dashboard.py index 088d98c4d5f..3ef1d92dcdb 100644 --- a/erpnext/projects/doctype/timesheet/timesheet_dashboard.py +++ b/erpnext/projects/doctype/timesheet/timesheet_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'time_sheet', diff --git a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py index 7da94b77772..4fd233ebb21 100644 --- a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py +++ b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class TimesheetDetail(Document): pass diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py index a22ed7b8338..dec2824fcc0 100644 --- a/erpnext/projects/report/billing_summary.py +++ b/erpnext/projects/report/billing_summary.py @@ -3,9 +3,11 @@ from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import time_diff_in_hours, flt +from frappe.utils import flt, time_diff_in_hours + def get_columns(): return [ diff --git a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py index 3dcae5b1b53..3a33b4b1a7e 100644 --- a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py +++ b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.desk.reportview import build_match_conditions + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py index cdabe6487ea..301639015c3 100644 --- a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py +++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.utils import date_diff, nowdate + def execute(filters=None): columns, data = [], [] data = get_data(filters) diff --git a/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py index 78291b2d781..88c77c88b43 100644 --- a/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py +++ b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py @@ -1,10 +1,14 @@ from __future__ import unicode_literals + import unittest + import frappe -from frappe.utils import nowdate, add_days, add_months +from frappe.utils import add_days, add_months, nowdate + from erpnext.projects.doctype.task.test_task import create_task from erpnext.projects.report.delayed_tasks_summary.delayed_tasks_summary import execute + class TestDelayedTasksSummary(unittest.TestCase): @classmethod def setUp(self): diff --git a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py index 17c92c234d5..30bd9f0182f 100644 --- a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py +++ b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import _ + from erpnext.projects.report.billing_summary import get_columns, get_data + def execute(filters=None): filters = frappe._dict(filters or {}) columns = get_columns() diff --git a/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/employee_hours_utilization_based_on_timesheet.py b/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/employee_hours_utilization_based_on_timesheet.py index 4d22f462463..d59a2ac52a6 100644 --- a/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/employee_hours_utilization_based_on_timesheet.py +++ b/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/employee_hours_utilization_based_on_timesheet.py @@ -2,11 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt, getdate from six import iteritems + def execute(filters=None): return EmployeeHoursReport(filters).run() diff --git a/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/test_employee_util.py b/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/test_employee_util.py index 969fc556e8d..f456c84a588 100644 --- a/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/test_employee_util.py +++ b/erpnext/projects/report/employee_hours_utilization_based_on_timesheet/test_employee_util.py @@ -1,11 +1,16 @@ from __future__ import unicode_literals -import unittest -import frappe +import unittest + +import frappe from frappe.utils.make_random import get_random -from erpnext.projects.report.employee_hours_utilization_based_on_timesheet.employee_hours_utilization_based_on_timesheet import execute + from erpnext.hr.doctype.employee.test_employee import make_employee from erpnext.projects.doctype.project.test_project import make_project +from erpnext.projects.report.employee_hours_utilization_based_on_timesheet.employee_hours_utilization_based_on_timesheet import ( + execute, +) + class TestEmployeeUtilization(unittest.TestCase): @classmethod diff --git a/erpnext/projects/report/project_billing_summary/project_billing_summary.py b/erpnext/projects/report/project_billing_summary/project_billing_summary.py index 17c92c234d5..30bd9f0182f 100644 --- a/erpnext/projects/report/project_billing_summary/project_billing_summary.py +++ b/erpnext/projects/report/project_billing_summary/project_billing_summary.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import _ + from erpnext.projects.report.billing_summary import get_columns, get_data + def execute(filters=None): filters = frappe._dict(filters or {}) columns = get_columns() diff --git a/erpnext/projects/report/project_profitability/project_profitability.py b/erpnext/projects/report/project_profitability/project_profitability.py index 0a52f7bf904..13e02c89355 100644 --- a/erpnext/projects/report/project_profitability/project_profitability.py +++ b/erpnext/projects/report/project_profitability/project_profitability.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + def execute(filters=None): columns, data = [], [] data = get_data(filters) diff --git a/erpnext/projects/report/project_profitability/test_project_profitability.py b/erpnext/projects/report/project_profitability/test_project_profitability.py index 180926fe258..8cf169b38f4 100644 --- a/erpnext/projects/report/project_profitability/test_project_profitability.py +++ b/erpnext/projects/report/project_profitability/test_project_profitability.py @@ -1,12 +1,19 @@ from __future__ import unicode_literals + import unittest + import frappe -from frappe.utils import getdate, nowdate, add_days +from frappe.utils import add_days, getdate, nowdate + from erpnext.hr.doctype.employee.test_employee import make_employee -from erpnext.projects.doctype.timesheet.test_timesheet import make_salary_structure_for_timesheet, make_timesheet +from erpnext.projects.doctype.timesheet.test_timesheet import ( + make_salary_structure_for_timesheet, + make_timesheet, +) from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice from erpnext.projects.report.project_profitability.project_profitability import execute + class TestProjectProfitability(unittest.TestCase): def setUp(self): diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py index 98dd617f9b3..dbb4e848578 100644 --- a/erpnext/projects/report/project_summary/project_summary.py +++ b/erpnext/projects/report/project_summary/project_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns() data = [] diff --git a/erpnext/projects/report/project_wise_stock_tracking/project_wise_stock_tracking.py b/erpnext/projects/report/project_wise_stock_tracking/project_wise_stock_tracking.py index c13d7cf3344..5d2b7dbc5be 100644 --- a/erpnext/projects/report/project_wise_stock_tracking/project_wise_stock_tracking.py +++ b/erpnext/projects/report/project_wise_stock_tracking/project_wise_stock_tracking.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ + def execute(filters=None): columns = get_columns() proj_details = get_project_details() diff --git a/erpnext/projects/utils.py b/erpnext/projects/utils.py index c39f908e43e..69264704b4b 100644 --- a/erpnext/projects/utils.py +++ b/erpnext/projects/utils.py @@ -4,8 +4,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe + @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def query_task(doctype, txt, searchfield, start, page_len, filters): diff --git a/erpnext/projects/web_form/tasks/tasks.py b/erpnext/projects/web_form/tasks/tasks.py index e5a94048be1..aed794261ea 100644 --- a/erpnext/projects/web_form/tasks/tasks.py +++ b/erpnext/projects/web_form/tasks/tasks.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe + def get_context(context): if frappe.form_dict.project: context.parents = [{'title': frappe.form_dict.project, 'route': '/projects?project='+ frappe.form_dict.project}] diff --git a/erpnext/public/build.json b/erpnext/public/build.json index 6b70dab8037..4cf9bb11eff 100644 --- a/erpnext/public/build.json +++ b/erpnext/public/build.json @@ -11,7 +11,8 @@ ], "js/erpnext-web.min.js": [ "public/js/website_utils.js", - "public/js/shopping_cart.js" + "public/js/shopping_cart.js", + "public/js/wishlist.js" ], "css/erpnext-web.css": [ "public/scss/website.scss", @@ -70,6 +71,12 @@ "public/js/bank_reconciliation_tool/number_card.js", "public/js/bank_reconciliation_tool/dialog_manager.js" ], + "js/e-commerce.min.js": [ + "e_commerce/product_ui/views.js", + "e_commerce/product_ui/grid.js", + "e_commerce/product_ui/list.js", + "e_commerce/product_ui/search.js" + ], "js/hierarchy-chart.min.js": [ "public/js/hierarchy_chart/hierarchy_chart_desktop.js", "public/js/hierarchy_chart/hierarchy_chart_mobile.js" diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index eb709e5e85e..a0f56a2d07f 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -21,6 +21,6 @@ $.extend(frappe.breadcrumbs.module_map, { 'Geo': 'Settings', 'Portal': 'Website', 'Utilities': 'Settings', - 'Shopping Cart': 'Website', + 'E-commerce': 'Website', 'Contacts': 'CRM' }); diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 16613b365f1..6c1d5f9898e 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -487,6 +487,10 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ var me = this; var item = frappe.get_doc(cdt, cdn); var update_stock = 0, show_batch_dialog = 0; + + item.weight_per_unit = 0; + item.weight_uom = ''; + if(['Sales Invoice'].includes(this.frm.doc.doctype)) { update_stock = cint(me.frm.doc.update_stock); show_batch_dialog = update_stock; @@ -846,21 +850,25 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ if (frappe.meta.get_docfield(this.frm.doctype, "shipping_address") && in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) { - erpnext.utils.get_shipping_address(this.frm, function(){ + erpnext.utils.get_shipping_address(this.frm, function() { set_party_account(set_pricing); }); // Get default company billing address in Purchase Invoice, Order and Receipt - frappe.call({ - 'method': 'frappe.contacts.doctype.address.address.get_default_address', - 'args': { - 'doctype': 'Company', - 'name': this.frm.doc.company - }, - 'callback': function(r) { - me.frm.set_value('billing_address', r.message); - } - }); + if (this.frm.doc.company && frappe.meta.get_docfield(this.frm.doctype, "billing_address")) { + frappe.call({ + method: "erpnext.setup.doctype.company.company.get_default_company_address", + args: {name: this.frm.doc.company, existing_address: this.frm.doc.billing_address || ""}, + debounce: 2000, + callback: function(r) { + if (r.message) { + me.frm.set_value("billing_address", r.message); + } else { + me.frm.set_value("company_address", ""); + } + } + }); + } } else { set_party_account(set_pricing); diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js index 23ec2fdb849..62867327537 100644 --- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js +++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js @@ -67,8 +67,6 @@ erpnext.HierarchyChart = class { } show() { - frappe.breadcrumbs.add('HR'); - this.setup_actions(); if ($(`[data-fieldname="company"]`).length) return; let me = this; @@ -83,8 +81,9 @@ erpnext.HierarchyChart = class { reqd: 1, change: () => { me.company = undefined; + $('#hierarchy-chart-wrapper').remove(); - if (company.get_value() && me.company != company.get_value()) { + if (company.get_value()) { me.company = company.get_value(); // svg for connectors @@ -92,6 +91,8 @@ erpnext.HierarchyChart = class { me.setup_hierarchy(); me.render_root_nodes(); me.all_nodes_expanded = false; + } else { + frappe.throw(__('Please select a company first.')); } } }); @@ -172,11 +173,11 @@ erpnext.HierarchyChart = class { `); this.page.main - .find('#hierarchy-chart-wrapper') + .find('#hierarchy-chart') + .empty() .append(this.$hierarchy); this.nodes = {}; - this.all_nodes_expanded = false; } make_svg_markers() { @@ -203,6 +204,8 @@ erpnext.HierarchyChart = class { +
+
`); } @@ -219,7 +222,10 @@ erpnext.HierarchyChart = class { let expand_node = undefined; let node = undefined; - $.each(r.message, (i, data) => { + $.each(r.message, (_i, data) => { + if ($(`#${data.id}`).length) + return; + node = new me.Node({ id: data.id, parent: $('
  • ').appendTo(me.$hierarchy.find('.node-children')), @@ -290,7 +296,7 @@ erpnext.HierarchyChart = class { () => frappe.dom.freeze(), () => this.setup_hierarchy(), () => this.render_root_nodes(true), - () => this.get_all_nodes(node.id, node.name), + () => this.get_all_nodes(), (data_list) => this.render_children_of_all_nodes(data_list), () => frappe.dom.unfreeze() ]); @@ -341,15 +347,13 @@ erpnext.HierarchyChart = class { node.expanded = true; } - get_all_nodes(node_id, node_name) { + get_all_nodes() { return new Promise(resolve => { frappe.call({ method: 'erpnext.utilities.hierarchy_chart.get_all_nodes', args: { method: this.method, - company: this.company, - parent: node_id, - parent_name: node_name + company: this.company }, callback: (r) => { resolve(r.message); diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js index b1b78c05174..b1a88795572 100644 --- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js +++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js @@ -59,8 +59,6 @@ erpnext.HierarchyChartMobile = class { } show() { - frappe.breadcrumbs.add('HR'); - let me = this; if ($(`[data-fieldname="company"]`).length) return; diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js index 6a923ae4234..d99063b0454 100644 --- a/erpnext/public/js/shopping_cart.js +++ b/erpnext/public/js/shopping_cart.js @@ -2,8 +2,8 @@ // License: GNU General Public License v3. See license.txt // shopping cart -frappe.provide("erpnext.shopping_cart"); -var shopping_cart = erpnext.shopping_cart; +frappe.provide("erpnext.e_commerce.shopping_cart"); +var shopping_cart = erpnext.e_commerce.shopping_cart; var getParams = function (url) { var params = []; @@ -51,10 +51,10 @@ frappe.ready(function() { if (referral_sales_partner) { $(".txtreferral_sales_partner").val(referral_sales_partner); } + // update login shopping_cart.show_shoppingcart_dropdown(); shopping_cart.set_cart_count(); - shopping_cart.bind_dropdown_cart_buttons(); shopping_cart.show_cart_navbar(); }); @@ -63,7 +63,7 @@ $.extend(shopping_cart, { $(".shopping-cart").on('shown.bs.dropdown', function() { if (!$('.shopping-cart-menu .cart-container').length) { return frappe.call({ - method: 'erpnext.shopping_cart.cart.get_shopping_cart_menu', + method: 'erpnext.e_commerce.shopping_cart.cart.get_shopping_cart_menu', callback: function(r) { if (r.message) { $('.shopping-cart-menu').html(r.message); @@ -75,15 +75,18 @@ $.extend(shopping_cart, { }, update_cart: function(opts) { - if(frappe.session.user==="Guest") { - if(localStorage) { + if (frappe.session.user==="Guest") { + if (localStorage) { localStorage.setItem("last_visited", window.location.pathname); } - window.location.href = "/login"; + frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => { + window.location.href = res.message || "/login"; + }); } else { + shopping_cart.freeze(); return frappe.call({ type: "POST", - method: "erpnext.shopping_cart.cart.update_cart", + method: "erpnext.e_commerce.shopping_cart.cart.update_cart", args: { item_code: opts.item_code, qty: opts.qty, @@ -92,10 +95,8 @@ $.extend(shopping_cart, { }, btn: opts.btn, callback: function(r) { - shopping_cart.set_cart_count(); - if (r.message.shopping_cart_menu) { - $('.shopping-cart-menu').html(r.message.shopping_cart_menu); - } + shopping_cart.unfreeze(); + shopping_cart.set_cart_count(true); if(opts.callback) opts.callback(r); } @@ -103,7 +104,7 @@ $.extend(shopping_cart, { } }, - set_cart_count: function() { + set_cart_count: function(animate=false) { var cart_count = frappe.get_cookie("cart_count"); if(frappe.session.user==="Guest") { cart_count = 0; @@ -121,7 +122,7 @@ $.extend(shopping_cart, { $(".cart-items").html('Cart is Empty'); $(".cart-tax-items").hide(); $(".btn-place-order").hide(); - $(".cart-addresses").hide(); + $(".cart-payment-addresses").hide(); } else { $cart.css("display", "inline"); @@ -129,13 +130,19 @@ $.extend(shopping_cart, { if(cart_count) { $badge.html(cart_count); + + if (animate) { + $cart.addClass("cart-animate"); + setTimeout(() => { + $cart.removeClass("cart-animate"); + }, 500); + } } else { $badge.remove(); } }, shopping_cart_update: function({item_code, qty, cart_dropdown, additional_notes}) { - frappe.freeze(); shopping_cart.update_cart({ item_code, qty, @@ -143,7 +150,6 @@ $.extend(shopping_cart, { with_items: 1, btn: this, callback: function(r) { - frappe.unfreeze(); if(!r.exc) { $(".cart-items").html(r.message.items); $(".cart-tax-items").html(r.message.taxes); @@ -155,35 +161,71 @@ $.extend(shopping_cart, { }); }, - - bind_dropdown_cart_buttons: function () { - $(".cart-icon").on('click', '.number-spinner button', function () { - var btn = $(this), - input = btn.closest('.number-spinner').find('input'), - oldValue = input.val().trim(), - newVal = 0; - - if (btn.attr('data-dir') == 'up') { - newVal = parseInt(oldValue) + 1; - } else { - if (oldValue > 1) { - newVal = parseInt(oldValue) - 1; - } - } - input.val(newVal); - var item_code = input.attr("data-item-code"); - shopping_cart.shopping_cart_update({item_code, qty: newVal, cart_dropdown: true}); - return false; - }); - - }, - show_cart_navbar: function () { frappe.call({ - method: "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.is_cart_enabled", + method: "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.is_cart_enabled", callback: function(r) { $(".shopping-cart").toggleClass('hidden', r.message ? false : true); } }); + }, + + toggle_button_class(button, remove, add) { + button.removeClass(remove); + button.addClass(add); + }, + + bind_add_to_cart_action() { + $('.page_content').on('click', '.btn-add-to-cart-list', (e) => { + const $btn = $(e.currentTarget); + $btn.prop('disabled', true); + + if (frappe.session.user==="Guest") { + if (localStorage) { + localStorage.setItem("last_visited", window.location.pathname); + } + frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => { + window.location.href = res.message || "/login"; + }); + return; + } + + $btn.addClass('hidden'); + $btn.closest('.cart-action-container').addClass('d-flex'); + $btn.parent().find('.go-to-cart').removeClass('hidden'); + $btn.parent().find('.go-to-cart-grid').removeClass('hidden'); + $btn.parent().find('.cart-indicator').removeClass('hidden'); + + const item_code = $btn.data('item-code'); + erpnext.e_commerce.shopping_cart.update_cart({ + item_code, + qty: 1 + }); + + }); + }, + + freeze() { + if (window.location.pathname !== "/cart") return; + + if (!$('#freeze').length) { + let freeze = $('') + .appendTo("body"); + + setTimeout(function() { + freeze.addClass("show"); + }, 1); + } else { + $("#freeze").addClass("show"); + } + }, + + unfreeze() { + if ($('#freeze').length) { + let freeze = $('#freeze').removeClass("show"); + setTimeout(function() { + freeze.remove(); + }, 1); + } } }); diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 85c1693657f..fdf4e35e6d4 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -86,9 +86,9 @@ $.extend(erpnext, { proceed_save_with_reminders_frequency_change: () => { frappe.ui.hide_open_dialog(); - + frappe.call({ - method: 'erpnext.hr.doctype.hr_settings.hr_settings.set_proceed_with_frequency_change', + method: 'erpnext.hr.doctype.hr_settings.hr_settings.set_proceed_with_frequency_change', callback: () => { cur_frm.save(); } diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 4d432e3d5cc..a492b32a9f6 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -289,8 +289,8 @@ erpnext.utils.get_shipping_address = function(frm, callback) { company: frm.doc.company, address: frm.doc.shipping_address }, - callback: function(r){ - if (r.message){ + callback: function(r) { + if (r.message) { frm.set_value("shipping_address", r.message[0]) //Address title or name frm.set_value("shipping_address_display", r.message[1]) //Address to be displayed on the page } diff --git a/erpnext/public/js/wishlist.js b/erpnext/public/js/wishlist.js new file mode 100644 index 00000000000..f6599e9f6d1 --- /dev/null +++ b/erpnext/public/js/wishlist.js @@ -0,0 +1,204 @@ +frappe.provide("erpnext.e_commerce.wishlist"); +var wishlist = erpnext.e_commerce.wishlist; + +frappe.provide("erpnext.e_commerce.shopping_cart"); +var shopping_cart = erpnext.e_commerce.shopping_cart; + +$.extend(wishlist, { + set_wishlist_count: function(animate=false) { + // set badge count for wishlist icon + var wish_count = frappe.get_cookie("wish_count"); + if (frappe.session.user==="Guest") { + wish_count = 0; + } + + if (wish_count) { + $(".wishlist").toggleClass('hidden', false); + } + + var $wishlist = $('.wishlist-icon'); + var $badge = $wishlist.find("#wish-count"); + + if (parseInt(wish_count) === 0 || wish_count === undefined) { + $wishlist.css("display", "none"); + } else { + $wishlist.css("display", "inline"); + } + if (wish_count) { + $badge.html(wish_count); + if (animate) { + $wishlist.addClass('cart-animate'); + setTimeout(() => { + $wishlist.removeClass('cart-animate'); + }, 500); + } + } else { + $badge.remove(); + } + }, + + bind_move_to_cart_action: function() { + // move item to cart from wishlist + $('.page_content').on("click", ".btn-add-to-cart", (e) => { + const $move_to_cart_btn = $(e.currentTarget); + let item_code = $move_to_cart_btn.data("item-code"); + + shopping_cart.shopping_cart_update({ + item_code, + qty: 1, + cart_dropdown: true + }); + + let success_action = function() { + const $card_wrapper = $move_to_cart_btn.closest(".wishlist-card"); + $card_wrapper.addClass("wish-removed"); + }; + let args = { item_code: item_code }; + this.add_remove_from_wishlist("remove", args, success_action, null, true); + }); + }, + + bind_remove_action: function() { + // remove item from wishlist + let me = this; + + $('.page_content').on("click", ".remove-wish", (e) => { + const $remove_wish_btn = $(e.currentTarget); + let item_code = $remove_wish_btn.data("item-code"); + + let success_action = function() { + const $card_wrapper = $remove_wish_btn.closest(".wishlist-card"); + $card_wrapper.addClass("wish-removed"); + if (frappe.get_cookie("wish_count") == 0) { + $(".page_content").empty(); + me.render_empty_state(); + } + }; + let args = { item_code: item_code }; + this.add_remove_from_wishlist("remove", args, success_action); + }); + }, + + bind_wishlist_action() { + // 'wish'('like') or 'unwish' item in product listing + $('.page_content').on('click', '.like-action, .like-action-list', (e) => { + const $btn = $(e.currentTarget); + this.wishlist_action($btn); + }); + }, + + wishlist_action(btn) { + const $wish_icon = btn.find('.wish-icon'); + let me = this; + + if (frappe.session.user==="Guest") { + if (localStorage) { + localStorage.setItem("last_visited", window.location.pathname); + } + this.redirect_guest(); + return; + } + + let success_action = function() { + erpnext.e_commerce.wishlist.set_wishlist_count(true); + }; + + if ($wish_icon.hasClass('wished')) { + // un-wish item + btn.removeClass("like-animate"); + btn.addClass("like-action-wished"); + this.toggle_button_class($wish_icon, 'wished', 'not-wished'); + + let args = { item_code: btn.data('item-code') }; + let failure_action = function() { + me.toggle_button_class($wish_icon, 'not-wished', 'wished'); + }; + this.add_remove_from_wishlist("remove", args, success_action, failure_action); + } else { + // wish item + btn.addClass("like-animate"); + btn.addClass("like-action-wished"); + this.toggle_button_class($wish_icon, 'not-wished', 'wished'); + + let args = {item_code: btn.data('item-code')}; + let failure_action = function() { + me.toggle_button_class($wish_icon, 'wished', 'not-wished'); + }; + this.add_remove_from_wishlist("add", args, success_action, failure_action); + } + }, + + toggle_button_class(button, remove, add) { + button.removeClass(remove); + button.addClass(add); + }, + + add_remove_from_wishlist(action, args, success_action, failure_action, async=false) { + /* AJAX call to add or remove Item from Wishlist + action: "add" or "remove" + args: args for method (item_code, price, formatted_price), + success_action: method to execute on successs, + failure_action: method to execute on failure, + async: make call asynchronously (true/false). */ + if (frappe.session.user==="Guest") { + if (localStorage) { + localStorage.setItem("last_visited", window.location.pathname); + } + this.redirect_guest(); + } else { + let method = "erpnext.e_commerce.doctype.wishlist.wishlist.add_to_wishlist"; + if (action === "remove") { + method = "erpnext.e_commerce.doctype.wishlist.wishlist.remove_from_wishlist"; + } + + frappe.call({ + async: async, + type: "POST", + method: method, + args: args, + callback: function (r) { + if (r.exc) { + if (failure_action && (typeof failure_action === 'function')) { + failure_action(); + } + frappe.msgprint({ + message: __("Sorry, something went wrong. Please refresh."), + indicator: "red", title: __("Note") + }); + } else if (success_action && (typeof success_action === 'function')) { + success_action(); + } + } + }); + } + }, + + redirect_guest() { + frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => { + window.location.href = res.message || "/login"; + }); + }, + + render_empty_state() { + $(".page_content").append(` +
    +
    + Empty Cart +
    +
    ${ __('Wishlist is empty !') }

    +
    + `); + } + +}); + +frappe.ready(function() { + if (window.location.pathname !== "/wishlist") { + $(".wishlist").toggleClass('hidden', true); + wishlist.set_wishlist_count(); + } else { + wishlist.bind_move_to_cart_action(); + wishlist.bind_remove_action(); + } + +}); \ No newline at end of file diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 490a7c4af73..fbb26a8008c 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -1,16 +1,17 @@ @import "frappe/public/scss/common/mixins"; -body.product-page { - background: var(--gray-50); +:root { + --green-info: #38A160; + --product-bg-color: white; + --body-bg-color: var(--gray-50); } +body.product-page { + background: var(--body-bg-color); +} .item-breadcrumbs { .breadcrumb-container { - ol.breadcrumb { - background-color: var(--gray-50) !important; - } - a { color: var(--gray-900); } @@ -61,9 +62,21 @@ body.product-page { } } +.no-image-item { + height: 340px; + width: 340px; + background: var(--gray-100); + border-radius: var(--border-radius); + font-size: 2rem; + color: var(--gray-500); + display: flex; + align-items: center; + justify-content: center; +} + .item-card-group-section { .card { - height: 360px; + height: 100%; align-items: center; justify-content: center; @@ -73,6 +86,19 @@ body.product-page { } } + .card:hover, .card:focus-within { + .btn-add-to-cart-list { + visibility: visible; + } + .like-action { + visibility: visible; + } + .btn-explore-variants { + visibility: visible; + } + } + + .card-img-container { height: 210px; width: 100%; @@ -86,14 +112,28 @@ body.product-page { .no-image { @include flex(flex, center, center, null); - height: 200px; - margin: 0 auto; - margin-top: var(--margin-xl); + height: 220px; + background: var(--gray-100); + width: 100%; + border-radius: var(--border-radius) var(--border-radius) 0 0; + font-size: 2rem; + color: var(--gray-500); + } + + .no-image-list { + @include flex(flex, center, center, null); + height: 150px; background: var(--gray-100); - width: 80%; border-radius: var(--border-radius); font-size: 2rem; color: var(--gray-500); + margin-top: 15px; + margin-bottom: 15px; + } + + .card-body-flex { + display: flex; + flex-direction: column; } .product-title { @@ -126,10 +166,70 @@ body.product-page { font-weight: 600; color: var(--text-color); margin: var(--margin-sm) 0; + margin-bottom: auto !important; + + .striked-price { + font-weight: 500; + font-size: 15px; + color: var(--gray-500); + } + } + + .product-info-green { + color: var(--green-info); + font-weight: 600; } .item-card { padding: var(--padding-sm); + min-width: 300px; + } + + .wishlist-card { + padding: var(--padding-sm); + min-width: 260px; + .card-body-flex { + display: flex; + flex-direction: column; + } + } +} + +#products-list-area, #products-grid-area { + padding: 0 5px; +} + +.list-row { + background-color: white; + padding-bottom: 1rem; + padding-top: 1.5rem !important; + border-radius: 8px; + border-bottom: 1px solid var(--gray-50); + + &:hover, &:focus-within { + box-shadow: 0px 16px 60px rgba(0, 0, 0, 0.08), 0px 8px 30px -20px rgba(0, 0, 0, 0.04); + transition: box-shadow 400ms; + + .btn-add-to-cart-list { + visibility: visible; + } + .like-action-list { + visibility: visible; + } + .btn-explore-variants { + visibility: visible; + } + } + + .product-code { + padding-top: 0 !important; + } + + .btn-explore-variants { + min-width: 135px; + max-height: 30px; + float: right; + padding: 0.25rem 1rem; } } @@ -174,28 +274,76 @@ body.product-page { } } +.product-filter { + width: 14px !important; + height: 14px !important; +} + +.discount-filter { + &:before { + width: 14px !important; + height: 14px !important; + } +} + +.list-image { + border: none !important; + overflow: hidden; + max-height: 200px; + background-color: white; +} + .product-container { @include card($padding: var(--padding-md)); - min-height: 70vh; + background-color: var(--product-bg-color) !important; + min-height: fit-content; .product-details { - max-width: 40%; - margin-left: -30px; + max-width: 50%; .btn-add-to-cart { - font-size: var(--text-base); + font-size: 14px; + } + } + + &.item-main { + .product-image { + width: 100%; + } + } + + .expand { + max-width: 100% !important; // expand in absence of slideshow + } + + @media (max-width: 789px) { + .product-details { + max-width: 90% !important; + + .btn-add-to-cart { + font-size: 14px; + } + } + } + + .btn-add-to-wishlist { + svg use { + stroke: #F47A7A; + } + } + + .btn-view-in-wishlist { + svg use { + fill: #F47A7A; + stroke: none; } } .product-title { - font-size: 24px; + font-size: 16px; font-weight: 600; color: var(--text-color); - } - - .product-code { - color: var(--text-muted); - font-size: 13px; + padding: 0 !important; } .product-description { @@ -232,7 +380,7 @@ body.product-page { max-height: 430px; } - overflow: scroll; + overflow: auto; } .item-slideshow-image { @@ -251,29 +399,114 @@ body.product-page { .item-cart { .product-price { - font-size: 20px; + font-size: 22px; color: var(--text-color); font-weight: 600; .formatted-price { color: var(--text-muted); - font-size: var(--text-base); + font-size: 14px; } } .no-stock { font-size: var(--text-base); } + + .offers-heading { + font-size: 16px !important; + color: var(--text-color); + .tag-icon { + --icon-stroke: var(--gray-500); + } + } + + .w-30-40 { + width: 30%; + + @media (max-width: 992px) { + width: 40%; + } + } + } + + .tab-content { + font-size: 14px; + } +} + +// Item Recommendations +.recommended-item-section { + padding-right: 0; + + .recommendation-header { + font-size: 16px; + font-weight: 500 + } + + .recommendation-container { + padding: .5rem; + min-height: 0px; + + .r-item-image { + width: 40%; + + .r-product-image { + padding: 2px 15px; + } + + .no-image-r-item { + display: flex; justify-content: center; + background-color: var(--gray-200); + align-items: center; + color: var(--gray-400); + margin-top: .15rem; + border-radius: 6px; + height: 100%; + font-size: 24px; + } + } + + .r-item-info { + font-size: 14px; + padding-right: 0; + width: 60%; + + a { + color: var(--gray-800); + font-weight: 400; + } + + .item-price { + font-size: 15px; + font-weight: 600; + color: var(--text-color); + } + + .striked-item-price { + font-weight: 500; + color: var(--gray-500); + } + } + } +} + +.product-code { + padding: .5rem 0; + color: var(--text-muted); + font-size: 14px; + .product-item-group { + padding-right: .25rem; + border-right: solid 1px var(--text-muted); + } + + .product-item-code { + padding-left: .5rem; } } .item-configurator-dialog { - .modal-header { - padding: var(--padding-md) var(--padding-xl); - } - .modal-body { - padding: 0 var(--padding-xl); padding-bottom: var(--padding-xl); .status-area { @@ -313,20 +546,74 @@ body.product-page { } } -.cart-icon { - .cart-badge { - position: relative; - top: -10px; - left: -12px; - background: var(--red-600); - width: 16px; - align-items: center; - height: 16px; - font-size: 10px; - border-radius: 50%; +.sub-category-container { + padding-bottom: .5rem; + margin-bottom: 1.25rem; + border-bottom: 1px solid var(--table-border-color); + + .heading { + color: var(--gray-500); } } +.scroll-categories { + white-space: nowrap; + overflow-x: auto; + + .category-pill { + margin: 0px 4px; + display: inline-block; + padding: 6px 12px; + background-color: #ecf5fe; + width: fit-content; + font-size: 14px; + border-radius: 18px; + color: var(--blue-500); + } +} + + +.shopping-badge { + position: relative; + top: -10px; + left: -12px; + background: var(--red-600); + width: 16px; + align-items: center; + height: 16px; + font-size: 10px; + border-radius: 50%; +} + + +.cart-animate { + animation: wiggle 0.5s linear; +} +@keyframes wiggle { + 8%, + 41% { + transform: translateX(-10px); + } + 25%, + 58% { + transform: translate(10px); + } + 75% { + transform: translate(-5px); + } + 92% { + transform: translate(5px); + } + 0%, + 100% { + transform: translate(0); + } +} + +.total-discount { + font-size: 14px; + color: var(--primary-color) !important; +} #page-cart { .shopping-cart-header { @@ -340,6 +627,7 @@ body.product-page { display: flex; flex-direction: column; justify-content: space-between; + height: fit-content; } .cart-items-header { @@ -347,6 +635,10 @@ body.product-page { } .cart-table { + tr { + margin-bottom: 1rem; + } + th, tr, td { border-color: var(--border-color); border-width: 1px; @@ -364,71 +656,200 @@ body.product-page { color: var(--text-color); } + .cart-item-image { + width: 20%; + min-width: 100px; + img { + max-height: 112px; + } + + .no-image-cart-item { + max-height: 112px; + display: flex; justify-content: center; + background-color: var(--gray-200); + align-items: center; + color: var(--gray-400); + margin-top: .15rem; + border-radius: 6px; + height: 100%; + font-size: 24px; + } + } + .cart-items { .item-title { - font-size: var(--text-base); + width: 80%; + font-size: 14px; font-weight: 500; color: var(--text-color); } .item-subtitle { color: var(--text-muted); - font-size: var(--text-md); + font-size: 13px; } .item-subtotal { - font-size: var(--text-base); + font-size: 14px; font-weight: 500; } + .sm-item-subtotal { + font-size: 14px; + font-weight: 500; + display: none; + + @media (max-width: 992px) { + display: unset !important; + } + } + .item-rate { - font-size: var(--text-md); + font-size: 13px; color: var(--text-muted); } - textarea { - width: 40%; + .free-tag { + padding: 4px 8px; + border-radius: 4px; + background-color: var(--dark-green-50); } + + textarea { + width: 80%; + height: 60px; + font-size: 14px; + } + } .cart-tax-items { .item-grand-total { font-size: 16px; - font-weight: 600; + font-weight: 700; color: var(--text-color); } } + + .column-sm-view { + @media (max-width: 992px) { + display: none !important; + } + } + + .item-column { + width: 50%; + @media (max-width: 992px) { + width: 70%; + } + } + + .remove-cart-item { + border-radius: 6px; + border: 1px solid var(--gray-100); + width: 28px; + height: 28px; + font-weight: 300; + color: var(--gray-700); + background-color: var(--gray-100); + float: right; + cursor: pointer; + margin-top: .25rem; + justify-content: center; + } + + .remove-cart-item-logo { + margin-top: 2px; + margin-left: 2.2px; + fill: var(--gray-700) !important; + } } - .cart-addresses { + .cart-payment-addresses { hr { border-color: var(--border-color); } } + .payment-summary { + h6 { + padding-bottom: 1rem; + border-bottom: solid 1px var(--gray-200); + } + + table { + font-size: 14px; + td { + padding: 0; + padding-top: 0.35rem !important; + border: none !important; + } + + &.grand-total { + border-top: solid 1px var(--gray-200); + } + } + + .bill-label { + color: var(--gray-600); + } + + .bill-content { + font-weight: 500; + &.net-total { + font-size: 16px; + font-weight: 600; + } + } + + .btn-coupon-code { + font-size: 14px; + border: dashed 1px var(--gray-400); + box-shadow: none; + } + } + .number-spinner { width: 75%; + min-width: 105px; .cart-btn { border: none; background: var(--gray-100); box-shadow: none; + width: 24px; height: 28px; align-items: center; + justify-content: center; display: flex; + font-size: 20px; + font-weight: 300; + color: var(--gray-700); } .cart-qty { height: 28px; - font-size: var(--text-md); + font-size: 13px; + &:disabled { + background: var(--gray-100); + opacity: 0.65; + } } } .place-order-container { .btn-place-order { - width: 62%; + float: right; } } } + + .t-and-c-container { + padding: 1.5rem; + } + + .t-and-c-terms { + font-size: 14px; + } } .cart-empty.frappe-card { @@ -444,7 +865,7 @@ body.product-page { .address-card { .card-title { - font-size: var(--text-base); + font-size: 14px; font-weight: 500; } @@ -453,27 +874,37 @@ body.product-page { } .card-text { - font-size: var(--text-md); + font-size: 13px; color: var(--gray-700); } .card-link { - font-size: var(--text-md); + font-size: 13px; svg use { - stroke: var(--blue-500); + stroke: var(--primary-color); } } .btn-change-address { - color: var(--blue-500); + border: 1px solid var(--primary-color); + color: var(--primary-color); + box-shadow: none; } } +.address-header { + margin-top: .15rem;padding: 0; +} + +.btn-new-address { + float: right; + font-size: 15px !important; + color: var(--primary-color) !important; +} + .btn-new-address:hover, .btn-change-address:hover { - box-shadow: none; - color: var(--blue-500) !important; - border: 1px solid var(--blue-500); + color: var(--primary-color) !important; } .modal .address-card { @@ -483,3 +914,451 @@ body.product-page { border: 1px solid var(--dark-border-color); } } + +.cart-indicator { + position: absolute; + text-align: center; + width: 22px; + height: 22px; + left: calc(100% - 40px); + top: 22px; + + border-radius: 66px; + box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1); + background: white; + color: var(--primary-color); + font-size: 14px; + + &.list-indicator { + position: unset; + margin-left: auto; + } +} + + +.like-action { + visibility: hidden; + text-align: center; + position: absolute; + cursor: pointer; + width: 28px; + height: 28px; + left: 20px; + top: 20px; + + /* White */ + background: white; + box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1); + border-radius: 66px; + + &.like-action-wished { + visibility: visible !important; + } + + @media (max-width: 992px) { + visibility: visible !important; + } +} + +.like-action-list { + visibility: hidden; + text-align: center; + position: absolute; + cursor: pointer; + width: 28px; + height: 28px; + left: 20px; + top: 0; + + /* White */ + background: white; + box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1); + border-radius: 66px; + + &.like-action-wished { + visibility: visible !important; + } + + @media (max-width: 992px) { + visibility: visible !important; + } +} + +.like-action-item-fp { + visibility: visible !important; + position: unset; + float: right; +} + +.like-animate { + animation: expand cubic-bezier(0.04, 0.4, 0.5, 0.95) 1.6s forwards 1; +} + +@keyframes expand { + 30% { + transform: scale(1.3); + } + 50% { + transform: scale(0.8); + } + 70% { + transform: scale(1.1); + } + 100% { + transform: scale(1); + } + } + +.not-wished { + cursor: pointer; + stroke: #F47A7A !important; + + &:hover { + fill: #F47A7A; + } +} + +.wished { + stroke: none; + fill: #F47A7A !important; +} + +.list-row-checkbox { + &:before { + display: none; + } + + &:checked:before { + display: block; + z-index: 1; + } +} + +#pay-for-order { + padding: .5rem 1rem; // Pay button in SO +} + +.btn-explore-variants { + visibility: hidden; + box-shadow: none; + margin: var(--margin-sm) 0; + width: 90px; + max-height: 50px; // to avoid resizing on window resize + flex: none; + transition: 0.3s ease; + + color: white; + background-color: var(--orange-500); + border: 1px solid var(--orange-500); + font-size: 13px; + + &:hover { + color: white; + } +} + +.btn-add-to-cart-list{ + visibility: hidden; + box-shadow: none; + margin: var(--margin-sm) 0; + // margin-top: auto !important; + max-height: 50px; // to avoid resizing on window resize + flex: none; + transition: 0.3s ease; + + font-size: 13px; + + &:hover { + color: white; + } + + @media (max-width: 992px) { + visibility: visible !important; + } +} + +.go-to-cart-grid { + max-height: 30px; + margin-top: 1rem !important; +} + +.go-to-cart { + max-height: 30px; + float: right; +} + +.remove-wish { + background-color: white; + position: absolute; + cursor: pointer; + top:10px; + right: 20px; + width: 32px; + height: 32px; + + border-radius: 50%; + border: 1px solid var(--gray-100); + box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1); +} + +.wish-removed { + display: none; +} + +.item-website-specification { + font-size: .875rem; + .product-title { + font-size: 18px; + } + + .table { + width: 70%; + } + + td { + border: none !important; + } + + .spec-label { + color: var(--gray-600); + } + + .spec-content { + color: var(--gray-800); + } +} + +.reviews-full-page { + padding: 1rem 2rem; +} + +.ratings-reviews-section { + border-top: 1px solid #E2E6E9; + padding: .5rem 1rem; +} + +.reviews-header { + font-size: 20px; + font-weight: 600; + color: var(--gray-800); + display: flex; + align-items: center; + padding: 0; +} + +.btn-write-review { + float: right; + padding: .5rem 1rem; + font-size: 14px; + font-weight: 400; + border: none !important; + box-shadow: none; + + color: var(--gray-900); + background-color: var(--gray-100); + + &:hover { + box-shadow: var(--btn-shadow); + } +} + +.btn-view-more { + font-size: 14px; +} + +.rating-summary-section { + display: flex; +} + +.rating-summary-title { + margin-top: 0.15rem; + font-size: 18px; +} + +.rating-summary-numbers { + display: flex; + flex-direction: column; + align-items: center; + + border-right: solid 1px var(--gray-100); +} + +.user-review-title { + margin-top: 0.15rem; + font-size: 15px; + font-weight: 600; +} + +.rating { + --star-fill: var(--gray-300); + .star-hover { + --star-fill: var(--yellow-100); + } + .star-click { + --star-fill: var(--yellow-300); + } +} + +.ratings-pill { + background-color: var(--gray-100); + padding: .5rem 1rem; + border-radius: 66px; +} + +.review { + max-width: 80%; + line-height: 1.6; + padding-bottom: 0.5rem; + border-bottom: 1px solid #E2E6E9; +} + +.review-signature { + display: flex; + font-size: 13px; + color: var(--gray-500); + font-weight: 400; + + .reviewer { + padding-right: 8px; + color: var(--gray-600); + } +} + +.rating-progress-bar-section { + padding-bottom: 2rem; + + .rating-bar-title { + margin-left: -15px; + } + + .rating-progress-bar { + margin-bottom: 4px; + height: 7px; + margin-top: 6px; + + .progress-bar-cosmetic { + background-color: var(--gray-600); + border-radius: var(--border-radius); + } + } +} + +.offer-container { + font-size: 14px; +} + +#search-results-container { + border: 1px solid var(--gray-200); + padding: .25rem 1rem; + + .category-chip { + background-color: var(--gray-100); + border: none !important; + box-shadow: none; + } + + .recent-search { + padding: .5rem .5rem; + border-radius: var(--border-radius); + + &:hover { + background-color: var(--gray-100); + } + } +} + +#search-box { + background-color: white; + height: 100%; + padding-left: 2.5rem; + border: 1px solid var(--gray-200); +} + +.search-icon { + position: absolute; + left: 0; + top: 0; + width: 2.5rem; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 1px; +} + +#toggle-view { + float: right; + + .btn-primary { + background-color: var(--gray-600); + box-shadow: 0 0 0 0.2rem var(--gray-400); + } +} + +.placeholder-div { + height:80%; + width: -webkit-fill-available; + padding: 50px; + text-align: center; + background-color: #F9FAFA; + border-top-left-radius: calc(0.75rem - 1px); + border-top-right-radius: calc(0.75rem - 1px); +} +.placeholder { + font-size: 72px; +} + +[data-path="cart"] { + .modal-backdrop { + background-color: var(--gray-50); // lighter backdrop only on cart freeze + } +} + +.item-thumb { + height: 50px; + max-width: 80px; + min-width: 80px; + object-fit: cover; +} + +.brand-line { + color: gray; +} + +.btn-next, .btn-prev { + font-size: 14px; +} + +.alert-error { + color: #e27a84; + background-color: #fff6f7; + border-color: #f5c6cb; +} + +.font-md { + font-size: 14px !important; +} + +.in-green { + color: var(--green-info) !important; + font-weight: 500; +} + +.has-stock { + font-weight: 400 !important; +} + +.out-of-stock { + font-weight: 400; + font-size: 14px; + line-height: 20px; + color: #F47A7A; +} + +.mt-minus-2 { + margin-top: -2rem; +} + +.mt-minus-1 { + margin-top: -1rem; +} \ No newline at end of file diff --git a/erpnext/quality_management/doctype/non_conformance/non_conformance.py b/erpnext/quality_management/doctype/non_conformance/non_conformance.py index d4e8cc7a716..a4613fdaf6b 100644 --- a/erpnext/quality_management/doctype/non_conformance/non_conformance.py +++ b/erpnext/quality_management/doctype/non_conformance/non_conformance.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class NonConformance(Document): pass diff --git a/erpnext/quality_management/doctype/non_conformance/test_non_conformance.py b/erpnext/quality_management/doctype/non_conformance/test_non_conformance.py index 54f8b58cfb0..759b117f9b0 100644 --- a/erpnext/quality_management/doctype/non_conformance/test_non_conformance.py +++ b/erpnext/quality_management/doctype/non_conformance/test_non_conformance.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestNonConformance(unittest.TestCase): pass diff --git a/erpnext/quality_management/doctype/quality_action/quality_action.py b/erpnext/quality_management/doctype/quality_action/quality_action.py index 02401ba689d..646a0dfc2c8 100644 --- a/erpnext/quality_management/doctype/quality_action/quality_action.py +++ b/erpnext/quality_management/doctype/quality_action/quality_action.py @@ -3,9 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class QualityAction(Document): def validate(self): self.status = 'Open' if any([d.status=='Open' for d in self.resolutions]) else 'Completed' diff --git a/erpnext/quality_management/doctype/quality_action/test_quality_action.py b/erpnext/quality_management/doctype/quality_action/test_quality_action.py index 98d665f3910..33229d4b451 100644 --- a/erpnext/quality_management/doctype/quality_action/test_quality_action.py +++ b/erpnext/quality_management/doctype/quality_action/test_quality_action.py @@ -3,9 +3,9 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQualityAction(unittest.TestCase): # quality action has no code pass diff --git a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py index de8873feb0c..b456fb7e9a0 100644 --- a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py +++ b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityActionResolution(Document): pass diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py index d3e96cf2d94..9189c282973 100644 --- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py +++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class QualityFeedback(Document): @frappe.whitelist() def set_parameters(self): diff --git a/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py b/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py index 5a8bd5ce30c..7a87c362446 100644 --- a/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py +++ b/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + class TestQualityFeedback(unittest.TestCase): def test_quality_feedback(self): diff --git a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py index d652e8a57bb..9a21b263603 100644 --- a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py +++ b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityFeedbackParameter(Document): pass diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py index 0c6dfc07802..c6a520a3c59 100644 --- a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py +++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityFeedbackTemplate(Document): pass diff --git a/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py b/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py index afed14b6ad0..1de58aae3ed 100644 --- a/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py +++ b/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQualityFeedbackTemplate(unittest.TestCase): pass diff --git a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py index 3f3348fd7fa..44a6b014a0c 100644 --- a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py +++ b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityFeedbackTemplateParameter(Document): pass diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal.py b/erpnext/quality_management/doctype/quality_goal/quality_goal.py index 3e616b75ceb..2888401782a 100644 --- a/erpnext/quality_management/doctype/quality_goal/quality_goal.py +++ b/erpnext/quality_management/doctype/quality_goal/quality_goal.py @@ -3,10 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class QualityGoal(Document): def validate(self): pass diff --git a/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py b/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py index 0e135b50212..84240d227ea 100644 --- a/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py +++ b/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.quality_management.doctype.quality_procedure.test_quality_procedure import create_procedure + +import frappe + class TestQualityGoal(unittest.TestCase): def test_quality_goal(self): diff --git a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py index f4bd357f1b2..c9c2c6e564c 100644 --- a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py +++ b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityGoalObjective(Document): pass diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py index 9e453ebfc2e..0ac0484399e 100644 --- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py +++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class QualityMeeting(Document): pass diff --git a/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py b/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py index 6bf4c179c6b..e57256d2896 100644 --- a/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py +++ b/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py @@ -3,9 +3,9 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestQualityMeeting(unittest.TestCase): # nothing to test pass diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py index 5d77975d74c..5e4d9ff37a7 100644 --- a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py +++ b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityMeetingAgenda(Document): pass diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py b/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py index 4750cc1f7af..8744d275ed8 100644 --- a/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py +++ b/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestQualityMeetingAgenda(unittest.TestCase): pass diff --git a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py index 47b2c95bd9e..e3d061b36ca 100644 --- a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py +++ b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityMeetingMinutes(Document): pass diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py index 117db0012ba..56293c98e09 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils.nestedset import NestedSet, rebuild_tree from frappe import _ +from frappe.utils.nestedset import NestedSet + class QualityProcedure(NestedSet): nsm_parent_field = 'parent_quality_procedure' diff --git a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py index 4fa7734bc68..b064011bf6c 100644 --- a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py @@ -3,11 +3,13 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + from .quality_procedure import add_node + class TestQualityProcedure(unittest.TestCase): def test_add_node(self): try: diff --git a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py index 0d9a286052d..e281294643d 100644 --- a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py +++ b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityProcedureProcess(Document): pass diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.py b/erpnext/quality_management/doctype/quality_review/quality_review.py index 34cc890e219..b766623510a 100644 --- a/erpnext/quality_management/doctype/quality_review/quality_review.py +++ b/erpnext/quality_management/doctype/quality_review/quality_review.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class QualityReview(Document): def validate(self): # fetch targets from goal diff --git a/erpnext/quality_management/doctype/quality_review/test_quality_review.py b/erpnext/quality_management/doctype/quality_review/test_quality_review.py index 161ecd01ef1..2f28ddac45e 100644 --- a/erpnext/quality_management/doctype/quality_review/test_quality_review.py +++ b/erpnext/quality_management/doctype/quality_review/test_quality_review.py @@ -3,12 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + from ..quality_goal.test_quality_goal import get_quality_goal from .quality_review import review + class TestQualityReview(unittest.TestCase): def test_review_creation(self): quality_goal = get_quality_goal() diff --git a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py index 3092a1e9979..23b11e87e6a 100644 --- a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py +++ b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityReviewObjective(Document): pass diff --git a/erpnext/regional/__init__.py b/erpnext/regional/__init__.py index faa59129a5a..45a689efa8b 100644 --- a/erpnext/regional/__init__.py +++ b/erpnext/regional/__init__.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + from erpnext import get_region + def check_deletion_permission(doc, method): region = get_region(doc.company) if region in ["Nepal", "France"] and doc.docstatus != 0: diff --git a/erpnext/regional/address_template/setup.py b/erpnext/regional/address_template/setup.py index 1b4087d77ba..0f9a1b19f53 100644 --- a/erpnext/regional/address_template/setup.py +++ b/erpnext/regional/address_template/setup.py @@ -1,7 +1,9 @@ """Import Address Templates from ./templates directory.""" import os + import frappe + def set_up_address_templates(default_country=None): for country, html in get_address_templates(): is_default = 1 if country == default_country else 0 diff --git a/erpnext/regional/address_template/test_regional_address_template.py b/erpnext/regional/address_template/test_regional_address_template.py index 8a05ea26f45..2880d6253f9 100644 --- a/erpnext/regional/address_template/test_regional_address_template.py +++ b/erpnext/regional/address_template/test_regional_address_template.py @@ -1,9 +1,11 @@ from __future__ import unicode_literals + from unittest import TestCase import frappe -from erpnext.regional.address_template.setup import get_address_templates -from erpnext.regional.address_template.setup import update_address_template + +from erpnext.regional.address_template.setup import get_address_templates, update_address_template + def ensure_country(country): if frappe.db.exists("Country", country): diff --git a/erpnext/regional/doctype/datev_settings/datev_settings.py b/erpnext/regional/doctype/datev_settings/datev_settings.py index cff5bba58fd..0d2d9eb4b47 100644 --- a/erpnext/regional/doctype/datev_settings/datev_settings.py +++ b/erpnext/regional/doctype/datev_settings/datev_settings.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class DATEVSettings(Document): pass diff --git a/erpnext/regional/doctype/datev_settings/test_datev_settings.py b/erpnext/regional/doctype/datev_settings/test_datev_settings.py index 0271329f4d2..73412f755d7 100644 --- a/erpnext/regional/doctype/datev_settings/test_datev_settings.py +++ b/erpnext/regional/doctype/datev_settings/test_datev_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestDATEVSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py b/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py index 9150bdd9260..38fe3089412 100644 --- a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py +++ b/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EInvoiceRequestLog(Document): pass diff --git a/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py b/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py index c84e9a249bd..091cc88e454 100644 --- a/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py +++ b/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestEInvoiceRequestLog(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py b/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py index 4f6b3eca7a6..70ec2ed0679 100644 --- a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py +++ b/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py @@ -7,6 +7,7 @@ import frappe from frappe import _ from frappe.model.document import Document + class EInvoiceSettings(Document): def validate(self): if self.enable and not self.credentials: diff --git a/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py b/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py index a11ce63ee6c..10770deb0ee 100644 --- a/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py +++ b/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestEInvoiceSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py b/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py index 056c54f069d..a0fe399f110 100644 --- a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py +++ b/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EInvoiceUser(Document): pass diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py index 4791dc26753..0704de8387f 100644 --- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py +++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class GSTHSNCode(Document): pass diff --git a/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.py b/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.py index ed54f207139..1a90e6d711c 100644 --- a/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.py +++ b/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestGSTHSNCode(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/gst_settings/gst_settings.py b/erpnext/regional/doctype/gst_settings/gst_settings.py index af3d92e59a7..7b27fb6c5bc 100644 --- a/erpnext/regional/doctype/gst_settings/gst_settings.py +++ b/erpnext/regional/doctype/gst_settings/gst_settings.py @@ -3,11 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, os + +import os + +import frappe from frappe import _ -from frappe.utils import get_url, nowdate, date_diff -from frappe.model.document import Document from frappe.contacts.doctype.contact.contact import get_default_contact +from frappe.model.document import Document +from frappe.utils import date_diff, get_url, nowdate + class EmailMissing(frappe.ValidationError): pass diff --git a/erpnext/regional/doctype/gst_settings/test_gst_settings.py b/erpnext/regional/doctype/gst_settings/test_gst_settings.py index d118dee6177..836d3a88c33 100644 --- a/erpnext/regional/doctype/gst_settings/test_gst_settings.py +++ b/erpnext/regional/doctype/gst_settings/test_gst_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestGSTSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index 0ee5b097b54..d8ce3197395 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -3,15 +3,19 @@ # For license information, please see license.txt from __future__ import unicode_literals -import os + import json +import os + import frappe -from six import iteritems from frappe import _ from frappe.model.document import Document -from frappe.utils import flt, cstr +from frappe.utils import cstr, flt +from six import iteritems + from erpnext.regional.india import state_numbers + class GSTR3BReport(Document): def validate(self): self.get_data() diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index 065f80d610a..115f9b88165 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -3,13 +3,15 @@ # See license.txt from __future__ import unicode_literals -import frappe -import unittest -from frappe.utils import getdate -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.stock.doctype.item.test_item import make_item import json +import unittest + +import frappe +from frappe.utils import getdate + +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.stock.doctype.item.test_item import make_item test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"] diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py index 00300539e9a..76cb621f541 100644 --- a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py @@ -3,21 +3,21 @@ from __future__ import unicode_literals -from decimal import Decimal -import json import re -import traceback import zipfile -import frappe, erpnext + +import dateutil +import frappe +from bs4 import BeautifulSoup as bs from frappe import _ from frappe.model.document import Document -from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.utils import flt, get_datetime_str, today from frappe.utils.data import format_datetime -from bs4 import BeautifulSoup as bs -from frappe.utils import cint, flt, today, nowdate, add_days, get_files_path, get_datetime_str -import dateutil from frappe.utils.file_manager import save_file +import erpnext + + class ImportSupplierInvoice(Document): def validate(self): if not frappe.db.get_value("Stock Settings", fieldname="stock_uom"): diff --git a/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py index d1caf77fc2c..4be4c3a22f9 100644 --- a/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py +++ b/erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestImportSupplierInvoice(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py index 656c3296e58..d8553f1d913 100644 --- a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py +++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import getdate, get_link_to_form from frappe.model.document import Document +from frappe.utils import get_link_to_form, getdate + from erpnext.accounts.utils import get_fiscal_year + class LowerDeductionCertificate(Document): def validate(self): self.validate_dates() diff --git a/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py index 7e950206fcc..54443c0206a 100644 --- a/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py +++ b/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestLowerDeductionCertificate(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py b/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py index d74154bfe78..4c3e8a78e9d 100644 --- a/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py +++ b/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class SouthAfricaVATSettings(Document): pass diff --git a/erpnext/regional/doctype/south_africa_vat_settings/test_south_africa_vat_settings.py b/erpnext/regional/doctype/south_africa_vat_settings/test_south_africa_vat_settings.py index 1c36652ad6e..0f19f25f88d 100644 --- a/erpnext/regional/doctype/south_africa_vat_settings/test_south_africa_vat_settings.py +++ b/erpnext/regional/doctype/south_africa_vat_settings/test_south_africa_vat_settings.py @@ -4,5 +4,6 @@ # import frappe import unittest + class TestSouthAfricaVATSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py index 41a0f1193bc..64b2ec5646c 100644 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py +++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document -from frappe.utils import getdate, flt, get_link_to_form -from erpnext.accounts.utils import get_fiscal_year from frappe.contacts.doctype.address.address import get_company_address +from frappe.model.document import Document +from frappe.utils import flt, get_link_to_form, getdate + +from erpnext.accounts.utils import get_fiscal_year + class TaxExemption80GCertificate(Document): def validate(self): diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py index 41b42036687..74e9ced3941 100644 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py +++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py @@ -3,14 +3,21 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe from frappe.utils import getdate + from erpnext.accounts.utils import get_fiscal_year -from erpnext.non_profit.doctype.donation.test_donation import create_donor, create_mode_of_payment, create_donor_type from erpnext.non_profit.doctype.donation.donation import create_donation -from erpnext.non_profit.doctype.membership.test_membership import setup_membership, make_membership +from erpnext.non_profit.doctype.donation.test_donation import ( + create_donor, + create_donor_type, + create_mode_of_payment, +) from erpnext.non_profit.doctype.member.member import create_member +from erpnext.non_profit.doctype.membership.test_membership import make_membership, setup_membership + class TestTaxExemption80GCertificate(unittest.TestCase): def setUp(self): diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py index bdad798d980..76d8912b004 100644 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py +++ b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TaxExemption80GCertificateDetail(Document): pass diff --git a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py index 80d6b3a5f1f..a1b27d7e3d3 100644 --- a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py +++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class UAEVATAccount(Document): pass diff --git a/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py index b88439f9b85..cec30e61cef 100644 --- a/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py +++ b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestUAEVATSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py index 20dc604510b..1bf37dd499d 100644 --- a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py +++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class UAEVATSettings(Document): pass diff --git a/erpnext/regional/france/setup.py b/erpnext/regional/france/setup.py index db6419e9462..3e3a9f6e56a 100644 --- a/erpnext/regional/france/setup.py +++ b/erpnext/regional/france/setup.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def setup(company=None, patch=True): make_custom_fields() add_custom_roles_for_reports() diff --git a/erpnext/regional/france/utils.py b/erpnext/regional/france/utils.py index 424615dbbc0..63c5a1f583b 100644 --- a/erpnext/regional/france/utils.py +++ b/erpnext/regional/france/utils.py @@ -2,7 +2,7 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + # don't remove this function it is used in tests def test_method(): diff --git a/erpnext/regional/germany/setup.py b/erpnext/regional/germany/setup.py index c1fa6e492d1..35d14135ba5 100644 --- a/erpnext/regional/germany/setup.py +++ b/erpnext/regional/germany/setup.py @@ -1,4 +1,4 @@ -import os + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields diff --git a/erpnext/regional/germany/utils/datev/datev_csv.py b/erpnext/regional/germany/utils/datev/datev_csv.py index c5c2bc41f4d..9d1fabbada7 100644 --- a/erpnext/regional/germany/utils/datev/datev_csv.py +++ b/erpnext/regional/germany/utils/datev/datev_csv.py @@ -4,12 +4,12 @@ from __future__ import unicode_literals import datetime import zipfile from csv import QUOTE_NONNUMERIC -from six import BytesIO -import six import frappe import pandas as pd from frappe import _ +from six import BytesIO + from .datev_constants import DataCategory diff --git a/erpnext/regional/india/__init__.py b/erpnext/regional/india/__init__.py index faeb36fc693..5c4d30881d1 100644 --- a/erpnext/regional/india/__init__.py +++ b/erpnext/regional/india/__init__.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from six import iteritems states = [ diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index fe4c172e237..19699243f9e 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -3,24 +3,39 @@ # For license information, please see license.txt from __future__ import unicode_literals + +import base64 +import io +import json import os import re -import jwt import sys -import json -import base64 -import frappe -import six import traceback -import io + +import frappe +import jwt +import six from frappe import _, bold -from pyqrcode import create as qrcreate -from frappe.utils.background_jobs import enqueue -from frappe.utils.scheduler import is_scheduler_inactive from frappe.core.page.background_jobs.background_jobs import get_info -from frappe.integrations.utils import make_post_request, make_get_request +from frappe.integrations.utils import make_get_request, make_post_request +from frappe.utils.background_jobs import enqueue +from frappe.utils.data import ( + add_to_date, + cint, + cstr, + flt, + format_date, + get_link_to_form, + getdate, + now_datetime, + time_diff_in_hours, + time_diff_in_seconds, +) +from frappe.utils.scheduler import is_scheduler_inactive +from pyqrcode import create as qrcreate + from erpnext.regional.india.utils import get_gst_accounts, get_place_of_supply -from frappe.utils.data import cstr, cint, format_date, flt, time_diff_in_seconds, now_datetime, add_to_date, get_link_to_form, getdate, time_diff_in_hours + @frappe.whitelist() def validate_eligibility(doc): @@ -483,7 +498,7 @@ def log_error(data=None): "Data:", data, seperator, "Exception:", err_tb ]) - frappe.log_error(title=_('E Invoice Request Failed'), message=message) + return frappe.log_error(title=_('E Invoice Request Failed'), message=message) def santize_einvoice_fields(einvoice): int_fields = ["Pin","Distance","CrDay"] diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 2d6b9133900..888dcfc7bd7 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -3,14 +3,19 @@ from __future__ import unicode_literals -import frappe, os, json +import json +import os + +import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.permissions import add_permission, update_permission_property -from erpnext.regional.india import states -from erpnext.accounts.utils import get_fiscal_year, FiscalYearError from frappe.utils import today +from erpnext.accounts.utils import FiscalYearError, get_fiscal_year +from erpnext.regional.india import states + + def setup(company=None, patch=True): # Company independent fixtures should be called only once at the first company setup if frappe.db.count('Company', {'country': 'India'}) <=1: @@ -492,6 +497,26 @@ def make_custom_fields(update=True): hidden=1, insert_after='einvoice_status', no_copy=1, print_hide=1, read_only=1) ] + payment_entry_fields = [ + dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', insert_after='deductions', + print_hide=1, collapsible=1), + dict(fieldname='company_address', label='Company Address', fieldtype='Link', insert_after='gst_section', + print_hide=1, options='Address'), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', insert_after='company_address', + fetch_from='company_address.gstin', print_hide=1, read_only=1), + dict(fieldname='place_of_supply', label='Place of Supply', + fieldtype='Data', insert_after='company_gstin', + print_hide=1, read_only=1), + dict(fieldname='gst_column_break', fieldtype='Column Break', + insert_after='place_of_supply'), + dict(fieldname='customer_address', label='Customer Address', fieldtype='Link', insert_after='gst_column_break', + print_hide=1, options='Address', depends_on = 'eval:doc.party_type == "Customer"'), + dict(fieldname='customer_gstin', label='Customer GSTIN', + fieldtype='Data', insert_after='customer_address', + fetch_from='customer_address.gstin', print_hide=1, read_only=1) + ] + custom_fields = { 'Address': [ dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data', @@ -506,6 +531,7 @@ def make_custom_fields(update=True): 'Purchase Receipt': purchase_invoice_gst_fields, 'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields + si_einvoice_fields, 'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields + delivery_note_gst_category, + 'Payment Entry': payment_entry_fields, 'Journal Entry': journal_entry_fields, 'Sales Order': sales_invoice_gst_fields, 'Tax Category': inter_state_gst_field, diff --git a/erpnext/regional/india/test_utils.py b/erpnext/regional/india/test_utils.py index a16f56c704a..2c77c8d8aa8 100644 --- a/erpnext/regional/india/test_utils.py +++ b/erpnext/regional/india/test_utils.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals import unittest -import frappe from unittest.mock import patch + +import frappe + from erpnext.regional.india.utils import validate_document_name diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index ce5aa10902e..0feb2dbe536 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -1,19 +1,19 @@ from __future__ import unicode_literals -import frappe, re, json + +import json +import re + +import frappe from frappe import _ -import erpnext -from frappe.utils import cstr, flt, cint, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words, getdate -from erpnext.regional.india import states, state_numbers -from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount +from frappe.model.utils import get_fetch_values +from frappe.utils import cint, cstr, date_diff, flt, getdate, nowdate +from six import string_types + from erpnext.controllers.accounts_controller import get_taxes_and_charges +from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount from erpnext.hr.utils import get_salary_assignment from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip -from erpnext.regional.india import number_state_mapping -from six import string_types -from erpnext.accounts.general_ledger import make_gl_entries -from erpnext.accounts.utils import get_account_currency -from frappe.model.utils import get_fetch_values - +from erpnext.regional.india import number_state_mapping, state_numbers, states GST_INVOICE_NUMBER_FORMAT = re.compile(r"^[a-zA-Z0-9\-/]+$") #alphanumeric and - / GSTIN_FORMAT = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$") @@ -767,6 +767,15 @@ def update_itc_availed_fields(doc, method): if tax.account_head in gst_accounts.get('cess_account', []): doc.itc_cess_amount += flt(tax.base_tax_amount_after_discount_amount) +def update_place_of_supply(doc, method): + country = frappe.get_cached_value('Company', doc.company, 'country') + if country != 'India': + return + + address = frappe.db.get_value("Address", doc.get('customer_address'), ["gst_state", "gst_state_number"], as_dict=1) + if address and address.gst_state and address.gst_state_number: + doc.place_of_supply = cstr(address.gst_state_number) + "-" + cstr(address.gst_state) + @frappe.whitelist() def get_regional_round_off_accounts(company, account_list): country = frappe.get_cached_value('Company', company, 'country') diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 7db2f6b0f8d..291906af9cd 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -8,7 +8,14 @@ import frappe from frappe import _ from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.permissions import add_permission, update_permission_property -from erpnext.regional.italy import fiscal_regimes, tax_exemption_reasons, mode_of_payment_codes, vat_collectability_options + +from erpnext.regional.italy import ( + fiscal_regimes, + mode_of_payment_codes, + tax_exemption_reasons, + vat_collectability_options, +) + def setup(company=None, patch=True): make_custom_fields() diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index ba1aeafc3e9..d6c7f1dbfa9 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -2,13 +2,14 @@ from __future__ import unicode_literals import io import json + import frappe -from frappe.utils import flt, cstr -from erpnext.controllers.taxes_and_totals import get_itemised_tax from frappe import _ -from frappe.core.doctype.file.file import remove_file +from frappe.utils import cstr, flt +from frappe.utils.file_manager import remove_file from six import string_types -from frappe.desk.form.load import get_attachments + +from erpnext.controllers.taxes_and_totals import get_itemised_tax from erpnext.regional.italy import state_codes diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 8f077e3de0b..dcabe368aa5 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -10,13 +10,18 @@ Provide a report and downloadable CSV according to the German DATEV format. from __future__ import unicode_literals import json + import frappe +from frappe import _ from six import string_types -from frappe import _ from erpnext.accounts.utils import get_fiscal_year -from erpnext.regional.germany.utils.datev.datev_csv import zip_and_download, get_datev_csv -from erpnext.regional.germany.utils.datev.datev_constants import Transactions, DebtorsCreditors, AccountNames +from erpnext.regional.germany.utils.datev.datev_constants import ( + AccountNames, + DebtorsCreditors, + Transactions, +) +from erpnext.regional.germany.utils.datev.datev_csv import get_datev_csv, zip_and_download COLUMNS = [ { @@ -200,7 +205,7 @@ def get_transactions(filters, as_dict=1): def run(params_method, filters): extra_fields, extra_joins, extra_filters = params_method(filters) return run_query(filters, extra_fields, extra_joins, extra_filters, as_dict=as_dict) - + def sort_by(row): # "Belegdatum" is in the fifth column when list format is used return row["Belegdatum" if as_dict else 5] @@ -361,7 +366,7 @@ def run_query(filters, extra_fields, extra_joins, extra_filters, as_dict=1): FROM `tabGL Entry` gl /* Kontonummer */ - LEFT JOIN `tabAccount` acc + LEFT JOIN `tabAccount` acc ON gl.account = acc.name LEFT JOIN `tabParty Account` par diff --git a/erpnext/regional/report/datev/test_datev.py b/erpnext/regional/report/datev/test_datev.py index 59b878e94a5..b53889366f1 100644 --- a/erpnext/regional/report/datev/test_datev.py +++ b/erpnext/regional/report/datev/test_datev.py @@ -2,21 +2,27 @@ from __future__ import unicode_literals import zipfile -import frappe -from six import BytesIO from unittest import TestCase -from frappe.utils import today, now_datetime, cstr + +import frappe +from frappe.utils import cstr, now_datetime, today +from six import BytesIO + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - -from erpnext.regional.report.datev.datev import validate -from erpnext.regional.report.datev.datev import get_transactions -from erpnext.regional.report.datev.datev import get_customers -from erpnext.regional.report.datev.datev import get_suppliers -from erpnext.regional.report.datev.datev import get_account_names -from erpnext.regional.report.datev.datev import download_datev_csv - +from erpnext.regional.germany.utils.datev.datev_constants import ( + AccountNames, + DebtorsCreditors, + Transactions, +) from erpnext.regional.germany.utils.datev.datev_csv import get_datev_csv, get_header -from erpnext.regional.germany.utils.datev.datev_constants import Transactions, DebtorsCreditors, AccountNames +from erpnext.regional.report.datev.datev import ( + download_datev_csv, + get_account_names, + get_customers, + get_suppliers, + get_transactions, +) + def make_company(company_name, abbr): if not frappe.db.exists("Company", company_name): diff --git a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py b/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py index 66ffceae539..a068a380776 100644 --- a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py +++ b/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): validate_filters(filters) diff --git a/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.py b/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.py index 376ba3ee471..f4ce7a77ad9 100644 --- a/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.py +++ b/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.py @@ -2,7 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from erpnext.accounts.report.sales_register.sales_register import _execute + def execute(filters=None): return _execute(filters) diff --git a/erpnext/regional/report/eway_bill/eway_bill.py b/erpnext/regional/report/eway_bill/eway_bill.py index 4f777fcf7e3..c78084f7dff 100644 --- a/erpnext/regional/report/eway_bill/eway_bill.py +++ b/erpnext/regional/report/eway_bill/eway_bill.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json import re + +import frappe from frappe import _ from frappe.utils import nowdate + def execute(filters=None): if not filters: filters.setdefault('posting_date', [nowdate(), nowdate()]) columns, data = [], [] @@ -41,7 +44,7 @@ def get_data(filters): } # Regular expression set to remove all the special characters - special_characters = "[$%^*()+\\[\]{};':\"\\|<>.?]" + special_characters = r"[$%^*()+\\[\]{};':\"\\|<>.?]" for row in data: set_defaults(row) diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py index e903c9f00a4..9567916cd2a 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py @@ -2,11 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import format_datetime -from frappe import _ + import re +import frappe +from frappe import _ +from frappe.utils import format_datetime + + def execute(filters=None): account_details = {} for acc in frappe.db.sql("""select name, is_group from tabAccount""", as_dict=1): @@ -116,7 +119,7 @@ def get_result_as_list(data, filters): if d.get("voucher_no").startswith("{0}-".format(JournalCode)) or d.get("voucher_no").startswith("{0}/".format(JournalCode)): EcritureNum = re.split("-|/", d.get("voucher_no"))[1] else: - EcritureNum = re.search("{0}(\d+)".format(JournalCode), d.get("voucher_no"), re.IGNORECASE).group(1) + EcritureNum = re.search(r"{0}(\d+)".format(JournalCode), d.get("voucher_no"), re.IGNORECASE).group(1) EcritureDate = format_datetime(d.get("GlPostDate"), "yyyyMMdd") diff --git a/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py b/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py index b5948f9952d..092f72adf15 100644 --- a/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py +++ b/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py @@ -3,7 +3,10 @@ from __future__ import unicode_literals -from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import _execute +from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import ( + _execute, +) + def execute(filters=None): return _execute(filters, additional_table_columns=[ diff --git a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py index e13f509f475..44f623bfae9 100644 --- a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py +++ b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import _execute + def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Customer GSTIN', fieldname="customer_gstin", width=120), diff --git a/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py b/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py index 12e9676b4ba..e9724441b17 100644 --- a/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py +++ b/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from erpnext.accounts.report.purchase_register.purchase_register import _execute + def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Supplier GSTIN', fieldname="supplier_gstin", width=120), diff --git a/erpnext/regional/report/gst_sales_register/gst_sales_register.py b/erpnext/regional/report/gst_sales_register/gst_sales_register.py index 075bd483cf0..6975af35854 100644 --- a/erpnext/regional/report/gst_sales_register/gst_sales_register.py +++ b/erpnext/regional/report/gst_sales_register/gst_sales_register.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from erpnext.accounts.report.sales_register.sales_register import _execute + def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Customer GSTIN', fieldname="customer_gstin", width=120), diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js index 444f5dbb8ca..ef2bdb67980 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.js +++ b/erpnext/regional/report/gstr_1/gstr_1.js @@ -51,7 +51,9 @@ frappe.query_reports["GSTR-1"] = { { "value": "B2C Large", "label": __("B2C(Large) Invoices - 5A, 5B") }, { "value": "B2C Small", "label": __("B2C(Small) Invoices - 7") }, { "value": "CDNR-REG", "label": __("Credit/Debit Notes (Registered) - 9B") }, - { "value": "EXPORT", "label": __("Export Invoice - 6A") } + { "value": "CDNR-UNREG", "label": __("Credit/Debit Notes (Unregistered) - 9B") }, + { "value": "EXPORT", "label": __("Export Invoice - 6A") }, + { "value": "Advances", "label": __("Tax Liability (Advances Received) - 11A(1), 11A(2)") } ], "default": "B2B" } diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 9d4f9206f50..ca0defa648a 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -2,14 +2,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe import _ -from frappe.utils import flt, formatdate, now_datetime, getdate + +import json from datetime import date + +import frappe +from frappe import _ +from frappe.utils import flt, formatdate, getdate from six import iteritems -from erpnext.regional.doctype.gstr_3b_report.gstr_3b_report import get_period + from erpnext.regional.india.utils import get_gst_accounts + def execute(filters=None): return Gstr1Report(filters).run() @@ -50,26 +54,45 @@ class Gstr1Report(object): self.get_invoice_items() self.get_items_based_on_tax_rate() self.invoice_fields = [d["fieldname"] for d in self.invoice_columns] - self.get_data() + + self.get_data() return self.columns, self.data def get_data(self): if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): self.get_b2c_data() - else: + elif self.filters.get("type_of_business") == "Advances": + self.get_advance_data() + elif self.invoices: for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) for rate, items in items_based_on_rate.items(): row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) - if self.filters.get("type_of_business") == "CDNR-REG": + if self.filters.get("type_of_business") in ("CDNR-REG", "CDNR-UNREG"): row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") row.append("C" if invoice_details.is_return else "D") if taxable_value: self.data.append(row) + def get_advance_data(self): + advances_data = {} + advances = self.get_advance_entries() + for entry in advances: + # only consider IGST and SGST so as to avoid duplication of taxable amount + if entry.account_head in self.gst_accounts.igst_account or \ + entry.account_head in self.gst_accounts.sgst_account: + advances_data.setdefault((entry.place_of_supply, entry.rate), [0.0, 0.0]) + advances_data[(entry.place_of_supply, entry.rate)][0] += (entry.amount * 100 / entry.rate) + elif entry.account_head in self.gst_accounts.cess_account: + advances_data[(entry.place_of_supply, entry.rate)][1] += entry.amount + + for key, value in advances_data.items(): + row= [key[0], key[1], value[0], value[1]] + self.data.append(row) + def get_b2c_data(self): b2cs_output = {} @@ -106,7 +129,7 @@ class Gstr1Report(object): def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items): row = [] for fieldname in self.invoice_fields: - if self.filters.get("type_of_business") == "CDNR-REG" and fieldname == "invoice_value": + if self.filters.get("type_of_business") in ("CDNR-REG", "CDNR-UNREG") and fieldname == "invoice_value": row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) elif fieldname == "invoice_value": row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) @@ -167,6 +190,16 @@ class Gstr1Report(object): for d in invoice_data: self.invoices.setdefault(d.invoice_number, d) + def get_advance_entries(self): + return frappe.db.sql(""" + SELECT SUM(a.base_tax_amount) as amount, a.account_head, a.rate, p.place_of_supply + FROM `tabPayment Entry` p, `tabAdvance Taxes and Charges` a + WHERE p.docstatus = 1 + AND p.name = a.parent + AND posting_date between %s and %s + GROUP BY a.account_head, p.place_of_supply, a.rate + """, (self.filters.get('from_date'), self.filters.get('to_date')), as_dict=1) + def get_conditions(self): conditions = "" @@ -198,6 +231,12 @@ class Gstr1Report(object): elif self.filters.get("type_of_business") == "CDNR-REG": conditions += """ AND (is_return = 1 OR is_debit_note = 1) AND IFNULL(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ')""" + elif self.filters.get("type_of_business") == "CDNR-UNREG": + b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') + conditions += """ AND ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') + AND ABS(grand_total) > {0} AND (is_return = 1 OR is_debit_note = 1) + AND IFNULL(gst_category, '') in ('Unregistered', 'Overseas')""".format(flt(b2c_limit)) + elif self.filters.get("type_of_business") == "EXPORT": conditions += """ AND is_return !=1 and gst_category = 'Overseas' """ @@ -503,6 +542,84 @@ class Gstr1Report(object): "width": 80 } ] + elif self.filters.get("type_of_business") == "CDNR-UNREG": + self.invoice_columns = [ + { + "fieldname": "customer_name", + "label": "Receiver Name", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "return_against", + "label": "Issued Against", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Note Date", + "fieldtype": "Date", + "width": 120 + }, + { + "fieldname": "invoice_number", + "label": "Note Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":120 + }, + { + "fieldname": "export_type", + "label": "Export Type", + "fieldtype": "Data", + "hidden": 1 + }, + { + "fieldname": "reason_for_issuing_document", + "label": "Reason For Issuing document", + "fieldtype": "Data", + "width": 140 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "gst_category", + "label": "GST Category", + "fieldtype": "Data" + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "pre_gst", + "label": "PRE GST", + "fieldtype": "Data", + "width": 80 + }, + { + "fieldname": "document_type", + "label": "Document Type", + "fieldtype": "Data", + "width": 80 + } + ] elif self.filters.get("type_of_business") == "B2C Small": self.invoice_columns = [ { @@ -578,6 +695,25 @@ class Gstr1Report(object): "width": 120 } ] + elif self.filters.get("type_of_business") == "Advances": + self.invoice_columns = [ + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + } + ] + + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + } + ] + self.columns = self.invoice_columns + self.tax_columns + self.other_columns @frappe.whitelist() @@ -616,12 +752,29 @@ def get_json(filters, report_name, data): out = get_export_json(res) gst_json["exp"] = out - elif filters["type_of_business"] == 'CDNR-REG': + elif filters["type_of_business"] == "CDNR-REG": for item in report_data[:-1]: res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) out = get_cdnr_reg_json(res, gstin) gst_json["cdnr"] = out + elif filters["type_of_business"] == "CDNR-UNREG": + for item in report_data[:-1]: + res.setdefault(item["invoice_number"],[]).append(item) + + out = get_cdnr_unreg_json(res, gstin) + gst_json["cdnur"] = out + + elif filters["type_of_business"] == "Advances": + for item in report_data[:-1]: + if not item.get("place_of_supply"): + frappe.throw(_("""{0} not entered in some entries. + Please update and try again""").format(frappe.bold("Place Of Supply"))) + + res.setdefault(item["place_of_supply"],[]).append(item) + + out = get_advances_json(res, gstin) + gst_json["at"] = out return { 'report_name': report_name, @@ -701,6 +854,40 @@ def get_b2cs_json(data, gstin): return out +def get_advances_json(data, gstin): + company_state_number = gstin[0:2] + out = [] + for place_of_supply, items in iteritems(data): + supply_type = "INTRA" if company_state_number == place_of_supply.split('-')[0] else "INTER" + row = { + "pos": place_of_supply.split('-')[0], + "itms": [], + "sply_ty": supply_type + } + + for item in items: + itms = { + 'rt': item['rate'], + 'ad_amount': flt(item.get('taxable_value')), + 'csamt': flt(item.get('cess_amount')) + } + + if supply_type == "INTRA": + itms.update({ + "samt": flt((itms["ad_amount"] * itms["rt"]) / 100), + "camt": flt((itms["ad_amount"] * itms["rt"]) / 100), + "rt": itms["rt"] * 2 + }) + else: + itms.update({ + "iamt": flt((itms["ad_amount"] * itms["rt"]) / 100) + }) + + row['itms'].append(itms) + out.append(row) + + return out + def get_b2cl_json(res, gstin): out = [] for pos in res: @@ -780,6 +967,27 @@ def get_cdnr_reg_json(res, gstin): return out +def get_cdnr_unreg_json(res, gstin): + out = [] + + for invoice, items in iteritems(res): + inv_item = { + "nt_num": items[0]["invoice_number"], + "nt_dt": getdate(items[0]["posting_date"]).strftime('%d-%m-%Y'), + "val": abs(flt(items[0]["invoice_value"])), + "ntty": items[0]["document_type"], + "pos": "%02d" % int(items[0]["place_of_supply"].split('-')[0]), + "typ": get_invoice_type_for_cdnrur(items[0]) + } + + inv_item["itms"] = [] + for item in items: + inv_item["itms"].append(get_rate_and_tax_details(item, gstin)) + + out.append(inv_item) + + return out + def get_invoice_type_for_cdnr(row): if row.get('gst_category') == 'SEZ': if row.get('export_type') == 'WPAY': @@ -787,12 +995,23 @@ def get_invoice_type_for_cdnr(row): else: invoice_type = 'SEWOP' elif row.get('gst_category') == 'Deemed Export': - row.invoice_type = 'DE' + invoice_type = 'DE' elif row.get('gst_category') == 'Registered Regular': invoice_type = 'R' return invoice_type +def get_invoice_type_for_cdnrur(row): + if row.get('gst_category') == 'Overseas': + if row.get('export_type') == 'WPAY': + invoice_type = 'EXPWP' + else: + invoice_type = 'EXPWOP' + elif row.get('gst_category') == 'Unregistered': + invoice_type = 'B2CL' + + return invoice_type + def get_basic_invoice_detail(row): return { "inum": row["invoice_number"], @@ -832,7 +1051,7 @@ def get_company_gstin_number(company, address=None, all_gstins=False): ["Dynamic Link", "link_name", "=", company], ["Dynamic Link", "parenttype", "=", "Address"], ] - gstin = frappe.get_all("Address", filters=filters, pluck="gstin") + gstin = frappe.get_all("Address", filters=filters, pluck="gstin", order_by="is_primary_address desc") if gstin and not all_gstins: gstin = gstin[0] diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index 616c2b853df..5e44955ce30 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -2,10 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from datetime import date + +import frappe + from erpnext.regional.report.gstr_1.gstr_1 import Gstr1Report + def execute(filters=None): return Gstr2Report(filters).run() diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py index 1adddbdae57..7a938c7e0f2 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py @@ -2,16 +2,20 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe import _ -from frappe.utils import flt, getdate, cstr -from frappe.model.meta import get_field_precision -from frappe.utils.xlsxutils import handle_html -from six import iteritems + import json + +import frappe +from frappe import _ +from frappe.model.meta import get_field_precision +from frappe.utils import cstr, flt, getdate +from six import iteritems + +import erpnext from erpnext.regional.india.utils import get_gst_accounts from erpnext.regional.report.gstr_1.gstr_1 import get_company_gstin_number + def execute(filters=None): return _execute(filters) diff --git a/erpnext/regional/report/irs_1099/irs_1099.py b/erpnext/regional/report/irs_1099/irs_1099.py index f67d622fdf8..b1a5d109621 100644 --- a/erpnext/regional/report/irs_1099/irs_1099.py +++ b/erpnext/regional/report/irs_1099/irs_1099.py @@ -3,16 +3,16 @@ import json -from PyPDF2 import PdfFileWriter - import frappe -from erpnext.accounts.utils import get_fiscal_year from frappe import _ from frappe.utils import cstr, nowdate from frappe.utils.data import fmt_money from frappe.utils.jinja import render_template from frappe.utils.pdf import get_pdf from frappe.utils.print_format import read_multi_pdf +from PyPDF2 import PdfFileWriter + +from erpnext.accounts.utils import get_fiscal_year IRS_1099_FORMS_FILE_EXTENSION = ".pdf" diff --git a/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py b/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py index 54808e59e1a..5300b928925 100644 --- a/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py +++ b/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py @@ -2,9 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from erpnext.regional.report.provident_fund_deductions.provident_fund_deductions import get_conditions + +from erpnext.regional.report.provident_fund_deductions.provident_fund_deductions import ( + get_conditions, +) + def execute(filters=None): data = get_data(filters) diff --git a/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py b/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py index 82423f005cc..ae5d6b90b4e 100644 --- a/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py +++ b/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import getdate from frappe import _ +from frappe.utils import getdate + def execute(filters=None): data = get_data(filters) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index daa69768c57..e19aeaa0eff 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -1,21 +1,23 @@ # coding=utf-8 from __future__ import unicode_literals -import erpnext -import frappe from unittest import TestCase -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + +import frappe + +import erpnext from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse_account +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( - get_total_emiratewise, - get_tourist_tax_return_total, - get_tourist_tax_return_tax, - get_zero_rated_total, get_exempt_total, - get_standard_rated_expenses_total, get_standard_rated_expenses_tax, + get_standard_rated_expenses_total, + get_total_emiratewise, + get_tourist_tax_return_tax, + get_tourist_tax_return_total, + get_zero_rated_total, ) +from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse_account test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"] diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index b0614238ba0..f4c049d1623 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns() data, emirates, amounts_by_emirate = get_data(filters) diff --git a/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py b/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py index dea17a66fda..77beff36ecd 100644 --- a/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py +++ b/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py @@ -2,16 +2,18 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from unittest import TestCase + +import frappe from frappe.utils import today from erpnext.accounts.doctype.account.test_account import create_account -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice - +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.regional.report.vat_audit_report.vat_audit_report import execute + class TestVATAuditReport(TestCase): def setUp(self): frappe.set_user("Administrator") diff --git a/erpnext/regional/report/vat_audit_report/vat_audit_report.py b/erpnext/regional/report/vat_audit_report/vat_audit_report.py index ebf297113d7..3637bcaf439 100644 --- a/erpnext/regional/report/vat_audit_report/vat_audit_report.py +++ b/erpnext/regional/report/vat_audit_report/vat_audit_report.py @@ -2,11 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe from frappe import _ from frappe.utils import formatdate, get_link_to_form + def execute(filters=None): return VATAuditReport(filters).run() @@ -190,7 +193,7 @@ class VATAuditReport(object): row["posting_date"] = formatdate(inv_data.get("posting_date"), "dd-mm-yyyy") row["voucher_type"] = doctype row["voucher_no"] = inv - row["party_type"] = "Customer" if doctype == "Sales Invoice" else "Supplier" + row["party_type"] = "Customer" if doctype == "Sales Invoice" else "Supplier" row["party"] = inv_data.get("party") row["remarks"] = inv_data.get("remarks") row["gross_amount"]= item_details[0].get("gross_amount") diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py index 9b3677d2c64..3ccaae9e6a5 100644 --- a/erpnext/regional/saudi_arabia/setup.py +++ b/erpnext/regional/saudi_arabia/setup.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals -from erpnext.regional.united_arab_emirates.setup import make_custom_fields, add_print_formats +from erpnext.regional.united_arab_emirates.setup import add_print_formats, make_custom_fields def setup(company=None, patch=True): diff --git a/erpnext/regional/south_africa/setup.py b/erpnext/regional/south_africa/setup.py index 4657ff833dd..b13599ed0cb 100644 --- a/erpnext/regional/south_africa/setup.py +++ b/erpnext/regional/south_africa/setup.py @@ -7,6 +7,7 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.permissions import add_permission, update_permission_property + def setup(company=None, patch=True): make_custom_fields() add_permissions() @@ -24,7 +25,7 @@ def make_custom_fields(update=True): 'Sales Invoice Item': is_zero_rated, 'Purchase Invoice Item': is_zero_rated } - + create_custom_fields(custom_fields, update=update) def add_permissions(): @@ -36,7 +37,7 @@ def add_permissions(): add_permission(doctype, role, 0) update_permission_property(doctype, role, 0, 'write', 1) update_permission_property(doctype, role, 0, 'create', 1) - + if not frappe.db.get_value('Custom Role', dict(report="VAT Audit Report")): frappe.get_doc(dict( diff --git a/erpnext/regional/turkey/setup.py b/erpnext/regional/turkey/setup.py index 2396aab91f5..85d29b5da7f 100644 --- a/erpnext/regional/turkey/setup.py +++ b/erpnext/regional/turkey/setup.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + def setup(company=None, patch=True): pass diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index bd12d661f00..68da887bb72 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -3,11 +3,13 @@ from __future__ import unicode_literals -import frappe, os, json +import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.permissions import add_permission, update_permission_property + from erpnext.payroll.doctype.gratuity_rule.gratuity_rule import get_gratuity_rule + def setup(company=None, patch=True): make_custom_fields() add_print_formats() diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 7d5fd6ecf86..66a96514fc1 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -1,11 +1,14 @@ from __future__ import unicode_literals + import frappe from frappe import _ -import erpnext -from frappe.utils import flt, round_based_on_smallest_currency_fraction, money_in_words -from erpnext.controllers.taxes_and_totals import get_itemised_tax +from frappe.utils import flt, money_in_words, round_based_on_smallest_currency_fraction from six import iteritems +import erpnext +from erpnext.controllers.taxes_and_totals import get_itemised_tax + + def update_itemised_tax_data(doc): if not doc.taxes: return diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py index c0cec3aef92..03791f31753 100644 --- a/erpnext/regional/united_states/setup.py +++ b/erpnext/regional/united_states/setup.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe import os import json from frappe.permissions import add_permission, update_permission_property from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + def setup(company=None, patch=True): # Company independent fixtures should be called only once at the first company setup if frappe.db.count('Company', {'country': 'United States'}) <=1: diff --git a/erpnext/regional/united_states/test_united_states.py b/erpnext/regional/united_states/test_united_states.py index 513570ed6df..19e9a3546f8 100644 --- a/erpnext/regional/united_states/test_united_states.py +++ b/erpnext/regional/united_states/test_united_states.py @@ -1,8 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import unittest + +import frappe + from erpnext.regional.report.irs_1099.irs_1099 import execute as execute_1099_report diff --git a/erpnext/restaurant/doctype/restaurant/restaurant.py b/erpnext/restaurant/doctype/restaurant/restaurant.py index 0bb7b692c75..486afc3a11e 100644 --- a/erpnext/restaurant/doctype/restaurant/restaurant.py +++ b/erpnext/restaurant/doctype/restaurant/restaurant.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class Restaurant(Document): pass diff --git a/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py b/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py index adce5c73352..5b78bb2f45a 100644 --- a/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py +++ b/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'restaurant', diff --git a/erpnext/restaurant/doctype/restaurant/test_restaurant.py b/erpnext/restaurant/doctype/restaurant/test_restaurant.py index 3ba7f5785eb..574cd1f9e4a 100644 --- a/erpnext/restaurant/doctype/restaurant/test_restaurant.py +++ b/erpnext/restaurant/doctype/restaurant/test_restaurant.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest test_records = [ diff --git a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py index 952c46769b7..632f4850d8a 100644 --- a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py +++ b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class RestaurantMenu(Document): def validate(self): for d in self.items: diff --git a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py index 29f95fd8b1f..00cbf358d6f 100644 --- a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py +++ b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py @@ -3,9 +3,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_records = [ dict(doctype='Item', item_code='Food Item 1', item_group='Products', is_stock_item=0), diff --git a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py b/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py index cc86bb3165e..5d095f49a8e 100644 --- a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py +++ b/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class RestaurantMenuItem(Document): pass diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py index 357deaac007..1ed5921f350 100644 --- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py +++ b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py @@ -3,11 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe.model.document import Document + +import json + +import frappe from frappe import _ +from frappe.model.document import Document + from erpnext.controllers.queries import item_query + class RestaurantOrderEntry(Document): pass diff --git a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py b/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py index e0c051b1ad7..ee8928b13a1 100644 --- a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py +++ b/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class RestaurantOrderEntryItem(Document): pass diff --git a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py index f96de44c3d6..f6d2a7c8cc4 100644 --- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py +++ b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document + from datetime import timedelta + +from frappe.model.document import Document from frappe.utils import get_datetime + class RestaurantReservation(Document): def validate(self): if not self.reservation_end_time: diff --git a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py b/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py index 71681b2f183..885da724aa0 100644 --- a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py +++ b/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestRestaurantReservation(unittest.TestCase): pass diff --git a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py index d5ea9d53981..0b5d6352711 100644 --- a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py +++ b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py @@ -3,10 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, re + +import re + from frappe.model.document import Document from frappe.model.naming import make_autoname + class RestaurantTable(Document): def autoname(self): prefix = re.sub('-+', '-', self.restaurant.replace(' ', '-')) diff --git a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py b/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py index ffdb6f742a3..44059aee607 100644 --- a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py +++ b/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest test_records = [ diff --git a/erpnext/selling/doctype/campaign/campaign.py b/erpnext/selling/doctype/campaign/campaign.py index 10945428aee..09fea9a987c 100644 --- a/erpnext/selling/doctype/campaign/campaign.py +++ b/erpnext/selling/doctype/campaign/campaign.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe.model.document import Document from frappe.model.naming import set_name_by_naming_series + class Campaign(Document): def autoname(self): if frappe.defaults.get_global_default('campaign_naming_by') != 'Naming Series': diff --git a/erpnext/selling/doctype/campaign/campaign_dashboard.py b/erpnext/selling/doctype/campaign/campaign_dashboard.py index 3cef560c32f..990ebaae79c 100644 --- a/erpnext/selling/doctype/campaign/campaign_dashboard.py +++ b/erpnext/selling/doctype/campaign/campaign_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'campaign_name', diff --git a/erpnext/selling/doctype/campaign/test_campaign.py b/erpnext/selling/doctype/campaign/test_campaign.py index 8c6617fe79a..bcb985b50f7 100644 --- a/erpnext/selling/doctype/campaign/test_campaign.py +++ b/erpnext/selling/doctype/campaign/test_campaign.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Campaign') diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 27e9f08e8d6..2946cd9a172 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -2,20 +2,26 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json -from frappe.model.naming import set_name_by_naming_series -from frappe import _, msgprint + +import frappe import frappe.defaults -from frappe.utils import flt, cint, cstr, today, get_formatted_email +from frappe import _, msgprint +from frappe.contacts.address_and_contact import ( + delete_contact_and_address, + load_address_and_contact, +) from frappe.desk.reportview import build_match_conditions, get_filters_cond -from erpnext.utilities.transaction_base import TransactionBase -from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address -from frappe.model.rename_doc import update_linked_doctypes from frappe.model.mapper import get_mapped_doc +from frappe.model.naming import set_name_by_naming_series +from frappe.model.rename_doc import update_linked_doctypes +from frappe.utils import cint, cstr, flt, get_formatted_email, today from frappe.utils.user import get_users_with_role +from erpnext.accounts.party import get_dashboard_info, validate_party_accounts +from erpnext.utilities.transaction_base import TransactionBase + class Customer(TransactionBase): def get_feed(self): @@ -286,30 +292,6 @@ class Customer(TransactionBase): .format(frappe.bold(self.customer_name)) ) - def create_onboarding_docs(self, args): - defaults = frappe.defaults.get_defaults() - company = defaults.get('company') or \ - frappe.db.get_single_value('Global Defaults', 'default_company') - - for i in range(1, args.get('max_count')): - customer = args.get('customer_name_' + str(i)) - if customer: - try: - doc = frappe.get_doc({ - 'doctype': self.doctype, - 'customer_name': customer, - 'customer_type': 'Company', - 'customer_group': _('Commercial'), - 'territory': defaults.get('country'), - 'company': company - }).insert() - - if args.get('customer_email_' + str(i)): - create_contact(customer, self.doctype, - doc.name, args.get("customer_email_" + str(i))) - except frappe.NameError: - pass - def create_contact(contact, party_type, party, email): """Create contact based on given contact name""" contact = contact.split(' ') diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 5b337313d3d..73daa85986b 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -3,13 +3,14 @@ from __future__ import unicode_literals -import frappe import unittest -from erpnext.accounts.party import get_due_date +import frappe from frappe.test_runner import make_test_records -from erpnext.exceptions import PartyFrozen, PartyDisabled from frappe.utils import flt + +from erpnext.accounts.party import get_due_date +from erpnext.exceptions import PartyDisabled, PartyFrozen from erpnext.selling.doctype.customer.customer import get_credit_limit, get_customer_outstanding from erpnext.tests.utils import create_test_contact_and_address @@ -19,6 +20,7 @@ test_records = frappe.get_test_records('Customer') from six import iteritems + class TestCustomer(unittest.TestCase): def setUp(self): if not frappe.get_value('Item', '_Test Item'): @@ -253,10 +255,10 @@ class TestCustomer(unittest.TestCase): return get_customer_outstanding('_Test Customer', '_Test Company') def test_customer_credit_limit(self): - from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note outstanding_amt = self.get_customer_outstanding_amount() credit_limit = get_credit_limit('_Test Customer', '_Test Company') diff --git a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py index 60a4a9a5d25..53bcc1b102e 100644 --- a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py +++ b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class CustomerCreditLimit(Document): pass diff --git a/erpnext/selling/doctype/industry_type/industry_type.py b/erpnext/selling/doctype/industry_type/industry_type.py index 7a30d6524a0..6d413ece2e7 100644 --- a/erpnext/selling/doctype/industry_type/industry_type.py +++ b/erpnext/selling/doctype/industry_type/industry_type.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class IndustryType(Document): pass diff --git a/erpnext/selling/doctype/industry_type/test_industry_type.py b/erpnext/selling/doctype/industry_type/test_industry_type.py index ebc6366155e..d6cf79ba89b 100644 --- a/erpnext/selling/doctype/industry_type/test_industry_type.py +++ b/erpnext/selling/doctype/industry_type/test_industry_type.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Industry Type') diff --git a/erpnext/selling/doctype/installation_note/installation_note.py b/erpnext/selling/doctype/installation_note/installation_note.py index ffcbb2daf09..128a9415c87 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.py +++ b/erpnext/selling/doctype/installation_note/installation_note.py @@ -2,15 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe +from frappe import _ from frappe.utils import cstr, getdate -from frappe import _ from erpnext.stock.utils import get_valid_serial_nos - from erpnext.utilities.transaction_base import TransactionBase + class InstallationNote(TransactionBase): def __init__(self, *args, **kwargs): super(InstallationNote, self).__init__(*args, **kwargs) diff --git a/erpnext/selling/doctype/installation_note/test_installation_note.py b/erpnext/selling/doctype/installation_note/test_installation_note.py index 553d070da0f..abfda9cd6b8 100644 --- a/erpnext/selling/doctype/installation_note/test_installation_note.py +++ b/erpnext/selling/doctype/installation_note/test_installation_note.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Installation Note') diff --git a/erpnext/selling/doctype/installation_note_item/installation_note_item.py b/erpnext/selling/doctype/installation_note_item/installation_note_item.py index 7e1205231bb..862c2a1bb51 100644 --- a/erpnext/selling/doctype/installation_note_item/installation_note_item.py +++ b/erpnext/selling/doctype/installation_note_item/installation_note_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class InstallationNoteItem(Document): pass diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index ae3482f402b..4c73916f852 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -2,13 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe +from frappe import _ +from frappe.model.document import Document from frappe.utils import get_link_to_form -from frappe import _ - -from frappe.model.document import Document class ProductBundle(Document): def autoname(self): diff --git a/erpnext/selling/doctype/product_bundle/test_product_bundle.py b/erpnext/selling/doctype/product_bundle/test_product_bundle.py index 7d1d372b111..13bd2a30923 100644 --- a/erpnext/selling/doctype/product_bundle/test_product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/test_product_bundle.py @@ -3,8 +3,8 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Product Bundle') def make_product_bundle(parent, items, qty=None): diff --git a/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py b/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py index 8721bfad866..5f71a27f369 100644 --- a/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py +++ b/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ProductBundleItem(Document): pass diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 5a0d9c90655..474cf56fc1b 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -18,6 +18,8 @@ frappe.ui.form.on('Quotation', { } }); + frm.set_df_property('packed_items', 'cannot_add_rows', true); + frm.set_df_property('packed_items', 'cannot_delete_rows', true); }, refresh: function(frm) { diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 3eba62bc193..43a44900fcb 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -43,6 +43,8 @@ "ignore_pricing_rule", "items_section", "items", + "bundle_items_section", + "packed_items", "pricing_rule_details", "pricing_rules", "sec_break23", @@ -926,6 +928,24 @@ "label": "Lost Reasons", "options": "Quotation Lost Reason Detail", "read_only": 1 + }, + { + "depends_on": "packed_items", + "fieldname": "packed_items", + "fieldtype": "Table", + "label": "Bundle Items", + "options": "Packed Item", + "print_hide": 1 + }, + { + "collapsible": 1, + "collapsible_depends_on": "packed_items", + "depends_on": "packed_items", + "fieldname": "bundle_items_section", + "fieldtype": "Section Break", + "label": "Bundle Items", + "options": "fa fa-suitcase", + "print_hide": 1 } ], "icon": "fa fa-shopping-cart", @@ -933,7 +953,7 @@ "is_submittable": 1, "links": [], "max_attachments": 1, - "modified": "2020-10-30 13:58:59.212060", + "modified": "2021-08-27 20:10:07.864951", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index e4f8a475816..e9644cc722b 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.model.mapper import get_mapped_doc -from frappe.utils import flt, nowdate, getdate from frappe import _ +from frappe.model.mapper import get_mapped_doc +from frappe.utils import flt, getdate, nowdate from erpnext.controllers.selling_controller import SellingController @@ -31,6 +32,9 @@ class Quotation(SellingController): if self.items: self.with_items = 1 + from erpnext.stock.doctype.packed_item.packed_item import make_packing_list + make_packing_list(self) + def validate_valid_till(self): if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date): frappe.throw(_("Valid till date cannot be before transaction date")) @@ -270,7 +274,7 @@ def _make_customer(source_name, ignore_permissions=False): customer = frappe.get_doc(customer_doclist) customer.flags.ignore_permissions = ignore_permissions if quotation.get("party_name") == "Shopping Cart": - customer.customer_group = frappe.db.get_value("Shopping Cart Settings", None, + customer.customer_group = frappe.db.get_value("E Commerce Settings", None, "default_customer_group") try: diff --git a/erpnext/selling/doctype/quotation/quotation_dashboard.py b/erpnext/selling/doctype/quotation/quotation_dashboard.py index d1bb788937b..9586cb10b59 100644 --- a/erpnext/selling/doctype/quotation/quotation_dashboard.py +++ b/erpnext/selling/doctype/quotation/quotation_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'prevdoc_docname', diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 527a999aefa..a44089a9ce4 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import flt, add_days, nowdate, add_months, getdate import unittest +import frappe +from frappe.utils import add_days, add_months, flt, getdate, nowdate + test_dependencies = ["Product Bundle"] @@ -133,8 +134,10 @@ class TestQuotation(unittest.TestCase): def test_create_quotation_with_margin(self): from erpnext.selling.doctype.quotation.quotation import make_sales_order - from erpnext.selling.doctype.sales_order.sales_order \ - import make_delivery_note, make_sales_invoice + from erpnext.selling.doctype.sales_order.sales_order import ( + make_delivery_note, + make_sales_invoice, + ) rate_with_margin = flt((1500*18.75)/100 + 1500) @@ -226,9 +229,87 @@ class TestQuotation(unittest.TestCase): expired_quotation.reload() self.assertEqual(expired_quotation.status, "Expired") + def test_product_bundle_mapping_on_creating_so(self): + from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle + from erpnext.selling.doctype.quotation.quotation import make_sales_order + from erpnext.stock.doctype.item.test_item import make_item + + make_item("_Test Product Bundle", {"is_stock_item": 0}) + make_item("_Test Bundle Item 1", {"is_stock_item": 1}) + make_item("_Test Bundle Item 2", {"is_stock_item": 1}) + + make_product_bundle("_Test Product Bundle", + ["_Test Bundle Item 1", "_Test Bundle Item 2"]) + + quotation = make_quotation(item_code="_Test Product Bundle", qty=1, rate=100) + sales_order = make_sales_order(quotation.name) + + quotation_item = [quotation.items[0].item_code, quotation.items[0].rate, quotation.items[0].qty, quotation.items[0].amount] + so_item = [sales_order.items[0].item_code, sales_order.items[0].rate, sales_order.items[0].qty, sales_order.items[0].amount] + + self.assertEqual(quotation_item, so_item) + + quotation_packed_items = [ + [quotation.packed_items[0].parent_item, quotation.packed_items[0].item_code, quotation.packed_items[0].qty], + [quotation.packed_items[1].parent_item, quotation.packed_items[1].item_code, quotation.packed_items[1].qty] + ] + so_packed_items = [ + [sales_order.packed_items[0].parent_item, sales_order.packed_items[0].item_code, sales_order.packed_items[0].qty], + [sales_order.packed_items[1].parent_item, sales_order.packed_items[1].item_code, sales_order.packed_items[1].qty] + ] + + self.assertEqual(quotation_packed_items, so_packed_items) + + def test_product_bundle_price_calculation_when_calculate_bundle_price_is_unchecked(self): + from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle + from erpnext.stock.doctype.item.test_item import make_item + + make_item("_Test Product Bundle", {"is_stock_item": 0}) + bundle_item1 = make_item("_Test Bundle Item 1", {"is_stock_item": 1}) + bundle_item2 = make_item("_Test Bundle Item 2", {"is_stock_item": 1}) + + make_product_bundle("_Test Product Bundle", + ["_Test Bundle Item 1", "_Test Bundle Item 2"]) + + bundle_item1.valuation_rate = 100 + bundle_item1.save() + + bundle_item2.valuation_rate = 200 + bundle_item2.save() + + quotation = make_quotation(item_code="_Test Product Bundle", qty=2, rate=100) + self.assertEqual(quotation.items[0].amount, 200) + + def test_product_bundle_price_calculation_when_calculate_bundle_price_is_checked(self): + from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle + from erpnext.stock.doctype.item.test_item import make_item + + make_item("_Test Product Bundle", {"is_stock_item": 0}) + make_item("_Test Bundle Item 1", {"is_stock_item": 1}) + make_item("_Test Bundle Item 2", {"is_stock_item": 1}) + + make_product_bundle("_Test Product Bundle", + ["_Test Bundle Item 1", "_Test Bundle Item 2"]) + + enable_calculate_bundle_price() + + quotation = make_quotation(item_code="_Test Product Bundle", qty=2, rate=100, do_not_submit=1) + quotation.packed_items[0].rate = 100 + quotation.packed_items[1].rate = 200 + quotation.save() + + self.assertEqual(quotation.items[0].amount, 600) + self.assertEqual(quotation.items[0].rate, 300) + + enable_calculate_bundle_price(enable=0) test_records = frappe.get_test_records('Quotation') +def enable_calculate_bundle_price(enable=1): + selling_settings = frappe.get_doc("Selling Settings") + selling_settings.editable_bundle_item_rates = enable + selling_settings.save() + def get_quotation_dict(party_name=None, item_code=None): if not party_name: party_name = '_Test Customer' diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 8b53902d32f..31a95896bc1 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -649,7 +649,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-02-23 01:13:54.670763", + "modified": "2021-07-15 12:40:51.074820", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.py b/erpnext/selling/doctype/quotation_item/quotation_item.py index 7384871ed44..ea472497299 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.py +++ b/erpnext/selling/doctype/quotation_item/quotation_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class QuotationItem(Document): pass diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index e3b41e66fbc..1961371d0b8 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -43,6 +43,9 @@ frappe.ui.form.on("Sales Order", { } } }); + + frm.set_df_property('packed_items', 'cannot_add_rows', true); + frm.set_df_property('packed_items', 'cannot_delete_rows', true); }, refresh: function(frm) { if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed' diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 38ea5c81d49..85282ca1a07 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -55,6 +55,8 @@ "items_section", "scan_barcode", "items", + "packing_list", + "packed_items", "pricing_rule_details", "pricing_rules", "section_break_31", @@ -101,8 +103,6 @@ "in_words", "advance_paid", "disable_rounded_total", - "packing_list", - "packed_items", "payment_schedule_section", "payment_terms_template", "payment_schedule", @@ -1019,6 +1019,7 @@ { "collapsible": 1, "collapsible_depends_on": "packed_items", + "depends_on": "packed_items", "fieldname": "packing_list", "fieldtype": "Section Break", "hide_days": 1, @@ -1029,14 +1030,14 @@ "print_hide": 1 }, { + "depends_on": "packed_items", "fieldname": "packed_items", "fieldtype": "Table", "hide_days": 1, "hide_seconds": 1, "label": "Packed Items", "options": "Packed Item", - "print_hide": 1, - "read_only": 1 + "print_hide": 1 }, { "fieldname": "payment_schedule_section", @@ -1511,7 +1512,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2021-08-17 20:15:26.531553", + "modified": "2021-09-01 15:12:24.115483", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5d44582aab4..93676094218 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -2,24 +2,32 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json + +import frappe import frappe.utils -from frappe.utils import cstr, flt, getdate, cint, nowdate, add_days, get_link_to_form, strip_html from frappe import _ -from six import string_types -from frappe.model.utils import get_fetch_values -from frappe.model.mapper import get_mapped_doc -from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty -from frappe.desk.notifications import clear_doctype_notifications from frappe.contacts.doctype.address.address import get_company_address +from frappe.desk.notifications import clear_doctype_notifications +from frappe.model.mapper import get_mapped_doc +from frappe.model.utils import get_fetch_values +from frappe.utils import add_days, cint, cstr, flt, get_link_to_form, getdate, nowdate, strip_html +from six import string_types + +from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + unlink_inter_company_doc, + update_linked_doc, + validate_inter_company_party, +) from erpnext.controllers.selling_controller import SellingController +from erpnext.manufacturing.doctype.production_plan.production_plan import ( + get_items_for_material_requests, +) from erpnext.selling.doctype.customer.customer import check_credit_limit -from erpnext.stock.doctype.item.item import get_item_defaults from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults -from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests -from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\ - unlink_inter_company_doc +from erpnext.stock.doctype.item.item import get_item_defaults +from erpnext.stock.stock_balance import get_reserved_qty, update_bin_qty form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -947,11 +955,52 @@ def make_purchase_order(source_name, selected_items=None, target_doc=None): "pricing_rules" ], "postprocess": update_item, - "condition": lambda doc: doc.ordered_qty < doc.stock_qty and doc.item_code in items_to_map + "condition": lambda doc: doc.ordered_qty < doc.stock_qty and doc.item_code in items_to_map and not is_product_bundle(doc.item_code) + }, + "Packed Item": { + "doctype": "Purchase Order Item", + "field_map": [ + ["parent", "sales_order"], + ["uom", "uom"], + ["conversion_factor", "conversion_factor"], + ["parent_item", "product_bundle"], + ["rate", "rate"] + ], + "field_no_map": [ + "price_list_rate", + "item_tax_template", + "discount_percentage", + "discount_amount", + "supplier", + "pricing_rules" + ], } }, target_doc, set_missing_values) + + set_delivery_date(doc.items, source_name) + return doc +def set_delivery_date(items, sales_order): + delivery_dates = frappe.get_all( + 'Sales Order Item', + filters = { + 'parent': sales_order + }, + fields = ['delivery_date', 'item_code'] + ) + + delivery_by_item = frappe._dict() + for date in delivery_dates: + delivery_by_item[date.item_code] = date.delivery_date + + for item in items: + if item.product_bundle: + item.schedule_date = delivery_by_item[item.product_bundle] + +def is_product_bundle(item_code): + return frappe.db.exists('Product Bundle', item_code) + @frappe.whitelist() def make_work_orders(items, sales_order, company, project=None): '''Make Work Orders against the given Sales Order for the given `items`''' diff --git a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py index 2a71c27009f..ee3c707b5b8 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py +++ b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'sales_order', diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index d685fbff82b..62ea44df435 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -1,21 +1,29 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import json import unittest + import frappe import frappe.permissions -from frappe.utils import flt, add_days, nowdate, getdate from frappe.core.doctype.user_permission.test_user_permission import create_user -from erpnext.selling.doctype.sales_order.sales_order \ - import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.selling.doctype.sales_order.sales_order import make_work_orders +from frappe.utils import add_days, flt, getdate, nowdate + from erpnext.controllers.accounts_controller import update_child_qty_rate -from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle +from erpnext.selling.doctype.sales_order.sales_order import ( + WarehouseRequired, + make_delivery_note, + make_material_request, + make_raw_material_request, + make_sales_invoice, + make_work_orders, +) from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + class TestSalesOrder(unittest.TestCase): @@ -162,8 +170,8 @@ class TestSalesOrder(unittest.TestCase): self.assertEqual(so.get("items")[0].delivered_qty, 9) # Make return deliver note, sales invoice and check quantity - from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-3, do_not_submit=True) dn1.items[0].against_sales_order = so.name @@ -444,8 +452,8 @@ class TestSalesOrder(unittest.TestCase): self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name) def test_update_child_with_precision(self): - from frappe.model.meta import get_field_precision from frappe.custom.doctype.property_setter.property_setter import make_property_setter + from frappe.model.meta import get_field_precision precision = get_field_precision(frappe.get_meta("Sales Order Item").get_field("rate")) @@ -731,9 +739,11 @@ class TestSalesOrder(unittest.TestCase): frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 1) def test_drop_shipping(self): - from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_default_supplier, \ - update_status as so_update_status from erpnext.buying.doctype.purchase_order.purchase_order import update_status + from erpnext.selling.doctype.sales_order.sales_order import ( + make_purchase_order_for_default_supplier, + ) + from erpnext.selling.doctype.sales_order.sales_order import update_status as so_update_status # make items po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1}) @@ -815,8 +825,10 @@ class TestSalesOrder(unittest.TestCase): so.cancel() def test_drop_shipping_partial_order(self): - from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_default_supplier, \ - update_status as so_update_status + from erpnext.selling.doctype.sales_order.sales_order import ( + make_purchase_order_for_default_supplier, + ) + from erpnext.selling.doctype.sales_order.sales_order import update_status as so_update_status # make items po_item1 = make_item("_Test Item for Drop Shipping 1", {"is_stock_item": 1, "delivered_by_supplier": 1}) @@ -869,7 +881,9 @@ class TestSalesOrder(unittest.TestCase): def test_drop_shipping_full_for_default_suppliers(self): """Test if multiple POs are generated in one go against different default suppliers.""" - from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_default_supplier + from erpnext.selling.doctype.sales_order.sales_order import ( + make_purchase_order_for_default_supplier, + ) if not frappe.db.exists("Item", "_Test Item for Drop Shipping 1"): make_item("_Test Item for Drop Shipping 1", {"is_stock_item": 1, "delivered_by_supplier": 1}) @@ -1043,8 +1057,7 @@ class TestSalesOrder(unittest.TestCase): }] }) so.submit() - from erpnext.manufacturing.doctype.work_order.test_work_order import \ - make_wo_order_test_record + from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record work_order = make_wo_order_test_record(item=item.item_code, qty=1, do_not_save=True) work_order.fg_warehouse = "_Test Warehouse - _TC" @@ -1052,8 +1065,9 @@ class TestSalesOrder(unittest.TestCase): work_order.submit() make_stock_entry(item_code=item.item_code, target="_Test Warehouse - _TC", qty=1) item_serial_no = frappe.get_doc("Serial No", {"item_code": item.item_code}) - from erpnext.manufacturing.doctype.work_order.work_order import \ - make_stock_entry as make_production_stock_entry + from erpnext.manufacturing.doctype.work_order.work_order import ( + make_stock_entry as make_production_stock_entry, + ) se = frappe.get_doc(make_production_stock_entry(work_order.name, "Manufacture", 1)) se.submit() reserved_serial_no = se.get("items")[2].serial_no @@ -1085,8 +1099,9 @@ class TestSalesOrder(unittest.TestCase): si = make_sales_invoice(so.name) si.update_stock = 0 si.submit() - from erpnext.accounts.doctype.sales_invoice.sales_invoice import \ - make_delivery_note as make_delivery_note_from_invoice + from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + make_delivery_note as make_delivery_note_from_invoice, + ) dn = make_delivery_note_from_invoice(si.name) dn.save() dn.submit() @@ -1123,6 +1138,7 @@ class TestSalesOrder(unittest.TestCase): def test_cancel_sales_order_after_cancel_payment_entry(self): from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry + # make a sales order so = make_sales_order() @@ -1232,7 +1248,9 @@ class TestSalesOrder(unittest.TestCase): self.assertRaises(frappe.ValidationError, so.cancel) def test_payment_terms_are_fetched_when_creating_sales_invoice(self): - from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.payment_entry.test_payment_entry import ( + create_payment_terms_template, + ) from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice automatically_fetch_payment_terms() diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.py b/erpnext/selling/doctype/sales_order_item/sales_order_item.py index 62afef3e170..772aa6c8ae5 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.py +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe.model.document import Document + class SalesOrderItem(Document): pass diff --git a/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py b/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py index 68d289f0189..bdabef2fdbe 100644 --- a/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py +++ b/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SalesPartnerType(Document): pass diff --git a/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.py b/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.py index fb8f8b0417a..895b0ecf00a 100644 --- a/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.py +++ b/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSalesPartnerType(unittest.TestCase): pass diff --git a/erpnext/selling/doctype/sales_team/sales_team.py b/erpnext/selling/doctype/sales_team/sales_team.py index 28bea254d68..9b542c0eead 100644 --- a/erpnext/selling/doctype/sales_team/sales_team.py +++ b/erpnext/selling/doctype/sales_team/sales_team.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class SalesTeam(Document): pass diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json index f01934b7e6b..28c7e5a4f53 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.json +++ b/erpnext/selling/doctype/selling_settings/selling_settings.json @@ -6,24 +6,32 @@ "document_type": "Other", "engine": "InnoDB", "field_order": [ + "customer_defaults_section", "cust_master_name", - "campaign_naming_by", "customer_group", + "column_break_4", "territory", - "selling_price_list", - "close_opportunity_after_days", + "crm_settings_section", + "campaign_naming_by", "default_valid_till", - "column_break_5", + "column_break_9", + "close_opportunity_after_days", + "item_price_settings_section", + "selling_price_list", + "maintain_same_rate_action", + "role_to_override_stop_action", + "column_break_15", + "maintain_same_sales_rate", + "editable_price_list_rate", + "validate_selling_price", + "editable_bundle_item_rates", + "transaction_settings_section", "so_required", "dn_required", "sales_update_frequency", - "maintain_same_sales_rate", - "maintain_same_rate_action", - "role_to_override_stop_action", - "editable_price_list_rate", + "column_break_5", "allow_multiple_items", "allow_against_multiple_purchase_orders", - "validate_selling_price", "hide_tax_id" ], "fields": [ @@ -75,10 +83,6 @@ "fieldtype": "Data", "label": "Default Quotation Validity Days" }, - { - "fieldname": "column_break_5", - "fieldtype": "Column Break" - }, { "fieldname": "so_required", "fieldtype": "Select", @@ -152,6 +156,48 @@ "fieldtype": "Link", "label": "Role Allowed to Override Stop Action", "options": "Role" + }, + { + "fieldname": "column_break_15", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "editable_bundle_item_rates", + "fieldtype": "Check", + "label": "Calculate Product Bundle Price based on Child Items' Rates" + }, + { + "fieldname": "customer_defaults_section", + "fieldtype": "Section Break", + "label": "Customer Defaults" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, + { + "fieldname": "crm_settings_section", + "fieldtype": "Section Break", + "label": "CRM Settings" + }, + { + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, + { + "fieldname": "item_price_settings_section", + "fieldtype": "Section Break", + "label": "Item Price Settings" + }, + { + "fieldname": "transaction_settings_section", + "fieldtype": "Section Break", + "label": "Transaction Settings" + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" } ], "icon": "fa fa-cog", @@ -159,7 +205,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-04-04 20:18:12.814624", + "modified": "2021-09-06 22:05:06.139820", "modified_by": "Administrator", "module": "Selling", "name": "Selling Settings", diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py index b219e7ecce0..5bed43e4609 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.py +++ b/erpnext/selling/doctype/selling_settings/selling_settings.py @@ -4,17 +4,18 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import frappe.defaults -from frappe.utils import cint from frappe.custom.doctype.property_setter.property_setter import make_property_setter +from frappe.model.document import Document +from frappe.utils import cint from frappe.utils.nestedset import get_root_of -from frappe.model.document import Document class SellingSettings(Document): def on_update(self): self.toggle_hide_tax_id() + self.toggle_editable_rate_for_bundle_items() def validate(self): for key in ["cust_master_name", "campaign_naming_by", "customer_group", "territory", @@ -33,6 +34,11 @@ class SellingSettings(Document): make_property_setter(doctype, "tax_id", "hidden", self.hide_tax_id, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, "tax_id", "print_hide", self.hide_tax_id, "Check", validate_fields_for_doctype=False) + def toggle_editable_rate_for_bundle_items(self): + editable_bundle_item_rates = cint(self.editable_bundle_item_rates) + + make_property_setter("Packed Item", "rate", "read_only", not(editable_bundle_item_rates), "Check", validate_fields_for_doctype=False) + def set_default_customer_group_and_territory(self): if not self.customer_group: self.customer_group = get_root_of('Customer Group') diff --git a/erpnext/selling/doctype/selling_settings/test_selling_settings.py b/erpnext/selling/doctype/selling_settings/test_selling_settings.py index 961a54de0a8..572a110cc3e 100644 --- a/erpnext/selling/doctype/selling_settings/test_selling_settings.py +++ b/erpnext/selling/doctype/selling_settings/test_selling_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestSellingSettings(unittest.TestCase): pass diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py index 87846a84d30..45aee4ea6f0 100644 --- a/erpnext/selling/doctype/sms_center/sms_center.py +++ b/erpnext/selling/doctype/sms_center/sms_center.py @@ -2,14 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe - -from frappe.utils import cstr -from frappe import msgprint, _ - -from frappe.model.document import Document - +from frappe import _, msgprint from frappe.core.doctype.sms_settings.sms_settings import send_sms +from frappe.model.document import Document +from frappe.utils import cstr + class SMSCenter(Document): @frappe.whitelist() diff --git a/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json b/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json deleted file mode 100644 index 92d00bcb380..00000000000 --- a/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "add_more_button": 1, - "app": "ERPNext", - "creation": "2019-11-15 14:44:10.065014", - "docstatus": 0, - "doctype": "Onboarding Slide", - "domains": [], - "help_links": [ - { - "label": "Learn More", - "video_id": "zsrrVDk6VBs" - } - ], - "idx": 0, - "image_src": "", - "is_completed": 0, - "max_count": 3, - "modified": "2019-12-09 17:54:01.686006", - "modified_by": "Administrator", - "name": "Add A Few Customers", - "owner": "Administrator", - "ref_doctype": "Customer", - "slide_desc": "", - "slide_fields": [ - { - "align": "", - "fieldname": "customer_name", - "fieldtype": "Data", - "label": "Customer Name", - "placeholder": "", - "reqd": 1 - }, - { - "align": "", - "fieldtype": "Column Break", - "reqd": 0 - }, - { - "align": "", - "fieldname": "customer_email", - "fieldtype": "Data", - "label": "Email ID", - "reqd": 1 - } - ], - "slide_order": 40, - "slide_title": "Add A Few Customers", - "slide_type": "Create" -} \ No newline at end of file diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 3dc9094ac27..fbf4266e6a9 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -2,11 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json + +import json + +import frappe from frappe.utils.nestedset import get_root_of -from frappe.utils import cint -from erpnext.accounts.doctype.pos_profile.pos_profile import get_item_groups + from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability +from erpnext.accounts.doctype.pos_profile.pos_profile import get_item_groups + def search_by_term(search_term, warehouse, price_list): result = search_for_serial_or_batch_or_barcode_number(search_term) or {} @@ -209,7 +213,6 @@ def check_opening_entry(user): @frappe.whitelist() def create_opening_voucher(pos_profile, company, balance_details): - import json balance_details = json.loads(balance_details) new_pos_opening = frappe.get_doc({ diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.py b/erpnext/selling/page/sales_funnel/sales_funnel.py index 78aaa49a668..043a3e7f0fa 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.py +++ b/erpnext/selling/page/sales_funnel/sales_funnel.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe import _ -from erpnext.accounts.report.utils import convert +import frappe import pandas as pd +from frappe import _ + +from erpnext.accounts.report.utils import convert + def validate_filters(from_date, to_date, company): if from_date and to_date and (from_date >= to_date): diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py index f295333322c..fea19f9f16d 100644 --- a/erpnext/selling/report/address_and_contacts/address_and_contacts.py +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py @@ -2,10 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -from six.moves import range -from six import iteritems -import frappe +import frappe +from six import iteritems +from six.moves import range field_map = { "Contact": [ "first_name", "last_name", "phone", "mobile_no", "email_id", "is_primary_contact" ], diff --git a/erpnext/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py b/erpnext/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py index 5523bad5715..c7040bef708 100644 --- a/erpnext/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py +++ b/erpnext/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe.utils import flt + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py index f15f63d7bb7..a29b5c8a627 100644 --- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py +++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py @@ -2,11 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import calendar + import frappe from frappe import _ from frappe.utils import cint, cstr, getdate + def execute(filters=None): common_columns = [ { diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py index 6fb7666c2ce..ed2fbfd595c 100644 --- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py +++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt -from erpnext.selling.doctype.customer.customer import get_customer_outstanding, get_credit_limit + +from erpnext.selling.doctype.customer.customer import get_credit_limit, get_customer_outstanding + def execute(filters=None): if not filters: filters = {} 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 index eb9273a5626..535d551cfab 100644 --- 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 @@ -4,10 +4,11 @@ from __future__ import unicode_literals import frappe +from frappe import _ + 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): diff --git a/erpnext/selling/report/inactive_customers/inactive_customers.py b/erpnext/selling/report/inactive_customers/inactive_customers.py index e7aff36e828..c79efe24b78 100644 --- a/erpnext/selling/report/inactive_customers/inactive_customers.py +++ b/erpnext/selling/report/inactive_customers/inactive_customers.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cint from frappe import _ +from frappe.utils import cint + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py index 1700fc7bdd5..539631240e1 100644 --- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py +++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py @@ -2,11 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt from frappe.utils.nestedset import get_descendants_of + def execute(filters=None): filters = frappe._dict(filters or {}) if filters.from_date > filters.to_date: diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py index e89c45182fd..f241a3e13d9 100644 --- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py +++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt + def execute(filters=None): columns = get_columns() data = get_data() diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py index f2518f09f8e..95e332ac537 100644 --- a/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py +++ b/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py @@ -2,12 +2,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import unittest -from frappe.utils import nowdate, add_months -from erpnext.selling.report.pending_so_items_for_purchase_request.pending_so_items_for_purchase_request\ - import execute + +from frappe.utils import add_months, nowdate + from erpnext.selling.doctype.sales_order.sales_order import make_material_request from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.selling.report.pending_so_items_for_purchase_request.pending_so_items_for_purchase_request import ( + execute, +) class TestPendingSOItemsForPurchaseRequest(unittest.TestCase): diff --git a/erpnext/selling/report/quotation_trends/quotation_trends.py b/erpnext/selling/report/quotation_trends/quotation_trends.py index 968e2ff26f7..d2ee9a8b742 100644 --- a/erpnext/selling/report/quotation_trends/quotation_trends.py +++ b/erpnext/selling/report/quotation_trends/quotation_trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe import _ -from erpnext.controllers.trends import get_columns, get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.py b/erpnext/selling/report/sales_analytics/sales_analytics.py index d036a1cb095..56bcb3180a3 100644 --- a/erpnext/selling/report/sales_analytics/sales_analytics.py +++ b/erpnext/selling/report/sales_analytics/sales_analytics.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _, scrub -from frappe.utils import getdate, flt, add_to_date, add_days +from frappe.utils import add_days, add_to_date, flt, getdate from six import iteritems + from erpnext.accounts.utils import get_fiscal_year + def execute(filters=None): return Analytics(filters).run() @@ -293,7 +296,7 @@ class Analytics(object): return period def get_period_date_ranges(self): - from dateutil.relativedelta import relativedelta, MO + from dateutil.relativedelta import MO, relativedelta from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date) increment = { diff --git a/erpnext/selling/report/sales_analytics/test_analytics.py b/erpnext/selling/report/sales_analytics/test_analytics.py index 4d81a1e4dda..a1800993f4f 100644 --- a/erpnext/selling/report/sales_analytics/test_analytics.py +++ b/erpnext/selling/report/sales_analytics/test_analytics.py @@ -2,11 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -import frappe.defaults + import unittest -from erpnext.selling.report.sales_analytics.sales_analytics import execute + +import frappe + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.selling.report.sales_analytics.sales_analytics import execute + class TestAnalytics(unittest.TestCase): def test_sales_analytics(self): diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py index 00dcd69c6e6..805c3d804fa 100644 --- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py +++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import copy + +import frappe from frappe import _ -from frappe.utils import flt, date_diff, getdate +from frappe.utils import date_diff, flt, getdate + def execute(filters=None): if not filters: diff --git a/erpnext/selling/report/sales_order_trends/sales_order_trends.py b/erpnext/selling/report/sales_order_trends/sales_order_trends.py index de7d3f2f778..89daf447781 100644 --- a/erpnext/selling/report/sales_order_trends/sales_order_trends.py +++ b/erpnext/selling/report/sales_order_trends/sales_order_trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe import _ -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py index 2c49d51a920..a84dec032e5 100644 --- a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py +++ b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py @@ -2,9 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ -from frappe.utils import flt +from frappe import _, msgprint def execute(filters=None): diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py index 24ca666f6b1..d4f49c71464 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py @@ -2,12 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt -from erpnext.accounts.utils import get_fiscal_year + +from erpnext.accounts.doctype.monthly_distribution.monthly_distribution import ( + get_periodwise_distribution_data, +) from erpnext.accounts.report.financial_statements import get_period_list -from erpnext.accounts.doctype.monthly_distribution.monthly_distribution import get_periodwise_distribution_data +from erpnext.accounts.utils import get_fiscal_year + def get_data_column(filters, partner_doctype): data = [] @@ -44,18 +48,6 @@ def get_data(filters, period_list, partner_doctype): if d.item_group not in item_groups: item_groups.append(d.item_group) - if item_groups: - child_items = [] - for item_group in item_groups: - if frappe.db.get_value("Item Group", {"name":item_group}, "is_group"): - for child_item_group in frappe.get_all("Item Group", {"parent_item_group":item_group}): - if child_item_group['name'] not in child_items: - child_items.append(child_item_group['name']) - - for item in child_items: - if item not in item_groups: - item_groups.append(item) - date_field = ("transaction_date" if filters.get('doctype') == "Sales Order" else "posting_date") diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py index 87ed5a8ea21..de21c4ad02d 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py @@ -2,8 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import ( + get_data_column, +) + def execute(filters=None): data = [] diff --git a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py index f07293d8ec2..39ec072f6ba 100644 --- a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py +++ b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py @@ -2,9 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ -from frappe.utils import flt +from frappe import _, msgprint def execute(filters=None): diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py index 9917d72af86..13245b789ef 100644 --- a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py +++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py @@ -2,9 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ -from frappe.utils import flt +from frappe import _, msgprint def execute(filters=None): diff --git a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py index ea9bbab0c72..83a1c2ce75c 100644 --- a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py @@ -2,8 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import ( + get_data_column, +) + def execute(filters=None): data = [] diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py index 41c7f765175..9dc2923b0a2 100644 --- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py +++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ -from frappe.utils import flt +from frappe import _, msgprint + from erpnext import get_company_currency + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py index b1d89cc3fb8..b340124a040 100644 --- a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py @@ -2,8 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import ( + get_data_column, +) + def execute(filters=None): data = [] diff --git a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py index e8835001707..c334381b430 100644 --- a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py +++ b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py @@ -2,10 +2,13 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from erpnext import get_default_currency from frappe import _ +from erpnext import get_default_currency + + def execute(filters=None): filters = frappe._dict(filters) columns = get_columns() diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 26ac630a32b..091c22271e6 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -90,10 +90,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.toggle_display("customer_name", (this.frm.doc.customer_name && this.frm.doc.customer_name!==this.frm.doc.customer)); - if(this.frm.fields_dict.packed_items) { - var packing_list_exists = (this.frm.doc.packed_items || []).length; - this.frm.toggle_display("packing_list", packing_list_exists ? true : false); - } + this.toggle_editable_price_list_rate(); }, diff --git a/erpnext/setup/default_energy_point_rules.py b/erpnext/setup/default_energy_point_rules.py index 8dbccc497b7..c41d000215b 100644 --- a/erpnext/setup/default_energy_point_rules.py +++ b/erpnext/setup/default_energy_point_rules.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from frappe import _ doctype_rule_map = { diff --git a/erpnext/setup/default_success_action.py b/erpnext/setup/default_success_action.py index 827839f8b75..be072fc47f3 100644 --- a/erpnext/setup/default_success_action.py +++ b/erpnext/setup/default_success_action.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from frappe import _ doctype_list = [ diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index fec5c7ca95d..332d7f438a7 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -2,11 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import cstr, flt, has_common, comma_or -from frappe import session, _ +from frappe import _, session +from frappe.utils import comma_or, cstr, flt, has_common + from erpnext.utilities.transaction_base import TransactionBase + class AuthorizationControl(TransactionBase): def get_appr_user_role(self, det, doctype_name, total, based_on, condition, item, company): amt_list, appr_users, appr_roles = [], [], [] diff --git a/erpnext/setup/doctype/authorization_rule/authorization_rule.py b/erpnext/setup/doctype/authorization_rule/authorization_rule.py index eb8e6ebe78c..ab0f4201219 100644 --- a/erpnext/setup/doctype/authorization_rule/authorization_rule.py +++ b/erpnext/setup/doctype/authorization_rule/authorization_rule.py @@ -2,12 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe - -from frappe.utils import cstr, flt -from frappe import _, msgprint - +from frappe import _ from frappe.model.document import Document +from frappe.utils import cstr, flt + class AuthorizationRule(Document): def check_duplicate_entry(self): diff --git a/erpnext/setup/doctype/authorization_rule/test_authorization_rule.py b/erpnext/setup/doctype/authorization_rule/test_authorization_rule.py index 332f1039921..8a0f6649078 100644 --- a/erpnext/setup/doctype/authorization_rule/test_authorization_rule.py +++ b/erpnext/setup/doctype/authorization_rule/test_authorization_rule.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Authorization Rule') diff --git a/erpnext/setup/doctype/brand/brand.json b/erpnext/setup/doctype/brand/brand.json index a8f0674b1f8..45b4db81f1f 100644 --- a/erpnext/setup/doctype/brand/brand.json +++ b/erpnext/setup/doctype/brand/brand.json @@ -1,270 +1,111 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "field:brand", - "beta": 0, - "creation": "2013-02-22 01:27:54", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, + "actions": [], + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:brand", + "creation": "2013-02-22 01:27:54", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "brand", + "image", + "description", + "defaults", + "brand_defaults" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 1, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "brand", - "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": "Brand Name", - "length": 0, - "no_copy": 0, - "oldfieldname": "brand", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_in_quick_entry": 1, + "fieldname": "brand", + "fieldtype": "Data", + "label": "Brand Name", + "oldfieldname": "brand", + "oldfieldtype": "Data", + "reqd": 1, "unique": 1 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "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": "description", + "fieldtype": "Text", + "in_list_view": 1, + "label": "Description", + "oldfieldname": "description", + "oldfieldtype": "Text", "width": "300px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "defaults", - "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": "Defaults", - "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": "defaults", + "fieldtype": "Section Break", + "label": "Defaults" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "brand_defaults", - "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": "Brand Defaults", - "length": 0, - "no_copy": 0, - "options": "Item Default", - "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": "brand_defaults", + "fieldtype": "Table", + "label": "Brand Defaults", + "options": "Item Default" + }, + { + "fieldname": "image", + "fieldtype": "Attach Image", + "hidden": 1, + "label": "Image" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-certificate", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-23 23:18:06.067612", - "modified_by": "Administrator", - "module": "Setup", - "name": "Brand", - "owner": "Administrator", + ], + "icon": "fa fa-certificate", + "idx": 1, + "image_field": "image", + "links": [], + "modified": "2021-03-01 15:57:30.005783", + "modified_by": "Administrator", + "module": "Setup", + "name": "Brand", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Item Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Item Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User" + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales User" + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase User" + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User" } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, - "sort_order": "ASC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 -} + ], + "quick_entry": 1, + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "ASC" +} \ No newline at end of file diff --git a/erpnext/setup/doctype/brand/brand.py b/erpnext/setup/doctype/brand/brand.py index a8d1cf8ff2d..4cfb018c865 100644 --- a/erpnext/setup/doctype/brand/brand.py +++ b/erpnext/setup/doctype/brand/brand.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import copy +import frappe from frappe.model.document import Document + class Brand(Document): pass diff --git a/erpnext/setup/doctype/brand/test_brand.py b/erpnext/setup/doctype/brand/test_brand.py index 25ed86ef1dd..16873c9fc92 100644 --- a/erpnext/setup/doctype/brand/test_brand.py +++ b/erpnext/setup/doctype/brand/test_brand.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Brand') diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 45d5ce0c1c7..f9f70264f6d 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -2,23 +2,24 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, os, json -from frappe import _ -from frappe.utils import get_timestamp -from frappe.utils import cint, today, formatdate -import frappe.defaults -from frappe.cache_manager import clear_defaults_cache - -from frappe.model.document import Document -from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.utils.nestedset import NestedSet - -from past.builtins import cmp import functools +import json +import os + +import frappe +import frappe.defaults +from frappe import _ +from frappe.cache_manager import clear_defaults_cache +from frappe.contacts.address_and_contact import load_address_and_contact +from frappe.utils import cint, formatdate, get_timestamp, today +from frappe.utils.nestedset import NestedSet +from past.builtins import cmp + from erpnext.accounts.doctype.account.account import get_account_currency from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_charges + class Company(NestedSet): nsm_parent_field = 'parent_company' @@ -479,8 +480,9 @@ def update_company_current_month_sales(company): def update_company_monthly_sales(company): '''Cache past year monthly sales of every company based on sales invoices''' - from frappe.utils.goal import get_monthly_results import json + + from frappe.utils.goal import get_monthly_results filter_str = "company = {0} and status != 'Draft' and docstatus=1".format(frappe.db.escape(company)) month_to_value_dict = get_monthly_results("Sales Invoice", "base_grand_total", "posting_date", filter_str, "sum") diff --git a/erpnext/setup/doctype/company/company_dashboard.py b/erpnext/setup/doctype/company/company_dashboard.py index 2d760284e5a..3afea098a0f 100644 --- a/erpnext/setup/doctype/company/company_dashboard.py +++ b/erpnext/setup/doctype/company/company_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'graph': True, diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py index 1b7fd4fd5c8..abc4689a20e 100644 --- a/erpnext/setup/doctype/company/test_company.py +++ b/erpnext/setup/doctype/company/test_company.py @@ -2,12 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -import unittest import json +import unittest + +import frappe from frappe import _ from frappe.utils import random_string -from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import get_charts_for_country + +from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import ( + get_charts_for_country, +) test_ignore = ["Account", "Cost Center", "Payment Terms Template", "Salary Component", "Warehouse"] test_dependencies = ["Fiscal Year"] diff --git a/erpnext/setup/doctype/currency_exchange/currency_exchange.py b/erpnext/setup/doctype/currency_exchange/currency_exchange.py index 6480f60f59c..0b86e293778 100644 --- a/erpnext/setup/doctype/currency_exchange/currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/currency_exchange.py @@ -4,10 +4,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe import _, throw from frappe.model.document import Document -from frappe.utils import get_datetime_str, formatdate, nowdate, cint +from frappe.utils import cint, formatdate, get_datetime_str, nowdate + class CurrencyExchange(Document): def autoname(self): diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py index 4ff2dd7e0e9..1e159c96c59 100644 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py @@ -1,10 +1,13 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, unittest -from frappe.utils import flt + +import unittest + +import frappe +from frappe.utils import cint, flt + from erpnext.setup.utils import get_exchange_rate -from frappe.utils import cint test_records = frappe.get_test_records('Currency Exchange') diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index c06669b16b4..6e72810c561 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ - - from frappe.utils.nestedset import NestedSet, get_root_of + + class CustomerGroup(NestedSet): nsm_parent_field = 'parent_customer_group' def validate(self): diff --git a/erpnext/setup/doctype/customer_group/test_customer_group.py b/erpnext/setup/doctype/customer_group/test_customer_group.py index ec90b376cdc..e04b79b8f39 100644 --- a/erpnext/setup/doctype/customer_group/test_customer_group.py +++ b/erpnext/setup/doctype/customer_group/test_customer_group.py @@ -7,4 +7,5 @@ test_ignore = ["Price List"] import frappe + test_records = frappe.get_test_records('Customer Group') diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 217829f1269..4e9a8ccad87 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -2,19 +2,34 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe import _ -from frappe.utils import (fmt_money, formatdate, format_time, now_datetime, - get_url_to_form, get_url_to_list, flt, get_link_to_report, add_to_date, today) + from datetime import timedelta -from dateutil.relativedelta import relativedelta -from frappe.core.doctype.user.user import STANDARD_USERS + +import frappe import frappe.desk.notifications +from dateutil.relativedelta import relativedelta +from frappe import _ +from frappe.core.doctype.user.user import STANDARD_USERS +from frappe.utils import ( + add_to_date, + flt, + fmt_money, + format_time, + formatdate, + get_link_to_report, + get_url_to_form, + get_url_to_list, + now_datetime, + today, +) + from erpnext.accounts.utils import get_balance_on, get_count_on, get_fiscal_year user_specific_content = ["calendar_events", "todo_list"] from frappe.model.document import Document + + class EmailDigest(Document): def __init__(self, *args, **kwargs): super(EmailDigest, self).__init__(*args, **kwargs) diff --git a/erpnext/setup/doctype/email_digest/quotes.py b/erpnext/setup/doctype/email_digest/quotes.py index 5451ee1daff..c77fe824ac9 100644 --- a/erpnext/setup/doctype/email_digest/quotes.py +++ b/erpnext/setup/doctype/email_digest/quotes.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + import random + def get_random_quote(): quotes = [ ("Start by doing what's necessary; then do what's possible; and suddenly you are doing the impossible.", "Francis of Assisi"), diff --git a/erpnext/setup/doctype/email_digest/test_email_digest.py b/erpnext/setup/doctype/email_digest/test_email_digest.py index afe693afd2f..b3d0ce325b8 100644 --- a/erpnext/setup/doctype/email_digest/test_email_digest.py +++ b/erpnext/setup/doctype/email_digest/test_email_digest.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Email Digest') diff --git a/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py b/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py index 968c51c345b..5c8d695b6e5 100644 --- a/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py +++ b/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class EmailDigestRecipient(Document): pass diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index a0ba1efb5b4..66d3b9ee480 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + """Global Defaults""" import frappe import frappe.defaults -from frappe.utils import cint from frappe.custom.doctype.property_setter.property_setter import make_property_setter +from frappe.utils import cint keydict = { # "key in defaults": "key in Global Defaults" @@ -22,6 +23,7 @@ keydict = { from frappe.model.document import Document + class GlobalDefaults(Document): def on_update(self): diff --git a/erpnext/setup/doctype/global_defaults/test_global_defaults.py b/erpnext/setup/doctype/global_defaults/test_global_defaults.py index 0495af7b414..70a7c08c111 100644 --- a/erpnext/setup/doctype/global_defaults/test_global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/test_global_defaults.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestGlobalDefaults(unittest.TestCase): pass diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 5fcad00af16..0943b22c028 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -2,19 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import copy + +import frappe from frappe import _ -from frappe.utils import nowdate, cint, cstr +from frappe.utils import cint from frappe.utils.nestedset import NestedSet -from frappe.website.website_generator import WebsiteGenerator from frappe.website.render import clear_cache -from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow -from erpnext.shopping_cart.product_info import set_product_info_for_website -from erpnext.utilities.product import get_qty_in_stock +from frappe.website.website_generator import WebsiteGenerator from six.moves.urllib.parse import quote -from erpnext.shopping_cart.product_query import ProductQuery -from erpnext.shopping_cart.filters import ProductFiltersBuilder + +from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder + class ItemGroup(NestedSet, WebsiteGenerator): nsm_parent_field = 'parent_item_group' @@ -69,34 +69,15 @@ class ItemGroup(NestedSet, WebsiteGenerator): frappe.throw(frappe._("An item exists with same name ({0}), please change the item group name or rename the item").format(self.name), frappe.NameError) def get_context(self, context): - context.show_search=True - context.page_length = cint(frappe.db.get_single_value('Products Settings', 'products_per_page')) or 6 + context.show_search = True + context.body_class = "product-page" + context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6 context.search_link = '/product_search' - if frappe.form_dict: - search = frappe.form_dict.search - field_filters = frappe.parse_json(frappe.form_dict.field_filters) - attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters) - start = frappe.parse_json(frappe.form_dict.start) - else: - search = None - attribute_filters = None - field_filters = {} - start = 0 - - if not field_filters: - field_filters = {} - - # Ensure the query remains within current item group & sub group - field_filters['item_group'] = [ig[0] for ig in get_child_groups(self.name)] - - engine = ProductQuery() - context.items = engine.query(attribute_filters, field_filters, search, start, item_group=self.name) - filter_engine = ProductFiltersBuilder(self.name) context.field_filters = filter_engine.get_field_filters() - context.attribute_filters = filter_engine.get_attribute_fitlers() + context.attribute_filters = filter_engine.get_attribute_filters() context.update({ "parents": get_parent_item_groups(self.parent_item_group), @@ -116,106 +97,40 @@ class ItemGroup(NestedSet, WebsiteGenerator): values[f"slide_{index + 1}_image"] = slide.image values[f"slide_{index + 1}_title"] = slide.heading values[f"slide_{index + 1}_subtitle"] = slide.description - values[f"slide_{index + 1}_theme"] = slide.theme or "Light" - values[f"slide_{index + 1}_content_align"] = slide.content_align or "Centre" - values[f"slide_{index + 1}_primary_action_label"] = slide.label + values[f"slide_{index + 1}_theme"] = slide.get("theme") or "Light" + values[f"slide_{index + 1}_content_align"] = slide.get("content_align") or "Centre" values[f"slide_{index + 1}_primary_action"] = slide.url context.slideshow = values - context.breadcrumbs = 0 + context.no_breadcrumbs = False context.title = self.website_title or self.name + context.name = self.name + context.item_group_name = self.item_group_name return context def delete_child_item_groups_key(self): frappe.cache().hdel("child_item_groups", self.name) -@frappe.whitelist(allow_guest=True) -def get_product_list_for_group(product_group=None, start=0, limit=10, search=None): - if product_group: - item_group = frappe.get_cached_doc('Item Group', product_group) - if item_group.is_group: - # return child item groups if the type is of "Is Group" - return get_child_groups_for_list_in_html(item_group, start, limit, search) +def get_child_groups_for_website(item_group_name, immediate=False): + """Returns child item groups *excluding* passed group.""" + item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1) + filters = { + "lft": [">", item_group.lft], + "rgt": ["<", item_group.rgt], + "show_in_website": 1 + } - child_groups = ", ".join(frappe.db.escape(i[0]) for i in get_child_groups(product_group)) + if immediate: + filters["parent_item_group"] = item_group_name - # base query - query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group, - I.description, I.web_long_description as website_description, I.is_stock_item, - case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock, I.website_warehouse, - I.has_batch_no - from `tabItem` I - left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse - where I.show_in_website = 1 - and I.disabled = 0 - and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s) - and (I.variant_of = '' or I.variant_of is null) - and (I.item_group in ({child_groups}) - or I.name in (select parent from `tabWebsite Item Group` where item_group in ({child_groups}))) - """.format(child_groups=child_groups) - # search term condition - if search: - query += """ and (I.web_long_description like %(search)s - or I.item_name like %(search)s - or I.name like %(search)s)""" - search = "%" + cstr(search) + "%" - - query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit)) - - data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1) - data = adjust_qty_for_expired_items(data) - - if cint(frappe.db.get_single_value("Shopping Cart Settings", "enabled")): - for item in data: - set_product_info_for_website(item) - - return data - -def get_child_groups_for_list_in_html(item_group, start, limit, search): - search_filters = None - if search_filters: - search_filters = [ - dict(name = ('like', '%{}%'.format(search))), - dict(description = ('like', '%{}%'.format(search))) - ] - data = frappe.db.get_all('Item Group', - fields = ['name', 'route', 'description', 'image'], - filters = dict( - show_in_website = 1, - parent_item_group = item_group.name, - lft = ('>', item_group.lft), - rgt = ('<', item_group.rgt), - ), - or_filters = search_filters, - order_by = 'weightage desc, name asc', - start = start, - limit = limit + return frappe.get_all( + "Item Group", + filters=filters, + fields=["name", "route"] ) - return data - -def adjust_qty_for_expired_items(data): - adjusted_data = [] - - for item in data: - if item.get('has_batch_no') and item.get('website_warehouse'): - stock_qty_dict = get_qty_in_stock( - item.get('name'), 'website_warehouse', item.get('website_warehouse')) - qty = stock_qty_dict.stock_qty[0][0] if stock_qty_dict.stock_qty else 0 - item['in_stock'] = 1 if qty else 0 - adjusted_data.append(item) - - return adjusted_data - - -def get_child_groups(item_group_name): - item_group = frappe.get_doc("Item Group", item_group_name) - return frappe.db.sql("""select name - from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s - and show_in_website = 1""", {"lft": item_group.lft, "rgt": item_group.rgt}) - def get_child_item_groups(item_group_name): item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1) @@ -231,31 +146,33 @@ def get_item_for_list_in_html(context): if (context.get("website_image") or "").startswith("files/"): context["website_image"] = "/" + quote(context["website_image"]) - context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings', + context["show_availability_status"] = cint(frappe.db.get_single_value('E Commerce Settings', 'show_availability_status')) products_template = 'templates/includes/products_as_list.html' return frappe.get_template(products_template).render(context) -def get_group_item_count(item_group): - child_groups = ", ".join('"' + i[0] + '"' for i in get_child_groups(item_group)) - return frappe.db.sql("""select count(*) from `tabItem` - where docstatus = 0 and show_in_website = 1 - and (item_group in (%s) - or name in (select parent from `tabWebsite Item Group` - where item_group in (%s))) """ % (child_groups, child_groups))[0][0] +def get_parent_item_groups(item_group_name, from_item=False): + base_nav_page = {"name": _("Shop by Category"), "route":"/shop-by-category"} + + if from_item and frappe.request.environ.get("HTTP_REFERER"): + # base page after 'Home' will vary on Item page + last_page = frappe.request.environ["HTTP_REFERER"].split('/')[-1] + if last_page and last_page in ("shop-by-category", "all-products"): + base_nav_page_title = " ".join(last_page.split("-")).title() + base_nav_page = {"name": _(base_nav_page_title), "route":"/"+last_page} -def get_parent_item_groups(item_group_name): base_parents = [ - {"name": frappe._("Home"), "route":"/"}, - {"name": frappe._("All Products"), "route":"/all-products"}, + {"name": _("Home"), "route":"/"}, + base_nav_page, ] + if not item_group_name: return base_parents - item_group = frappe.get_doc("Item Group", item_group_name) + item_group = frappe.db.get_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1) parent_groups = frappe.db.sql("""select name, route from `tabItem Group` where lft <= %s and rgt >= %s and show_in_website=1 diff --git a/erpnext/setup/doctype/item_group/test_item_group.py b/erpnext/setup/doctype/item_group/test_item_group.py index 745b13a5bed..a816f391c62 100644 --- a/erpnext/setup/doctype/item_group/test_item_group.py +++ b/erpnext/setup/doctype/item_group/test_item_group.py @@ -2,10 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import print_function, unicode_literals + import unittest + import frappe -from frappe.utils.nestedset import NestedSetRecursionError, NestedSetMultipleRootsError, \ - NestedSetChildExistsError, NestedSetInvalidMergeError, rebuild_tree, get_ancestors_of +from frappe.utils.nestedset import ( + NestedSetChildExistsError, + NestedSetInvalidMergeError, + NestedSetMultipleRootsError, + NestedSetRecursionError, + get_ancestors_of, + rebuild_tree, +) test_records = frappe.get_test_records('Item Group') diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py index c1f9433b411..005cfec769a 100644 --- a/erpnext/setup/doctype/naming_series/naming_series.py +++ b/erpnext/setup/doctype/naming_series/naming_series.py @@ -2,15 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe - -from frappe.utils import cstr, cint -from frappe import msgprint, throw, _ - +from frappe import _, msgprint, throw +from frappe.core.doctype.doctype.doctype import validate_series from frappe.model.document import Document from frappe.model.naming import parse_naming_series from frappe.permissions import get_doctypes_with_read -from frappe.core.doctype.doctype.doctype import validate_series +from frappe.utils import cint, cstr + class NamingSeriesNotSetError(frappe.ValidationError): pass @@ -79,7 +79,8 @@ class NamingSeries(Document): options = self.scrub_options_list(ol) # validate names - for i in options: self.validate_series_name(i) + for i in options: + self.validate_series_name(i) if options and self.user_must_always_select: options = [''] + options @@ -138,7 +139,7 @@ class NamingSeries(Document): def validate_series_name(self, n): import re - if not re.match("^[\w\- /.#{}]*$", n, re.UNICODE): + if not re.match(r"^[\w\- \/.#{}]+$", n, re.UNICODE): throw(_('Special Characters except "-", "#", ".", "/", "{" and "}" not allowed in naming series')) @frappe.whitelist() diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py index 96e60936a4b..8424c7fe938 100644 --- a/erpnext/setup/doctype/party_type/party_type.py +++ b/erpnext/setup/doctype/party_type/party_type.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class PartyType(Document): pass diff --git a/erpnext/setup/doctype/party_type/test_party_type.py b/erpnext/setup/doctype/party_type/test_party_type.py index 079fe2fe3b7..e5f2908eb46 100644 --- a/erpnext/setup/doctype/party_type/test_party_type.py +++ b/erpnext/setup/doctype/party_type/test_party_type.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Party Type') diff --git a/erpnext/setup/doctype/print_heading/print_heading.py b/erpnext/setup/doctype/print_heading/print_heading.py index 3d5cd2d6f9e..cf25638608b 100644 --- a/erpnext/setup/doctype/print_heading/print_heading.py +++ b/erpnext/setup/doctype/print_heading/print_heading.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PrintHeading(Document): pass diff --git a/erpnext/setup/doctype/print_heading/test_print_heading.py b/erpnext/setup/doctype/print_heading/test_print_heading.py index b2be2e375e4..06f801a654e 100644 --- a/erpnext/setup/doctype/print_heading/test_print_heading.py +++ b/erpnext/setup/doctype/print_heading/test_print_heading.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Print Heading') diff --git a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py index 42c5a5a54fb..9131cc334a7 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py +++ b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class QuotationLostReason(Document): pass diff --git a/erpnext/setup/doctype/quotation_lost_reason/test_quotation_lost_reason.py b/erpnext/setup/doctype/quotation_lost_reason/test_quotation_lost_reason.py index f6b30b649b5..ab8d61f1ebe 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/test_quotation_lost_reason.py +++ b/erpnext/setup/doctype/quotation_lost_reason/test_quotation_lost_reason.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Quotation Lost Reason') diff --git a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py index 7bb8d02670e..434f24ea925 100644 --- a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py +++ b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QuotationLostReasonDetail(Document): pass diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py index 675f9ca560b..6c741a8fb44 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/sales_partner.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe.contacts.address_and_contact import load_address_and_contact from frappe.utils import cstr, filter_strip_join from frappe.website.website_generator import WebsiteGenerator -from frappe.contacts.address_and_contact import load_address_and_contact + class SalesPartner(WebsiteGenerator): website = frappe._dict( diff --git a/erpnext/setup/doctype/sales_partner/test_sales_partner.py b/erpnext/setup/doctype/sales_partner/test_sales_partner.py index 4548a4e19b5..6ece2390405 100644 --- a/erpnext/setup/doctype/sales_partner/test_sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/test_sales_partner.py @@ -2,8 +2,8 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Sales Partner') test_ignore = ["Item Group"] diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py index 19c2e5b9543..c7cad6bb998 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.py +++ b/erpnext/setup/doctype/sales_person/sales_person.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt from frappe.utils.nestedset import NestedSet, get_root_of + from erpnext import get_default_currency + class SalesPerson(NestedSet): nsm_parent_field = 'parent_sales_person' diff --git a/erpnext/setup/doctype/sales_person/sales_person_dashboard.py b/erpnext/setup/doctype/sales_person/sales_person_dashboard.py index 662008ec8db..61c1ba46d35 100644 --- a/erpnext/setup/doctype/sales_person/sales_person_dashboard.py +++ b/erpnext/setup/doctype/sales_person/sales_person_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/setup/doctype/sales_person/test_sales_person.py b/erpnext/setup/doctype/sales_person/test_sales_person.py index 8313cb45084..497aaad74f8 100644 --- a/erpnext/setup/doctype/sales_person/test_sales_person.py +++ b/erpnext/setup/doctype/sales_person/test_sales_person.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals test_dependencies = ["Employee"] import frappe + test_records = frappe.get_test_records('Sales Person') test_ignore = ["Item Group"] diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.py b/erpnext/setup/doctype/supplier_group/supplier_group.py index 9d84f9097b5..0ca35257926 100644 --- a/erpnext/setup/doctype/supplier_group/supplier_group.py +++ b/erpnext/setup/doctype/supplier_group/supplier_group.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.utils.nestedset import NestedSet, get_root_of + class SupplierGroup(NestedSet): nsm_parent_field = 'parent_supplier_group' diff --git a/erpnext/setup/doctype/supplier_group/test_supplier_group.py b/erpnext/setup/doctype/supplier_group/test_supplier_group.py index 0e3d23d6bd3..b3a636635ec 100644 --- a/erpnext/setup/doctype/supplier_group/test_supplier_group.py +++ b/erpnext/setup/doctype/supplier_group/test_supplier_group.py @@ -4,4 +4,5 @@ from __future__ import unicode_literals import frappe + test_records = frappe.get_test_records('Supplier Group') diff --git a/erpnext/setup/doctype/target_detail/target_detail.py b/erpnext/setup/doctype/target_detail/target_detail.py index 633be45d20b..89cd814f2d1 100644 --- a/erpnext/setup/doctype/target_detail/target_detail.py +++ b/erpnext/setup/doctype/target_detail/target_detail.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class TargetDetail(Document): pass diff --git a/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py b/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py index 5b00ccbdbb3..8c9059f61ef 100644 --- a/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py +++ b/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py @@ -2,15 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + +import json + import frappe from frappe import _, throw -import json from frappe.model.document import Document -from frappe.utils.jinja import validate_template from frappe.utils import cint - +from frappe.utils.jinja import validate_template from six import string_types + class TermsandConditions(Document): def validate(self): if self.terms: diff --git a/erpnext/setup/doctype/terms_and_conditions/test_terms_and_conditions.py b/erpnext/setup/doctype/terms_and_conditions/test_terms_and_conditions.py index 6fea78f46ae..abfa9214d64 100644 --- a/erpnext/setup/doctype/terms_and_conditions/test_terms_and_conditions.py +++ b/erpnext/setup/doctype/terms_and_conditions/test_terms_and_conditions.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Terms and Conditions') diff --git a/erpnext/setup/doctype/territory/territory.py b/erpnext/setup/doctype/territory/territory.py index 7eefe77495c..f61796b9bdf 100644 --- a/erpnext/setup/doctype/territory/territory.py +++ b/erpnext/setup/doctype/territory/territory.py @@ -2,12 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.utils import flt -from frappe import _ +import frappe +from frappe import _ +from frappe.utils import flt from frappe.utils.nestedset import NestedSet, get_root_of + class Territory(NestedSet): nsm_parent_field = 'parent_territory' diff --git a/erpnext/setup/doctype/territory/test_territory.py b/erpnext/setup/doctype/territory/test_territory.py index efe00c5a30b..a3aa866fff3 100644 --- a/erpnext/setup/doctype/territory/test_territory.py +++ b/erpnext/setup/doctype/territory/test_territory.py @@ -2,8 +2,8 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('Territory') test_ignore = ["Item Group"] diff --git a/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py index 933a8c3bed8..aa0f79b4c86 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestTransactionDeletionRecord(unittest.TestCase): def setUp(self): create_company('Dunder Mifflin Paper Co') diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py index 8a491554801..efb038faccc 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -3,11 +3,13 @@ # For license information, please see license.txt from __future__ import unicode_literals -from frappe.utils import cint + import frappe -from frappe.model.document import Document from frappe import _ from frappe.desk.notifications import clear_notifications +from frappe.model.document import Document +from frappe.utils import cint + class TransactionDeletionRecord(Document): def validate(self): diff --git a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py index 2176cb10deb..a113d504538 100644 --- a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py +++ b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class TransactionDeletionRecordItem(Document): pass diff --git a/erpnext/setup/doctype/uom/test_uom.py b/erpnext/setup/doctype/uom/test_uom.py index 330d30358d9..e222c134942 100644 --- a/erpnext/setup/doctype/uom/test_uom.py +++ b/erpnext/setup/doctype/uom/test_uom.py @@ -2,6 +2,6 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe + test_records = frappe.get_test_records('UOM') diff --git a/erpnext/setup/doctype/uom/uom.py b/erpnext/setup/doctype/uom/uom.py index 404b84b1134..f0e97b34e25 100644 --- a/erpnext/setup/doctype/uom/uom.py +++ b/erpnext/setup/doctype/uom/uom.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class UOM(Document): pass diff --git a/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.py b/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.py index 04596efbca6..33795d6b5b2 100644 --- a/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.py +++ b/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestUOMConversionFactor(unittest.TestCase): pass diff --git a/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py b/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py index 3566c537c6c..45342e9fee9 100644 --- a/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py +++ b/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class UOMConversionFactor(Document): pass diff --git a/erpnext/setup/doctype/website_item_group/website_item_group.py b/erpnext/setup/doctype/website_item_group/website_item_group.py index e416b509b98..2f720134484 100644 --- a/erpnext/setup/doctype/website_item_group/website_item_group.py +++ b/erpnext/setup/doctype/website_item_group/website_item_group.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class WebsiteItemGroup(Document): pass diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index bbee74cafb4..cdc83c14620 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -4,16 +4,18 @@ from __future__ import print_function, unicode_literals import frappe -from erpnext.accounts.doctype.cash_flow_mapper.default_cash_flow_mapper import DEFAULT_MAPPERS -from .default_success_action import get_default_success_action from frappe import _ -from frappe.utils import cint -from frappe.installer import update_site_config -from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to from frappe.custom.doctype.custom_field.custom_field import create_custom_field -from erpnext.setup.default_energy_point_rules import get_default_energy_point_rules +from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to +from frappe.installer import update_site_config +from frappe.utils import cint from six import iteritems +from erpnext.accounts.doctype.cash_flow_mapper.default_cash_flow_mapper import DEFAULT_MAPPERS +from erpnext.setup.default_energy_point_rules import get_default_energy_point_rules + +from .default_success_action import get_default_success_action + default_mail_footer = """
    Sent via ERPNext
    """ diff --git a/erpnext/setup/onboarding_slide/welcome_back_to_erpnext!/welcome_back_to_erpnext!.json b/erpnext/setup/onboarding_slide/welcome_back_to_erpnext!/welcome_back_to_erpnext!.json deleted file mode 100644 index f00dc947d2c..00000000000 --- a/erpnext/setup/onboarding_slide/welcome_back_to_erpnext!/welcome_back_to_erpnext!.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "add_more_button": 0, - "app": "ERPNext", - "creation": "2019-12-04 19:21:39.995776", - "docstatus": 0, - "doctype": "Onboarding Slide", - "domains": [], - "help_links": [], - "idx": 0, - "image_src": "", - "is_completed": 0, - "max_count": 3, - "modified": "2019-12-09 17:53:53.849953", - "modified_by": "Administrator", - "name": "Welcome back to ERPNext!", - "owner": "Administrator", - "slide_desc": "

    Let's continue where you left from!

    ", - "slide_fields": [], - "slide_module": "Setup", - "slide_order": 0, - "slide_title": "Welcome back to ERPNext!", - "slide_type": "Continue" -} \ No newline at end of file diff --git a/erpnext/setup/onboarding_slide/welcome_to_erpnext!/welcome_to_erpnext!.json b/erpnext/setup/onboarding_slide/welcome_to_erpnext!/welcome_to_erpnext!.json deleted file mode 100644 index 37eb67b1d7e..00000000000 --- a/erpnext/setup/onboarding_slide/welcome_to_erpnext!/welcome_to_erpnext!.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "add_more_button": 0, - "app": "ERPNext", - "creation": "2019-11-26 17:01:26.671859", - "docstatus": 0, - "doctype": "Onboarding Slide", - "domains": [], - "help_links": [], - "idx": 0, - "image_src": "", - "is_completed": 0, - "max_count": 0, - "modified": "2019-12-22 21:26:28.414597", - "modified_by": "Administrator", - "name": "Welcome to ERPNext!", - "owner": "Administrator", - "slide_desc": "
    Setting up an ERP can be overwhelming. But don't worry, we have got your back! This wizard will help you onboard to ERPNext in a short time!
    ", - "slide_fields": [], - "slide_module": "Setup", - "slide_order": 1, - "slide_title": "Welcome to ERPNext!", - "slide_type": "Information" -} \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/data/dashboard_charts.py b/erpnext/setup/setup_wizard/data/dashboard_charts.py index 9ce64eb9d92..5369bbab356 100644 --- a/erpnext/setup/setup_wizard/data/dashboard_charts.py +++ b/erpnext/setup/setup_wizard/data/dashboard_charts.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals -from frappe import _ -import frappe + import json +import frappe + + def get_company_for_dashboards(): company = frappe.defaults.get_defaults().company if company: diff --git a/erpnext/setup/setup_wizard/data/industry_type.py b/erpnext/setup/setup_wizard/data/industry_type.py index 4fa9f8abb16..2c83a5c721c 100644 --- a/erpnext/setup/setup_wizard/data/industry_type.py +++ b/erpnext/setup/setup_wizard/data/industry_type.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_industry_types(): return [ _('Accounting'), diff --git a/erpnext/setup/setup_wizard/operations/company_setup.py b/erpnext/setup/setup_wizard/operations/company_setup.py index 4833d93c4a7..4fb20dc8712 100644 --- a/erpnext/setup/setup_wizard/operations/company_setup.py +++ b/erpnext/setup/setup_wizard/operations/company_setup.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cstr, getdate + from .default_website import website_maker -from erpnext.accounts.doctype.account.account import RootNotEditable + def create_fiscal_year_and_company(args): if (args.get('fy_start_date')): @@ -34,7 +36,7 @@ def create_fiscal_year_and_company(args): def enable_shopping_cart(args): # Needs price_lists frappe.get_doc({ - "doctype": "Shopping Cart Settings", + "doctype": "E Commerce Settings", "enabled": 1, 'company': args.get('company_name') , 'price_list': frappe.db.get_value("Price List", {"selling": 1}), diff --git a/erpnext/setup/setup_wizard/operations/default_website.py b/erpnext/setup/setup_wizard/operations/default_website.py index 38b5c1470e7..2288ae06746 100644 --- a/erpnext/setup/setup_wizard/operations/default_website.py +++ b/erpnext/setup/setup_wizard/operations/default_website.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe import _ from frappe.utils import nowdate + class website_maker(object): def __init__(self, args): self.args = args diff --git a/erpnext/setup/setup_wizard/operations/defaults_setup.py b/erpnext/setup/setup_wizard/operations/defaults_setup.py index 6dd0fb1403f..3f90f72b608 100644 --- a/erpnext/setup/setup_wizard/operations/defaults_setup.py +++ b/erpnext/setup/setup_wizard/operations/defaults_setup.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cstr, getdate + def set_default_settings(args): # enable default currency frappe.db.set_value("Currency", args.get("currency"), "enabled", 1) diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index 3dcb63867c1..350ef33a0e5 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -3,16 +3,20 @@ from __future__ import unicode_literals -import frappe, os, json +import json +import os +import frappe from frappe import _ +from frappe.desk.doctype.global_search_settings.global_search_settings import ( + update_global_search_doctypes, +) from frappe.desk.page.setup_wizard.setup_wizard import make_records from frappe.utils import cstr, getdate -from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes +from frappe.utils.nestedset import rebuild_tree from erpnext.accounts.doctype.account.account import RootNotEditable from erpnext.regional.address_template.setup import set_up_address_templates -from frappe.utils.nestedset import rebuild_tree default_lead_sources = ["Existing Customer", "Reference", "Advertisement", "Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing", @@ -513,7 +517,7 @@ def create_bank_account(args): pass def update_shopping_cart_settings(args): - shopping_cart = frappe.get_doc("Shopping Cart Settings") + shopping_cart = frappe.get_doc("E Commerce Settings") shopping_cart.update({ "enabled": 1, 'company': args.company_name, diff --git a/erpnext/setup/setup_wizard/operations/sample_data.py b/erpnext/setup/setup_wizard/operations/sample_data.py index c6d9f0851b1..3aef40d3ebb 100644 --- a/erpnext/setup/setup_wizard/operations/sample_data.py +++ b/erpnext/setup/setup_wizard/operations/sample_data.py @@ -3,11 +3,15 @@ from __future__ import unicode_literals +import json +import os +import random + import frappe -from frappe.utils.make_random import add_random_children import frappe.utils -import random, os, json from frappe import _ +from frappe.utils.make_random import add_random_children + def make_sample_data(domains, make_dependent = False): """Create a few opportunities, quotes, material requests, issues, todos, projects diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py index 09b91709642..90384a7da0b 100644 --- a/erpnext/setup/setup_wizard/operations/taxes_setup.py +++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals -import os import json +import os import frappe from frappe import _ diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index f63d2695aa3..ecb07d53b7c 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -6,7 +6,10 @@ from __future__ import unicode_literals import frappe from frappe import _ -from .operations import install_fixtures as fixtures, company_setup, sample_data +from .operations import company_setup +from .operations import install_fixtures as fixtures +from .operations import sample_data + def get_setup_stages(args=None): if frappe.db.sql("select name from tabCompany"): @@ -106,7 +109,7 @@ def fin(args): def make_sample_data(domains): try: sample_data.make_sample_data(domains) - except: + except Exception: # clear message if frappe.message_log: frappe.message_log.pop() diff --git a/erpnext/setup/setup_wizard/utils.py b/erpnext/setup/setup_wizard/utils.py index 4223f000a6b..30b88aecbcd 100644 --- a/erpnext/setup/setup_wizard/utils.py +++ b/erpnext/setup/setup_wizard/utils.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals -import json, os + +import json +import os from frappe.desk.page.setup_wizard.setup_wizard import setup_complete -from erpnext.setup.setup_wizard import setup_wizard + def complete(): with open(os.path.join(os.path.dirname(__file__), diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 27237bf2cbe..c7746a64eb4 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, add_days -from frappe.utils import get_datetime_str, nowdate +from frappe.utils import add_days, flt, get_datetime_str, nowdate + from erpnext import get_default_company + def get_root_of(doctype): """Get root element of a DocType with a tree structure""" result = frappe.db.sql_list("""select name from `tab%s` @@ -109,7 +111,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No value = response.json()["result"] cache.setex(name=key, time=21600, value=flt(value)) return flt(value) - except: + except Exception: frappe.log_error(title="Get Exchange Rate") frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date)) return 0.0 diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json deleted file mode 100644 index 7a4bb20136f..00000000000 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "actions": [], - "creation": "2013-06-19 15:57:32", - "description": "Default settings for Shopping Cart", - "doctype": "DocType", - "document_type": "System", - "engine": "InnoDB", - "field_order": [ - "enabled", - "store_page_docs", - "display_settings", - "show_attachments", - "show_price", - "show_stock_availability", - "enable_variants", - "column_break_7", - "show_contact_us_button", - "show_quantity_in_website", - "show_apply_coupon_code_in_website", - "allow_items_not_in_stock", - "section_break_2", - "company", - "price_list", - "column_break_4", - "default_customer_group", - "quotation_series", - "section_break_8", - "enable_checkout", - "save_quotations_as_draft", - "column_break_11", - "payment_gateway_account", - "payment_success_url" - ], - "fields": [ - { - "default": "0", - "fieldname": "enabled", - "fieldtype": "Check", - "in_list_view": 1, - "label": "Enable Shopping Cart" - }, - { - "fieldname": "display_settings", - "fieldtype": "Section Break", - "label": "Display Settings" - }, - { - "default": "0", - "fieldname": "show_attachments", - "fieldtype": "Check", - "label": "Show Public Attachments" - }, - { - "default": "0", - "fieldname": "show_price", - "fieldtype": "Check", - "label": "Show Price" - }, - { - "default": "0", - "fieldname": "show_stock_availability", - "fieldtype": "Check", - "label": "Show Stock Availability" - }, - { - "default": "0", - "fieldname": "show_contact_us_button", - "fieldtype": "Check", - "label": "Show Contact Us Button" - }, - { - "default": "0", - "depends_on": "show_stock_availability", - "fieldname": "show_quantity_in_website", - "fieldtype": "Check", - "label": "Show Stock Quantity" - }, - { - "default": "0", - "fieldname": "show_apply_coupon_code_in_website", - "fieldtype": "Check", - "label": "Show Apply Coupon Code" - }, - { - "default": "0", - "fieldname": "allow_items_not_in_stock", - "fieldtype": "Check", - "label": "Allow items not in stock to be added to cart" - }, - { - "depends_on": "enabled", - "fieldname": "section_break_2", - "fieldtype": "Section Break" - }, - { - "fieldname": "company", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Company", - "mandatory_depends_on": "eval: doc.enabled === 1", - "options": "Company", - "remember_last_selected_value": 1 - }, - { - "description": "Prices will not be shown if Price List is not set", - "fieldname": "price_list", - "fieldtype": "Link", - "label": "Price List", - "mandatory_depends_on": "eval: doc.enabled === 1", - "options": "Price List" - }, - { - "fieldname": "column_break_4", - "fieldtype": "Column Break" - }, - { - "fieldname": "default_customer_group", - "fieldtype": "Link", - "ignore_user_permissions": 1, - "label": "Default Customer Group", - "mandatory_depends_on": "eval: doc.enabled === 1", - "options": "Customer Group" - }, - { - "fieldname": "quotation_series", - "fieldtype": "Select", - "label": "Quotation Series", - "mandatory_depends_on": "eval: doc.enabled === 1" - }, - { - "collapsible": 1, - "collapsible_depends_on": "eval:doc.enable_checkout", - "depends_on": "enabled", - "fieldname": "section_break_8", - "fieldtype": "Section Break", - "label": "Checkout Settings" - }, - { - "default": "0", - "fieldname": "enable_checkout", - "fieldtype": "Check", - "label": "Enable Checkout" - }, - { - "default": "Orders", - "depends_on": "enable_checkout", - "description": "After payment completion redirect user to selected page.", - "fieldname": "payment_success_url", - "fieldtype": "Select", - "label": "Payment Success Url", - "mandatory_depends_on": "enable_checkout", - "options": "\nOrders\nInvoices\nMy Account" - }, - { - "fieldname": "column_break_11", - "fieldtype": "Column Break" - }, - { - "depends_on": "enable_checkout", - "fieldname": "payment_gateway_account", - "fieldtype": "Link", - "label": "Payment Gateway Account", - "mandatory_depends_on": "enable_checkout", - "options": "Payment Gateway Account" - }, - { - "fieldname": "column_break_7", - "fieldtype": "Column Break" - }, - { - "default": "0", - "fieldname": "enable_variants", - "fieldtype": "Check", - "label": "Enable Variants" - }, - { - "default": "0", - "depends_on": "eval: doc.enable_checkout == 0", - "fieldname": "save_quotations_as_draft", - "fieldtype": "Check", - "label": "Save Quotations as Draft" - }, - { - "depends_on": "doc.enabled", - "fieldname": "store_page_docs", - "fieldtype": "HTML" - } - ], - "icon": "fa fa-shopping-cart", - "idx": 1, - "issingle": 1, - "links": [], - "modified": "2021-03-02 17:34:57.642565", - "modified_by": "Administrator", - "module": "Shopping Cart", - "name": "Shopping Cart Settings", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "email": 1, - "print": 1, - "read": 1, - "role": "Website Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "ASC", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/shopping_cart/filters.py b/erpnext/shopping_cart/filters.py deleted file mode 100644 index 7dfa09e2d62..00000000000 --- a/erpnext/shopping_cart/filters.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe import _dict - -class ProductFiltersBuilder: - def __init__(self, item_group=None): - if not item_group or item_group == "Products Settings": - self.doc = frappe.get_doc("Products Settings") - else: - self.doc = frappe.get_doc("Item Group", item_group) - - self.item_group = item_group - - def get_field_filters(self): - filter_fields = [row.fieldname for row in self.doc.filter_fields] - - meta = frappe.get_meta('Item') - fields = [df for df in meta.fields if df.fieldname in filter_fields] - - filter_data = [] - for df in fields: - filters, or_filters = {}, [] - if df.fieldtype == "Link": - if self.item_group: - or_filters.extend([ - ["item_group", "=", self.item_group], - ["Website Item Group", "item_group", "=", self.item_group] - ]) - - values = frappe.get_all("Item", fields=[df.fieldname], filters=filters, or_filters=or_filters, distinct="True", pluck=df.fieldname) - else: - doctype = df.get_link_doctype() - - # apply enable/disable/show_in_website filter - meta = frappe.get_meta(doctype) - - if meta.has_field('enabled'): - filters['enabled'] = 1 - if meta.has_field('disabled'): - filters['disabled'] = 0 - if meta.has_field('show_in_website'): - filters['show_in_website'] = 1 - - values = [d.name for d in frappe.get_all(doctype, filters)] - - # Remove None - if None in values: - values.remove(None) - - if values: - filter_data.append([df, values]) - - return filter_data - - def get_attribute_fitlers(self): - attributes = [row.attribute for row in self.doc.filter_attributes] - attribute_docs = [ - frappe.get_doc('Item Attribute', attribute) for attribute in attributes - ] - - valid_attributes = [] - - for attr_doc in attribute_docs: - selected_attributes = [] - for attr in attr_doc.item_attribute_values: - or_filters = [] - filters= [ - ["Item Variant Attribute", "attribute", "=", attr.parent], - ["Item Variant Attribute", "attribute_value", "=", attr.attribute_value] - ] - if self.item_group: - or_filters.extend([ - ["item_group", "=", self.item_group], - ["Website Item Group", "item_group", "=", self.item_group] - ]) - - if frappe.db.get_all("Item", filters, or_filters=or_filters, limit=1): - selected_attributes.append(attr) - - if selected_attributes: - valid_attributes.append( - _dict( - item_attribute_values=selected_attributes, - name=attr_doc.name - ) - ) - - return valid_attributes diff --git a/erpnext/shopping_cart/product_query.py b/erpnext/shopping_cart/product_query.py deleted file mode 100644 index 6c92d967d0c..00000000000 --- a/erpnext/shopping_cart/product_query.py +++ /dev/null @@ -1,159 +0,0 @@ -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe -from erpnext.shopping_cart.product_info import get_product_info_for_website - -class ProductQuery: - """Query engine for product listing - - Attributes: - cart_settings (Document): Settings for Cart - fields (list): Fields to fetch in query - filters (TYPE): Description - or_filters (list): Description - page_length (Int): Length of page for the query - settings (Document): Products Settings DocType - filters (list) - or_filters (list) - """ - - def __init__(self): - self.settings = frappe.get_doc("Products Settings") - self.cart_settings = frappe.get_doc("Shopping Cart Settings") - self.page_length = self.settings.products_per_page or 20 - self.fields = ['name', 'item_name', 'item_code', 'website_image', 'variant_of', 'has_variants', - 'item_group', 'image', 'web_long_description', 'description', 'route', 'weightage'] - self.filters = [] - self.or_filters = [['show_in_website', '=', 1]] - if not self.settings.get('hide_variants'): - self.or_filters.append(['show_variant_in_website', '=', 1]) - - def query(self, attributes=None, fields=None, search_term=None, start=0, item_group=None): - """Summary - - Args: - attributes (dict, optional): Item Attribute filters - fields (dict, optional): Field level filters - search_term (str, optional): Search term to lookup - start (int, optional): Page start - - Returns: - list: List of results with set fields - """ - if fields: self.build_fields_filters(fields) - if search_term: self.build_search_filters(search_term) - - result = [] - website_item_groups = [] - - # if from item group page consider website item group table - if item_group: - website_item_groups = frappe.db.get_all( - "Item", - fields=self.fields + ["`tabWebsite Item Group`.parent as wig_parent"], - filters=[["Website Item Group", "item_group", "=", item_group]] - ) - - if attributes: - all_items = [] - for attribute, values in attributes.items(): - if not isinstance(values, list): - values = [values] - - items = frappe.get_all( - "Item", - fields=self.fields, - filters=[ - *self.filters, - ["Item Variant Attribute", "attribute", "=", attribute], - ["Item Variant Attribute", "attribute_value", "in", values], - ], - or_filters=self.or_filters, - start=start, - limit=self.page_length, - order_by="weightage desc" - ) - - items_dict = {item.name: item for item in items} - - all_items.append(set(items_dict.keys())) - - result = [items_dict.get(item) for item in list(set.intersection(*all_items))] - else: - result = frappe.get_all( - "Item", - fields=self.fields, - filters=self.filters, - or_filters=self.or_filters, - start=start, - limit=self.page_length, - order_by="weightage desc" - ) - - # Combine results having context of website item groups into item results - if item_group and website_item_groups: - items_list = {row.name for row in result} - for row in website_item_groups: - if row.wig_parent not in items_list: - result.append(row) - - result = sorted(result, key=lambda x: x.get("weightage"), reverse=True) - - for item in result: - product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get('product_info') - if product_info: - item.formatted_price = (product_info.get('price') or {}).get('formatted_price') - - return result - - def build_fields_filters(self, filters): - """Build filters for field values - - Args: - filters (dict): Filters - """ - for field, values in filters.items(): - if not values: - continue - - # handle multiselect fields in filter addition - meta = frappe.get_meta('Item', cached=True) - df = meta.get_field(field) - if df.fieldtype == 'Table MultiSelect': - child_doctype = df.options - child_meta = frappe.get_meta(child_doctype, cached=True) - fields = child_meta.get("fields") - if fields: - self.filters.append([child_doctype, fields[0].fieldname, 'IN', values]) - elif isinstance(values, list): - # If value is a list use `IN` query - self.filters.append([field, 'IN', values]) - else: - # `=` will be faster than `IN` for most cases - self.filters.append([field, '=', values]) - - def build_search_filters(self, search_term): - """Query search term in specified fields - - Args: - search_term (str): Search candidate - """ - # Default fields to search from - default_fields = {'name', 'item_name', 'description', 'item_group'} - - # Get meta search fields - meta = frappe.get_meta("Item") - meta_fields = set(meta.get_search_fields()) - - # Join the meta fields and default fields set - search_fields = default_fields.union(meta_fields) - try: - if frappe.db.count('Item', cache=True) > 50000: - search_fields.remove('description') - except KeyError: - pass - - # Build or filters for query - search = '%{}%'.format(search_term) - self.or_filters += [[field, 'like', search] for field in search_fields] diff --git a/erpnext/startup/__init__.py b/erpnext/startup/__init__.py index deef4ba4d68..3aa52979134 100644 --- a/erpnext/startup/__init__.py +++ b/erpnext/startup/__init__.py @@ -19,7 +19,6 @@ # default settings that can be made for a user. from __future__ import unicode_literals - product_name = "ERPNext" user_defaults = { "Company": "company", diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 2b80fb8dfa1..bb76f5a6f97 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -3,9 +3,11 @@ from __future__ import unicode_literals + import frappe from frappe.utils import cint + def boot_session(bootinfo): """boot session - send website info if guest""" diff --git a/erpnext/startup/filters.py b/erpnext/startup/filters.py index 98210165dfa..c0ccf54d5f6 100644 --- a/erpnext/startup/filters.py +++ b/erpnext/startup/filters.py @@ -1,5 +1,5 @@ -import frappe + def get_filters_config(): filters_config = { diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index a89435d4866..60e67f8f580 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -1,8 +1,10 @@ -from __future__ import unicode_literals, print_function +from __future__ import print_function, unicode_literals + import frappe from frappe.utils import cint + def get_leaderboards(): leaderboards = { "Customer": { diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py index 8e880dc42e0..01bb344d15b 100644 --- a/erpnext/startup/notifications.py +++ b/erpnext/startup/notifications.py @@ -2,8 +2,10 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe + def get_notification_config(): notifications = { "for_doctype": { diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index 283f7d5fdaf..575aa0fa5d0 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import frappe from frappe import _ diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py index 45e662807a0..df6b632d251 100644 --- a/erpnext/stock/dashboard/item_dashboard.py +++ b/erpnext/stock/dashboard/item_dashboard.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals import frappe from frappe.model.db_query import DatabaseQuery -from frappe.utils import flt, cint +from frappe.utils import cint, flt + @frappe.whitelist() def get_data(item_code=None, warehouse=None, item_group=None, diff --git a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py index 70b030e48f2..5d8b703aa5e 100644 --- a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py +++ b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py @@ -2,10 +2,11 @@ from __future__ import unicode_literals import frappe from frappe.model.db_query import DatabaseQuery -from frappe.utils import nowdate -from frappe.utils import flt +from frappe.utils import flt, nowdate + from erpnext.stock.utils import get_stock_balance + @frappe.whitelist() def get_data(item_code=None, warehouse=None, parent_warehouse=None, company=None, start=0, sort_by="stock_capacity", sort_order="desc"): diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py index 2258532c6fe..1753002a819 100644 --- a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -2,11 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json + +import frappe from frappe import _ from frappe.utils.dashboard import cache_source + from erpnext.stock.utils import get_stock_value_from_bin + @frappe.whitelist() @cache_source def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index b37ae3f4f61..76db581a063 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -2,15 +2,16 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -from six import text_type + import frappe from frappe import _ from frappe.model.document import Document from frappe.model.naming import make_autoname, revert_series_if_last -from frappe.utils import flt, cint, get_link_to_form -from frappe.utils.jinja import render_template +from frappe.utils import cint, flt, get_link_to_form from frappe.utils.data import add_days -from six import string_types +from frappe.utils.jinja import render_template +from six import text_type + class UnableToSelectBatchError(frappe.ValidationError): pass diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index a85a0222b55..79989307efc 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -2,15 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -from frappe.exceptions import ValidationError import unittest -from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no +import frappe +from frappe.exceptions import ValidationError from frappe.utils import cint, flt + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.stock.doctype.batch.batch import UnableToSelectBatchError, get_batch_no, get_batch_qty from erpnext.stock.get_item_details import get_item_details + class TestBatch(unittest.TestCase): def test_item_has_batch_enabled(self): self.assertRaises(ValidationError, frappe.get_doc({ diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 43642013ce6..5fbc2d8dee1 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -2,10 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe.utils import flt, nowdate -import frappe.defaults from frappe.model.document import Document +from frappe.utils import flt, nowdate + class Bin(Document): def before_save(self): diff --git a/erpnext/stock/doctype/bin/test_bin.py b/erpnext/stock/doctype/bin/test_bin.py index fb32ce21407..f0dbe8c0dd8 100644 --- a/erpnext/stock/doctype/bin/test_bin.py +++ b/erpnext/stock/doctype/bin/test_bin.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Bin') diff --git a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py index b0b3e6afbf9..d484301572b 100644 --- a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py +++ b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class CustomsTariffNumber(Document): pass diff --git a/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.py b/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.py index d7e03067e8e..7c9807c762b 100644 --- a/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.py +++ b/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestCustomsTariffNumber(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 958189614fd..fdc8763baa6 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -543,6 +543,7 @@ { "collapsible": 1, "collapsible_depends_on": "packed_items", + "depends_on": "packed_items", "fieldname": "packing_list", "fieldtype": "Section Break", "label": "Packing List", @@ -551,6 +552,7 @@ "print_hide": 1 }, { + "depends_on": "packed_items", "fieldname": "packed_items", "fieldtype": "Table", "label": "Packed Items", @@ -1306,7 +1308,7 @@ "idx": 146, "is_submittable": 1, "links": [], - "modified": "2021-08-17 20:15:50.574966", + "modified": "2021-08-27 20:14:40.215231", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index f99a01b8202..5542cd00d4c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -4,17 +4,17 @@ from __future__ import unicode_literals import frappe -import frappe.defaults -from erpnext.controllers.selling_controller import SellingController -from erpnext.stock.doctype.batch.batch import set_batch_nos -from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no from frappe import _ from frappe.contacts.doctype.address.address import get_company_address from frappe.desk.notifications import clear_doctype_notifications from frappe.model.mapper import get_mapped_doc from frappe.model.utils import get_fetch_values from frappe.utils import cint, flt + from erpnext.controllers.accounts_controller import get_taxes_and_charges +from erpnext.controllers.selling_controller import SellingController +from erpnext.stock.doctype.batch.batch import set_batch_nos +from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -331,7 +331,7 @@ class DeliveryNote(SellingController): credit_note_link = frappe.utils.get_link_to_form('Sales Invoice', return_invoice.name) frappe.msgprint(_("Credit Note {0} has been created automatically").format(credit_note_link)) - except: + except Exception: frappe.throw(_("Could not create Credit Note automatically, please uncheck 'Issue Credit Note' and submit again")) def update_billed_amount_based_on_so(so_detail, update_modified=True): @@ -668,8 +668,13 @@ def make_inter_company_purchase_receipt(source_name, target_doc=None): return make_inter_company_transaction("Delivery Note", source_name, target_doc) def make_inter_company_transaction(doctype, source_name, target_doc=None): - from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_transaction, - get_inter_company_details, update_address, update_taxes, set_purchase_references) + from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( + get_inter_company_details, + set_purchase_references, + update_address, + update_taxes, + validate_inter_company_transaction, + ) if doctype == 'Delivery Note': source_doc = frappe.get_doc(doctype, source_name) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py b/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py index 9db5db865f5..31fc708eabd 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'delivery_note', diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index b333a6b57ea..7fda94b269d 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -3,26 +3,40 @@ from __future__ import unicode_literals -import unittest -import frappe + import json -import frappe.defaults -from frappe.utils import nowdate, nowtime, cstr, flt -from erpnext.stock.stock_ledger import get_previous_sle -from erpnext.accounts.utils import get_balance_on -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries -from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice, make_delivery_trip -from erpnext.stock.doctype.stock_entry.test_stock_entry \ - import make_stock_entry, make_serialized_item, get_qty_after_transaction -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoWarehouseError -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \ - import create_stock_reconciliation, set_valuation_method -from erpnext.selling.doctype.sales_order.test_sales_order \ - import make_sales_order, create_dn_against_so, automatically_fetch_payment_terms, compare_payment_schedules +import unittest + +import frappe +from frappe.utils import cstr, flt, nowdate, nowtime + from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse -from erpnext.stock.doctype.item.test_item import make_item +from erpnext.accounts.utils import get_balance_on from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle +from erpnext.selling.doctype.sales_order.test_sales_order import ( + automatically_fetch_payment_terms, + compare_payment_schedules, + create_dn_against_so, + make_sales_order, +) +from erpnext.stock.doctype.delivery_note.delivery_note import ( + make_delivery_trip, + make_sales_invoice, +) +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries +from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError, get_serial_nos +from erpnext.stock.doctype.stock_entry.test_stock_entry import ( + get_qty_after_transaction, + make_serialized_item, + make_stock_entry, +) +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, + set_valuation_method, +) +from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse +from erpnext.stock.stock_ledger import get_previous_sle class TestDeliveryNote(unittest.TestCase): @@ -540,7 +554,10 @@ class TestDeliveryNote(unittest.TestCase): def test_dn_billing_status_case2(self): # SO -> SI and SO -> DN1, DN2 - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice + from erpnext.selling.doctype.sales_order.sales_order import ( + make_delivery_note, + make_sales_invoice, + ) so = make_sales_order() @@ -579,8 +596,10 @@ class TestDeliveryNote(unittest.TestCase): def test_dn_billing_status_case3(self): # SO -> DN1 -> SI and SO -> SI and SO -> DN2 - from erpnext.selling.doctype.sales_order.sales_order \ - import make_delivery_note, make_sales_invoice as make_sales_invoice_from_so + from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note + from erpnext.selling.doctype.sales_order.sales_order import ( + make_sales_invoice as make_sales_invoice_from_so, + ) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) so = make_sales_order() @@ -626,8 +645,8 @@ class TestDeliveryNote(unittest.TestCase): def test_dn_billing_status_case4(self): # SO -> SI -> DN - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note + from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice so = make_sales_order() @@ -777,7 +796,9 @@ class TestDeliveryNote(unittest.TestCase): self.assertTrue("TESTBATCH" in dn.packed_items[0].batch_no, "Batch number not added in packed item") def test_payment_terms_are_fetched_when_creating_sales_invoice(self): - from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.payment_entry.test_payment_entry import ( + create_payment_terms_template, + ) from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice automatically_fetch_payment_terms() diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py index 8bd381a2ed3..693caabfb85 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class DeliveryNoteItem(Document): pass diff --git a/erpnext/stock/doctype/delivery_settings/delivery_settings.py b/erpnext/stock/doctype/delivery_settings/delivery_settings.py index 909efda856f..c25907defeb 100644 --- a/erpnext/stock/doctype/delivery_settings/delivery_settings.py +++ b/erpnext/stock/doctype/delivery_settings/delivery_settings.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class DeliverySettings(Document): pass diff --git a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py index 4395d266287..25c9da16aa8 100644 --- a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py +++ b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestDeliverySettings(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.py b/erpnext/stock/doctype/delivery_stop/delivery_stop.py index 768d1619f65..f94ccb80215 100644 --- a/erpnext/stock/doctype/delivery_stop/delivery_stop.py +++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class DeliveryStop(Document): pass diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index f76bb87efed..fe9818242fe 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -10,8 +10,8 @@ import frappe from frappe import _ from frappe.contacts.doctype.address.address import get_address_display from frappe.model.document import Document -from frappe.utils import cint, get_datetime, get_link_to_form from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, get_datetime, get_link_to_form class DeliveryTrip(Document): diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py index 1e716031751..c9081c908f7 100644 --- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py @@ -5,12 +5,17 @@ from __future__ import unicode_literals import unittest -import erpnext import frappe -from erpnext.stock.doctype.delivery_trip.delivery_trip import get_contact_and_address, notify_customers, make_expense_claim -from erpnext.tests.utils import create_test_contact_and_address from frappe.utils import add_days, flt, now_datetime, nowdate +import erpnext +from erpnext.stock.doctype.delivery_trip.delivery_trip import ( + get_contact_and_address, + make_expense_claim, + notify_customers, +) +from erpnext.tests.utils import create_test_contact_and_address + class TestDeliveryTrip(unittest.TestCase): def setUp(self): diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 2bf749a8152..e346ea87214 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -17,8 +17,6 @@ frappe.ui.form.on("Item", { frm.fields_dict["attributes"].grid.set_column_disp("attribute_value", true); } - // should never check Private - frm.fields_dict["website_image"].df.is_private = 0; if (frm.doc.is_fixed_asset) { frm.trigger("set_asset_naming_series"); } @@ -91,6 +89,29 @@ frappe.ui.form.on("Item", { erpnext.toggle_naming_series(); } + if (!frm.doc.published_in_website) { + frm.add_custom_button(__("Publish in Website"), function() { + frappe.call({ + method: "erpnext.e_commerce.doctype.website_item.website_item.make_website_item", + args: {doc: frm.doc}, + freeze: true, + freeze_message: __("Publishing Item ..."), + callback: function(result) { + frappe.msgprint({ + message: __("Website Item {0} has been created.", + [repl('%(item)s', { + item_encoded: encodeURIComponent(result.message[0]), + item: result.message[1] + })] + ), + title: __("Published"), + indicator: "green" + }); + } + }); + }, __('Actions')); + } + erpnext.item.edit_prices_button(frm); erpnext.item.toggle_attributes(frm); @@ -182,25 +203,8 @@ frappe.ui.form.on("Item", { } }, - copy_from_item_group: function(frm) { - return frm.call({ - doc: frm.doc, - method: "copy_specification_from_item_group" - }); - }, - has_variants: function(frm) { erpnext.item.toggle_attributes(frm); - }, - - show_in_website: function(frm) { - if (frm.doc.default_warehouse && !frm.doc.website_warehouse){ - frm.set_value("website_warehouse", frm.doc.default_warehouse); - } - }, - - set_meta_tags(frm) { - frappe.utils.set_meta_tag(frm.doc.route); } }); @@ -393,13 +397,15 @@ $.extend(erpnext.item, { edit_prices_button: function(frm) { frm.add_custom_button(__("Add / Edit Prices"), function() { frappe.set_route("List", "Item Price", {"item_code": frm.doc.name}); - }, __("View")); + }, __("Actions")); }, - weight_to_validate: function(frm){ - if((frm.doc.nett_weight || frm.doc.gross_weight) && !frm.doc.weight_uom) { - frappe.msgprint(__('Weight is mentioned,\nPlease mention "Weight UOM" too')); - frappe.validated = 0; + weight_to_validate: function(frm) { + if (frm.doc.weight_per_unit && !frm.doc.weight_uom) { + frappe.msgprint({ + message: __("Please mention 'Weight UOM' along with Weight."), + title: __("Note") + }); } }, diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index db5caf91645..3dcb2122c70 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -116,30 +116,14 @@ "customer_code", "default_item_manufacturer", "default_manufacturer_part_no", - "website_section", - "show_in_website", - "show_variant_in_website", - "route", - "weightage", - "slideshow", - "website_image", - "website_image_alt", - "thumbnail", - "cb72", - "website_warehouse", - "website_item_groups", - "set_meta_tags", - "sb72", - "copy_from_item_group", - "website_specifications", - "web_long_description", - "website_content", - "total_projected_qty", "hub_publishing_sb", "publish_in_hub", "hub_category_to_publish", "hub_warehouse", - "synced_with_hub" + "synced_with_hub", + "more_information_section", + "published_in_website", + "total_projected_qty" ], "fields": [ { @@ -869,125 +853,6 @@ "no_copy": 1, "print_hide": 1 }, - { - "collapsible": 1, - "depends_on": "eval:!doc.is_fixed_asset", - "fieldname": "website_section", - "fieldtype": "Section Break", - "label": "Website", - "options": "fa fa-globe" - }, - { - "default": "0", - "depends_on": "eval:!doc.variant_of", - "fieldname": "show_in_website", - "fieldtype": "Check", - "label": "Show in Website", - "search_index": 1 - }, - { - "default": "0", - "depends_on": "variant_of", - "fieldname": "show_variant_in_website", - "fieldtype": "Check", - "label": "Show in Website (Variant)", - "search_index": 1 - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "route", - "fieldtype": "Small Text", - "label": "Route", - "no_copy": 1 - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "description": "Items with higher weightage will be shown higher", - "fieldname": "weightage", - "fieldtype": "Int", - "label": "Weightage" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "description": "Show a slideshow at the top of the page", - "fieldname": "slideshow", - "fieldtype": "Link", - "label": "Slideshow", - "options": "Website Slideshow" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "description": "Item Image (if not slideshow)", - "fieldname": "website_image", - "fieldtype": "Attach", - "label": "Website Image" - }, - { - "fieldname": "thumbnail", - "fieldtype": "Data", - "label": "Thumbnail", - "read_only": 1 - }, - { - "fieldname": "cb72", - "fieldtype": "Column Break" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "description": "Show \"In Stock\" or \"Not in Stock\" based on stock available in this warehouse.", - "fieldname": "website_warehouse", - "fieldtype": "Link", - "ignore_user_permissions": 1, - "label": "Website Warehouse", - "options": "Warehouse" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "description": "List this Item in multiple groups on the website.", - "fieldname": "website_item_groups", - "fieldtype": "Table", - "label": "Website Item Groups", - "options": "Website Item Group" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "set_meta_tags", - "fieldtype": "Button", - "label": "Set Meta Tags" - }, - { - "collapsible": 1, - "collapsible_depends_on": "website_specifications", - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "sb72", - "fieldtype": "Section Break", - "label": "Website Specifications" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "copy_from_item_group", - "fieldtype": "Button", - "label": "Copy From Item Group" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "website_specifications", - "fieldtype": "Table", - "label": "Website Specifications", - "options": "Item Website Specification" - }, - { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "web_long_description", - "fieldtype": "Text Editor", - "label": "Website Description" - }, - { - "description": "You can use any valid Bootstrap 4 markup in this field. It will be shown on your Item Page.", - "fieldname": "website_content", - "fieldtype": "HTML Editor", - "label": "Website Content" - }, { "fieldname": "total_projected_qty", "fieldtype": "Float", @@ -1065,13 +930,20 @@ "read_only": 1 }, { - "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", - "fieldname": "website_image_alt", - "fieldtype": "Data", - "label": "Image Description" + "collapsible": 1, + "fieldname": "more_information_section", + "fieldtype": "Section Break", + "label": "More Information" + }, + { + "default": "0", + "depends_on": "published_in_website", + "fieldname": "published_in_website", + "fieldtype": "Check", + "label": "Published in Website", + "read_only": 1 } ], - "has_web_view": 1, "icon": "fa fa-tag", "idx": 2, "image_field": "image", diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index ca587bfe82c..50f68665a3a 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -1,23 +1,34 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -import itertools -import json -import erpnext -import frappe import copy -from erpnext.controllers.item_variant import (ItemVariantExistsError, - copy_attributes_to_variant, get_variant, make_variant_item_code, validate_item_variant_attributes) -from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for) -from frappe import _, msgprint -from frappe.utils import (cint, cstr, flt, formatdate, getdate, - now_datetime, random_string, strip, get_link_to_form, nowtime) -from frappe.utils.html_utils import clean_html -from frappe.website.doctype.website_slideshow.website_slideshow import \ - get_slideshow +import json -from frappe.website.render import clear_cache -from frappe.website.website_generator import WebsiteGenerator +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import ( + cint, + cstr, + flt, + formatdate, + get_link_to_form, + getdate, + now_datetime, + nowtime, + strip, +) +from frappe.utils.html_utils import clean_html + +import erpnext +from erpnext.controllers.item_variant import ( + ItemVariantExistsError, + copy_attributes_to_variant, + get_variant, + make_variant_item_code, + validate_item_variant_attributes, +) +from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for class DuplicateReorderRows(frappe.ValidationError): @@ -31,18 +42,11 @@ class StockExistsForTemplate(frappe.ValidationError): class InvalidBarcode(frappe.ValidationError): pass +class DataValidationError(frappe.ValidationError): + pass -class Item(WebsiteGenerator): - website = frappe._dict( - page_title_field="item_name", - condition_field="show_in_website", - template="templates/generators/item/item.html", - no_cache=1 - ) - +class Item(Document): def onload(self): - super(Item, self).onload() - self.set_onload('stock_exists', self.stock_ledger_created()) self.set_asset_naming_series() @@ -83,8 +87,6 @@ class Item(WebsiteGenerator): self.set_opening_stock() def validate(self): - super(Item, self).validate() - if not self.item_name: self.item_name = self.item_code @@ -111,8 +113,6 @@ class Item(WebsiteGenerator): self.validate_attributes() self.validate_variant_attributes() self.validate_variant_based_on_change() - self.validate_website_image() - self.make_thumbnail() self.validate_fixed_asset() self.validate_retain_sample() self.validate_uom_conversion_factor() @@ -121,22 +121,18 @@ class Item(WebsiteGenerator): self.update_defaults_from_item_group() self.validate_auto_reorder_enabled_in_stock_settings() self.cant_change() - self.update_show_in_website() self.validate_item_tax_net_rate_range() set_item_tax_from_hsn_code(self) if not self.is_new(): self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group") - self.old_website_item_groups = frappe.db.sql_list("""select item_group - from `tabWebsite Item Group` - where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name) def on_update(self): invalidate_cache_for_item(self) self.validate_name_with_item_group() self.update_variants() self.update_item_price() - self.update_template_item() + self.update_website_item() def validate_description(self): '''Clean HTML description if set''' @@ -196,95 +192,6 @@ class Item(WebsiteGenerator): stock_entry.add_comment("Comment", _("Opening Stock")) - def make_route(self): - if not self.route: - return cstr(frappe.db.get_value('Item Group', self.item_group, - 'route')) + '/' + self.scrub((self.item_name or self.item_code) + '-' + random_string(5)) - - def validate_website_image(self): - if frappe.flags.in_import: - return - - """Validate if the website image is a public file""" - auto_set_website_image = False - if not self.website_image and self.image: - auto_set_website_image = True - self.website_image = self.image - - if not self.website_image: - return - - # find if website image url exists as public - file_doc = frappe.get_all("File", filters={ - "file_url": self.website_image - }, fields=["name", "is_private"], order_by="is_private asc", limit_page_length=1) - - if file_doc: - file_doc = file_doc[0] - - if not file_doc: - if not auto_set_website_image: - frappe.msgprint(_("Website Image {0} attached to Item {1} cannot be found").format(self.website_image, self.name)) - - self.website_image = None - - elif file_doc.is_private: - if not auto_set_website_image: - frappe.msgprint(_("Website Image should be a public file or website URL")) - - self.website_image = None - - def make_thumbnail(self): - if frappe.flags.in_import: - return - - """Make a thumbnail of `website_image`""" - import requests.exceptions - - if not self.is_new() and self.website_image != frappe.db.get_value(self.doctype, self.name, "website_image"): - self.thumbnail = None - - if self.website_image and not self.thumbnail: - file_doc = None - - try: - file_doc = frappe.get_doc("File", { - "file_url": self.website_image, - "attached_to_doctype": "Item", - "attached_to_name": self.name - }) - except frappe.DoesNotExistError: - # cleanup - frappe.local.message_log.pop() - - except requests.exceptions.HTTPError: - frappe.msgprint(_("Warning: Invalid attachment {0}").format(self.website_image)) - self.website_image = None - - except requests.exceptions.SSLError: - frappe.msgprint( - _("Warning: Invalid SSL certificate on attachment {0}").format(self.website_image)) - self.website_image = None - - # for CSV import - if self.website_image and not file_doc: - try: - file_doc = frappe.get_doc({ - "doctype": "File", - "file_url": self.website_image, - "attached_to_doctype": "Item", - "attached_to_name": self.name - }).save() - - except IOError: - self.website_image = None - - if file_doc: - if not file_doc.thumbnail_url: - file_doc.make_thumbnail() - - self.thumbnail = file_doc.thumbnail_url - def validate_fixed_asset(self): if self.is_fixed_asset: if self.is_stock_item: @@ -308,167 +215,6 @@ class Item(WebsiteGenerator): frappe.throw(_("{0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format( self.item_code)) - def get_context(self, context): - context.show_search = True - context.search_link = '/product_search' - - context.parents = get_parent_item_groups(self.item_group) - context.body_class = "product-page" - - self.set_variant_context(context) - self.set_attribute_context(context) - self.set_disabled_attributes(context) - self.set_metatags(context) - self.set_shopping_cart_data(context) - - return context - - def set_variant_context(self, context): - if self.has_variants: - context.no_cache = True - - # load variants - # also used in set_attribute_context - context.variants = frappe.get_all("Item", - filters={"variant_of": self.name, "show_variant_in_website": 1}, - order_by="name asc") - - variant = frappe.form_dict.variant - if not variant and context.variants: - # the case when the item is opened for the first time from its list - variant = context.variants[0] - - if variant: - context.variant = frappe.get_doc("Item", variant) - - for fieldname in ("website_image", "website_image_alt", "web_long_description", "description", - "website_specifications"): - if context.variant.get(fieldname): - value = context.variant.get(fieldname) - if isinstance(value, list): - value = [d.as_dict() for d in value] - - context[fieldname] = value - - if self.slideshow: - if context.variant and context.variant.slideshow: - context.update(get_slideshow(context.variant)) - else: - context.update(get_slideshow(self)) - - def set_attribute_context(self, context): - if not self.has_variants: - return - - attribute_values_available = {} - context.attribute_values = {} - context.selected_attributes = {} - - # load attributes - for v in context.variants: - v.attributes = frappe.get_all("Item Variant Attribute", - fields=["attribute", "attribute_value"], - filters={"parent": v.name}) - # make a map for easier access in templates - v.attribute_map = frappe._dict({}) - for attr in v.attributes: - v.attribute_map[attr.attribute] = attr.attribute_value - - for attr in v.attributes: - values = attribute_values_available.setdefault(attr.attribute, []) - if attr.attribute_value not in values: - values.append(attr.attribute_value) - - if v.name == context.variant.name: - context.selected_attributes[attr.attribute] = attr.attribute_value - - # filter attributes, order based on attribute table - for attr in self.attributes: - values = context.attribute_values.setdefault(attr.attribute, []) - - if cint(frappe.db.get_value("Item Attribute", attr.attribute, "numeric_values")): - for val in sorted(attribute_values_available.get(attr.attribute, []), key=flt): - values.append(val) - - else: - # get list of values defined (for sequence) - for attr_value in frappe.db.get_all("Item Attribute Value", - fields=["attribute_value"], - filters={"parent": attr.attribute}, order_by="idx asc"): - - if attr_value.attribute_value in attribute_values_available.get(attr.attribute, []): - values.append(attr_value.attribute_value) - - context.variant_info = json.dumps(context.variants) - - def set_disabled_attributes(self, context): - """Disable selection options of attribute combinations that do not result in a variant""" - if not self.attributes or not self.has_variants: - return - - context.disabled_attributes = {} - attributes = [attr.attribute for attr in self.attributes] - - def find_variant(combination): - for variant in context.variants: - if len(variant.attributes) < len(attributes): - continue - - if "combination" not in variant: - ref_combination = [] - - for attr in variant.attributes: - idx = attributes.index(attr.attribute) - ref_combination.insert(idx, attr.attribute_value) - - variant["combination"] = ref_combination - - if not (set(combination) - set(variant["combination"])): - # check if the combination is a subset of a variant combination - # eg. [Blue, 0.5] is a possible combination if exists [Blue, Large, 0.5] - return True - - for i, attr in enumerate(self.attributes): - if i == 0: - continue - - combination_source = [] - - # loop through previous attributes - for prev_attr in self.attributes[:i]: - combination_source.append([context.selected_attributes.get(prev_attr.attribute)]) - - combination_source.append(context.attribute_values[attr.attribute]) - - for combination in itertools.product(*combination_source): - if not find_variant(combination): - context.disabled_attributes.setdefault(attr.attribute, []).append(combination[-1]) - - def set_metatags(self, context): - context.metatags = frappe._dict({}) - - safe_description = frappe.utils.to_markdown(self.description) - - context.metatags.url = frappe.utils.get_url() + '/' + context.route - - if context.website_image: - if context.website_image.startswith('http'): - url = context.website_image - else: - url = frappe.utils.get_url() + context.website_image - context.metatags.image = url - - context.metatags.description = safe_description[:300] - - context.metatags.title = self.item_name or self.item_code - - context.metatags['og:type'] = 'product' - context.metatags['og:site_name'] = 'ERPNext' - - def set_shopping_cart_data(self, context): - from erpnext.shopping_cart.product_info import get_product_info_for_website - context.shopping_cart = get_product_info_for_website(self.name, skip_quotation_creation=True) - def add_default_uom_in_conversion_factor_table(self): uom_conv_list = [d.uom for d in self.get("uoms")] if self.stock_uom not in uom_conv_list: @@ -483,9 +229,29 @@ class Item(WebsiteGenerator): [self.remove(d) for d in to_remove] - def update_show_in_website(self): - if self.disabled: - self.show_in_website = False + def update_website_item(self): + """Update Website Item if change in Item impacts it.""" + web_item = frappe.db.exists("Website Item", {"item_code": self.item_code}) + + if web_item: + changed = {} + editable_fields = ["item_name", "item_group", "stock_uom", "brand", "description", + "disabled"] + doc_before_save = self.get_doc_before_save() + + for field in editable_fields: + if doc_before_save.get(field) != self.get(field): + if field == "disabled": + changed["published"] = not self.get(field) + else: + changed[field] = self.get(field) + + if not changed: + return + + web_item_doc = frappe.get_doc("Website Item", web_item) + web_item_doc.update(changed) + web_item_doc.save() def validate_item_tax_net_rate_range(self): for tax in self.get('taxes'): @@ -615,7 +381,6 @@ class Item(WebsiteGenerator): (self.item_name, self.description, self.brand, self.name)) def on_trash(self): - super(Item, self).on_trash() frappe.db.sql("""delete from tabBin where item_code=%s""", self.name) frappe.db.sql("delete from `tabItem Price` where item_code=%s", self.name) for variant_of in frappe.get_all("Item", filters={"variant_of": self.name}): @@ -626,23 +391,15 @@ class Item(WebsiteGenerator): frappe.db.set_value("Item", old_name, "item_name", new_name) if merge: - # Validate properties before merging - if not frappe.db.exists("Item", new_name): - frappe.throw(_("Item {0} does not exist").format(new_name)) - - field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"] - new_properties = [cstr(d) for d in frappe.db.get_value("Item", new_name, field_list)] - if new_properties != [cstr(self.get(fld)) for fld in field_list]: - frappe.throw(_("To merge, following properties must be same for both items") - + ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list])) + self.validate_properties_before_merge(new_name) + self.validate_duplicate_website_item_before_merge(old_name, new_name) def after_rename(self, old_name, new_name, merge): if merge: self.validate_duplicate_item_in_stock_reconciliation(old_name, new_name) - if self.route: + if self.published_in_website: invalidate_cache_for_item(self) - clear_cache(self.route) frappe.db.set_value("Item", new_name, "item_code", new_name) @@ -682,7 +439,41 @@ class Item(WebsiteGenerator): msg += _("Note: To merge the items, create a separate Stock Reconciliation for the old item {0}").format( frappe.bold(old_name)) - frappe.throw(_(msg), title=_("Merge not allowed")) + frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError) + + def validate_properties_before_merge(self, new_name): + # Validate properties before merging + if not frappe.db.exists("Item", new_name): + frappe.throw(_("Item {0} does not exist").format(new_name)) + + field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"] + new_properties = [cstr(d) for d in frappe.db.get_value("Item", new_name, field_list)] + + if new_properties != [cstr(self.get(field)) for field in field_list]: + msg = _("To merge, following properties must be same for both items") + msg += ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]) + frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError) + + def validate_duplicate_website_item_before_merge(self, old_name, new_name): + """ + Block merge if both old and new items have website items against them. + This is to avoid duplicate website items after merging. + """ + web_items = frappe.get_all( + "Website Item", + filters={ + "item_code": ["in", [old_name, new_name]] + }, + fields=["item_code", "name"]) + + if len(web_items) <= 1: + return + + old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0] + web_item_link = get_link_to_form("Website Item", old_web_item) + + msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} and {new_name}" + frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError) def set_last_purchase_rate(self, new_name): last_purchase_rate = get_last_purchase_details(new_name).get("base_net_rate", 0) @@ -706,16 +497,6 @@ class Item(WebsiteGenerator): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock) frappe.db.auto_commit_on_many_writes = 0 - @frappe.whitelist() - def copy_specification_from_item_group(self): - self.set("website_specifications", []) - if self.item_group: - for label, desc in frappe.db.get_values("Item Website Specification", - {"parent": self.item_group}, ["label", "description"]): - row = self.append("website_specifications") - row.label = label - row.description = desc - def update_bom_item_desc(self): if self.is_new(): return @@ -739,25 +520,6 @@ class Item(WebsiteGenerator): where item_code = %s and docstatus < 2 """, (self.description, self.name)) - def update_template_item(self): - """Set Show in Website for Template Item if True for its Variant""" - if not self.variant_of: - return - - if self.show_in_website: - self.show_variant_in_website = 1 - self.show_in_website = 0 - - if self.show_variant_in_website: - # show template - template_item = frappe.get_doc("Item", self.variant_of) - - if not template_item.show_in_website: - template_item.show_in_website = 1 - template_item.flags.dont_update_variants = True - template_item.flags.ignore_permissions = True - template_item.save() - def validate_item_defaults(self): companies = {row.company for row in self.item_defaults} @@ -1004,47 +766,6 @@ class Item(WebsiteGenerator): if not enabled: frappe.msgprint(msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."), title=_("Enable Auto Re-Order"), indicator="orange") - def create_onboarding_docs(self, args): - company = frappe.defaults.get_defaults().get('company') or \ - frappe.db.get_single_value('Global Defaults', 'default_company') - - for i in range(1, args.get('max_count')): - item = args.get('item_' + str(i)) - if item: - default_warehouse = '' - default_warehouse = frappe.db.get_value('Warehouse', filters={ - 'warehouse_name': _('Finished Goods'), - 'company': company - }) - - try: - frappe.get_doc({ - 'doctype': self.doctype, - 'item_code': item, - 'item_name': item, - 'description': item, - 'show_in_website': 1, - 'is_sales_item': 1, - 'is_purchase_item': 1, - 'is_stock_item': 1, - 'item_group': _('Products'), - 'stock_uom': _(args.get('item_uom_' + str(i))), - 'item_defaults': [{ - 'default_warehouse': default_warehouse, - 'company': company - }] - }).insert() - - except frappe.NameError: - pass - else: - if args.get('item_price_' + str(i)): - item_price = flt(args.get('item_price_' + str(i))) - - price_list_name = frappe.db.get_value('Price List', {'selling': 1}) - make_item_price(item, price_list_name, item_price) - price_list_name = frappe.db.get_value('Price List', {'buying': 1}) - make_item_price(item, price_list_name, item_price) def make_item_price(item, price_list_name, item_price): frappe.get_doc({ @@ -1159,14 +880,9 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): def invalidate_cache_for_item(doc): + """Invalidate Item Group cache and rebuild ItemVariantsCacheManager.""" invalidate_cache_for(doc, doc.item_group) - website_item_groups = list(set((doc.get("old_website_item_groups") or []) - + [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group])) - - for item_group in website_item_groups: - invalidate_cache_for(doc, item_group) - if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group: invalidate_cache_for(doc, doc.old_item_group) @@ -1174,12 +890,14 @@ def invalidate_cache_for_item(doc): def invalidate_item_variants_cache_for_website(doc): - from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager + """Rebuild ItemVariantsCacheManager via Item or Website Item.""" + from erpnext.e_commerce.variant_selector.item_variants_cache import ItemVariantsCacheManager item_code = None - if doc.has_variants and doc.show_in_website: - item_code = doc.name - elif doc.variant_of and frappe.db.get_value('Item', doc.variant_of, 'show_in_website'): + is_web_item = doc.get("published_in_website") or doc.get("published") + if doc.has_variants and is_web_item: + item_code = doc.item_code + elif doc.variant_of and frappe.db.get_value('Item', doc.variant_of, 'published_in_website'): item_code = doc.variant_of if item_code: @@ -1303,10 +1021,6 @@ def update_variants(variants, template, publish_progress=True): if publish_progress: frappe.publish_progress(count / total * 100, title=_("Updating Variants...")) -def on_doctype_update(): - # since route is a Text column, it needs a length for indexing - frappe.db.add_index("Item", ["route(500)"]) - @erpnext.allow_regional def set_item_tax_from_hsn_code(item): pass diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py index b3e4796354b..e80ed6fcda9 100644 --- a/erpnext/stock/doctype/item/item_dashboard.py +++ b/erpnext/stock/doctype/item/item_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'heatmap': True, diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 7a9985d7f07..9eeb5ab1ba9 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -2,21 +2,31 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest -import frappe -import json +import json +import unittest + +import frappe from frappe.test_runner import make_test_objects -from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError, - InvalidItemAttributeValueError, get_variant) -from erpnext.stock.doctype.item.item import StockExistsForTemplate, InvalidBarcode -from erpnext.stock.doctype.item.item import (get_uom_conv_factor, get_item_attribute, - validate_is_stock_item, get_timeline_data) + +from erpnext.controllers.item_variant import ( + InvalidItemAttributeValueError, + ItemVariantExistsError, + create_variant, + get_variant, +) +from erpnext.stock.doctype.item.item import ( + InvalidBarcode, + StockExistsForTemplate, + get_item_attribute, + get_timeline_data, + get_uom_conv_factor, + validate_is_stock_item, +) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.stock.get_item_details import get_item_details from erpnext.tests.utils import change_settings - test_ignore = ["BOM"] test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"] @@ -506,19 +516,6 @@ class TestItem(unittest.TestCase): self.assertIsInstance(count, int) self.assertTrue(count >= 0) - def test_index_creation(self): - "check if index is getting created in db" - from erpnext.stock.doctype.item.item import on_doctype_update - on_doctype_update() - - indices = frappe.db.sql("show index from tabItem", as_dict=1) - expected_columns = {"item_code", "item_name", "item_group", "route"} - for index in indices: - expected_columns.discard(index.get("Column_name")) - - if expected_columns: - self.fail(f"Expected db index on these columns: {', '.join(expected_columns)}") - def test_attribute_completions(self): expected_attrs = {"Small", "Extra Small", "Extra Large", "Large", "2XL", "Medium"} diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json index 6cec85288fe..91c77d51529 100644 --- a/erpnext/stock/doctype/item/test_records.json +++ b/erpnext/stock/doctype/item/test_records.json @@ -40,9 +40,7 @@ "conversion_factor": 10.0 } ], - "stock_uom": "_Test UOM", - "show_in_website": 1, - "website_warehouse": "_Test Warehouse - _TC" + "stock_uom": "_Test UOM" }, { "description": "_Test Item 2", @@ -56,8 +54,6 @@ "item_group": "_Test Item Group", "item_name": "_Test Item 2", "stock_uom": "_Test UOM", - "show_in_website": 1, - "website_warehouse": "_Test Warehouse - _TC", "gst_hsn_code": "999800", "opening_stock": 10, "valuation_rate": 100, @@ -311,8 +307,7 @@ "warehouse_reorder_level": 20, "warehouse_reorder_qty": 20 } - ], - "show_in_website": 1 + ] }, { "description": "_Test Item 1", @@ -344,9 +339,7 @@ "warehouse_reorder_qty": 20 } ], - "stock_uom": "_Test UOM", - "show_in_website": 1, - "website_warehouse": "_Test Warehouse Group-C1 - _TC" + "stock_uom": "_Test UOM" }, { "description": "_Test Item With Item Tax Template", diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py index 190cb62e997..6080fb4a5fa 100644 --- a/erpnext/stock/doctype/item_alternative/item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/item_alternative.py @@ -3,10 +3,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + class ItemAlternative(Document): def validate(self): self.has_alternative_item() diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py index 8f76844bde0..2be8ef740a4 100644 --- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py @@ -2,17 +2,27 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import flt -from erpnext.stock.doctype.item.test_item import create_item -from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom -from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order -from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation -from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record -from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_rm_stock_entry + +import json import unittest +import frappe +from frappe.utils import flt + +from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_purchase_receipt, + make_rm_stock_entry, +) +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom +from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record +from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry +from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, +) + + class TestItemAlternative(unittest.TestCase): def setUp(self): make_items() diff --git a/erpnext/stock/doctype/item_attribute/item_attribute.py b/erpnext/stock/doctype/item_attribute/item_attribute.py index 3764738e838..9894788b8c2 100644 --- a/erpnext/stock/doctype/item_attribute/item_attribute.py +++ b/erpnext/stock/doctype/item_attribute/item_attribute.py @@ -2,13 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document from frappe.utils import flt -from erpnext.controllers.item_variant import (validate_is_incremental, - validate_item_attribute_value, InvalidItemAttributeValueError) +from erpnext.controllers.item_variant import ( + InvalidItemAttributeValueError, + validate_is_incremental, + validate_item_attribute_value, +) class ItemAttributeIncrementError(frappe.ValidationError): pass diff --git a/erpnext/stock/doctype/item_attribute/test_item_attribute.py b/erpnext/stock/doctype/item_attribute/test_item_attribute.py index 07af176a944..fc809f443e6 100644 --- a/erpnext/stock/doctype/item_attribute/test_item_attribute.py +++ b/erpnext/stock/doctype/item_attribute/test_item_attribute.py @@ -2,13 +2,16 @@ # See license.txt from __future__ import unicode_literals -import frappe + import unittest +import frappe + test_records = frappe.get_test_records('Item Attribute') from erpnext.stock.doctype.item_attribute.item_attribute import ItemAttributeIncrementError + class TestItemAttribute(unittest.TestCase): def setUp(self): if frappe.db.exists("Item Attribute", "_Test_Length"): diff --git a/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py b/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py index edbab002da0..ceffb4972a9 100644 --- a/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py +++ b/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ItemAttributeValue(Document): pass diff --git a/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py b/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py index 3e4e8500467..55fd0ec3436 100644 --- a/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py +++ b/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemCustomerDetail(Document): pass diff --git a/erpnext/stock/doctype/item_default/item_default.py b/erpnext/stock/doctype/item_default/item_default.py index 935f0ffb0ff..6239c540434 100644 --- a/erpnext/stock/doctype/item_default/item_default.py +++ b/erpnext/stock/doctype/item_default/item_default.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class ItemDefault(Document): pass diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py index 939abf8d324..044ac7c2350 100644 --- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py +++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py @@ -8,6 +8,7 @@ import frappe from frappe import _ from frappe.model.document import Document + class ItemManufacturer(Document): def validate(self): self.validate_duplicate_entry() diff --git a/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py index 1cef20c4171..5a4ca6a44ad 100644 --- a/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py +++ b/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestItemManufacturer(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py index e82a19b0dc0..3f0fc4136b0 100644 --- a/erpnext/stock/doctype/item_price/item_price.py +++ b/erpnext/stock/doctype/item_price/item_price.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document diff --git a/erpnext/stock/doctype/item_price/test_item_price.py b/erpnext/stock/doctype/item_price/test_item_price.py index f3d406eeca6..5ed80921660 100644 --- a/erpnext/stock/doctype/item_price/test_item_price.py +++ b/erpnext/stock/doctype/item_price/test_item_price.py @@ -2,11 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import unittest + import frappe from frappe.test_runner import make_test_records_for_doctype -from erpnext.stock.get_item_details import get_price_list_rate_for, process_args + from erpnext.stock.doctype.item_price.item_price import ItemPriceDuplicateItem +from erpnext.stock.get_item_details import get_price_list_rate_for, process_args class TestItemPrice(unittest.TestCase): diff --git a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py index 785737b267f..0dd7e431054 100644 --- a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py +++ b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemQualityInspectionParameter(Document): pass diff --git a/erpnext/stock/doctype/item_reorder/item_reorder.py b/erpnext/stock/doctype/item_reorder/item_reorder.py index 5cdaa229565..598339deee8 100644 --- a/erpnext/stock/doctype/item_reorder/item_reorder.py +++ b/erpnext/stock/doctype/item_reorder/item_reorder.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemReorder(Document): pass diff --git a/erpnext/stock/doctype/item_supplier/item_supplier.py b/erpnext/stock/doctype/item_supplier/item_supplier.py index 5dda535f810..9b5da55f600 100644 --- a/erpnext/stock/doctype/item_supplier/item_supplier.py +++ b/erpnext/stock/doctype/item_supplier/item_supplier.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemSupplier(Document): pass diff --git a/erpnext/stock/doctype/item_tax/item_tax.py b/erpnext/stock/doctype/item_tax/item_tax.py index 7c9e8115758..33c1e49f409 100644 --- a/erpnext/stock/doctype/item_tax/item_tax.py +++ b/erpnext/stock/doctype/item_tax/item_tax.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemTax(Document): pass diff --git a/erpnext/stock/doctype/item_variant/item_variant.py b/erpnext/stock/doctype/item_variant/item_variant.py index 5d5a022648a..47ab07fe98d 100644 --- a/erpnext/stock/doctype/item_variant/item_variant.py +++ b/erpnext/stock/doctype/item_variant/item_variant.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ItemVariant(Document): pass diff --git a/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py b/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py index d1a1eb54a5d..78dda6535fc 100644 --- a/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py +++ b/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class ItemVariantAttribute(Document): pass diff --git a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js index e8fb34732fc..cb9abc08e25 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js @@ -4,8 +4,8 @@ frappe.ui.form.on('Item Variant Settings', { setup: function(frm) { const allow_fields = []; - const exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website", - "show_variant_in_website", "opening_stock", "variant_of", "valuation_rate"]; + const exclude_fields = ["naming_series", "item_code", "item_name", "published_in_website", + "opening_stock", "variant_of", "valuation_rate"]; frappe.model.with_doctype('Item', () => { frappe.get_meta('Item').fields.forEach(d => { diff --git a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py index 78f1131b769..97db049f146 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -from frappe.model.document import Document from frappe import _ +from frappe.model.document import Document + class ItemVariantSettings(Document): invalid_fields_for_copy_fields_in_variants = ['barcodes'] @@ -13,10 +15,9 @@ class ItemVariantSettings(Document): def set_default_fields(self): self.fields = [] fields = frappe.get_meta('Item').fields - exclude_fields = {"naming_series", "item_code", "item_name", "show_in_website", - "show_variant_in_website", "standard_rate", "opening_stock", "image", "description", + exclude_fields = {"naming_series", "item_code", "item_name", "published_in_website", + "standard_rate", "opening_stock", "image", "description", "variant_of", "valuation_rate", "description", "barcodes", - "website_image", "thumbnail", "website_specifiations", "web_long_description", "has_variants", "attributes"} for d in fields: diff --git a/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.py b/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.py index 9a800c07fcb..040382a66f7 100644 --- a/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.py +++ b/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestItemVariantSettings(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/item_website_specification/item_website_specification.py b/erpnext/stock/doctype/item_website_specification/item_website_specification.py index e3041cf3eef..85491b73921 100644 --- a/erpnext/stock/doctype/item_website_specification/item_website_specification.py +++ b/erpnext/stock/doctype/item_website_specification/item_website_specification.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class ItemWebsiteSpecification(Document): pass diff --git a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py index 493e8b239a4..7dd3aa5c346 100644 --- a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py +++ b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class LandedCostItem(Document): pass diff --git a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py index 38f4eafc3aa..3d81d964111 100644 --- a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py +++ b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class LandedCostPurchaseReceipt(Document): pass diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py index 0dc396aefac..e649e4d0797 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class LandedCostTaxesandCharges(Document): pass diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index bf969f99f8e..51ccea982d9 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -2,14 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from frappe.utils import flt -from frappe.model.meta import get_field_precision from frappe.model.document import Document -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos -from erpnext.accounts.doctype.account.account import get_account_currency +from frappe.model.meta import get_field_precision +from frappe.utils import flt + +import erpnext from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + class LandedCostVoucher(Document): @frappe.whitelist() diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index cb09d933801..58a72f72dd1 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -3,15 +3,20 @@ from __future__ import unicode_literals + import unittest + import frappe from frappe.utils import flt -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ - import get_gl_entries, test_records as pr_test_records, make_purchase_receipt + +from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.accounts.doctype.account.test_account import create_account from erpnext.assets.doctype.asset.test_asset import create_asset_category, create_fixed_asset_item +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import ( + get_gl_entries, + make_purchase_receipt, +) + class TestLandedCostVoucher(unittest.TestCase): def test_landed_cost_voucher(self): @@ -208,7 +213,10 @@ class TestLandedCostVoucher(unittest.TestCase): self.assertEqual(pr.items[1].landed_cost_voucher_amount, 100) def test_multi_currency_lcv(self): - from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records + from erpnext.setup.doctype.currency_exchange.test_currency_exchange import ( + save_new_records, + test_records, + ) save_new_records(test_records) diff --git a/erpnext/stock/doctype/manufacturer/manufacturer.py b/erpnext/stock/doctype/manufacturer/manufacturer.py index b624f73b773..314a2808045 100644 --- a/erpnext/stock/doctype/manufacturer/manufacturer.py +++ b/erpnext/stock/doctype/manufacturer/manufacturer.py @@ -3,10 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address + +from frappe.contacts.address_and_contact import load_address_and_contact from frappe.model.document import Document + class Manufacturer(Document): def onload(self): """Load address and contacts in `__onload`""" diff --git a/erpnext/stock/doctype/manufacturer/test_manufacturer.py b/erpnext/stock/doctype/manufacturer/test_manufacturer.py index 996f6b27ca0..c0c61b00d0b 100644 --- a/erpnext/stock/doctype/manufacturer/test_manufacturer.py +++ b/erpnext/stock/doctype/manufacturer/test_manufacturer.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Manufacturer') diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 026b85e26d2..9eb47216266 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -5,19 +5,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -import json -from frappe.utils import cstr, flt, getdate, new_line_sep, nowdate, add_days, get_link_to_form -from frappe import msgprint, _ +import frappe +from frappe import _, msgprint from frappe.model.mapper import get_mapped_doc -from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty +from frappe.utils import cstr, flt, get_link_to_form, getdate, new_line_sep, nowdate + +from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_items from erpnext.controllers.buying_controller import BuyingController from erpnext.manufacturing.doctype.work_order.work_order import get_item_details -from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_items from erpnext.stock.doctype.item.item import get_item_defaults - -from six import string_types +from erpnext.stock.stock_balance import get_indented_qty, update_bin_qty form_grid_templates = { "items": "templates/form_grid/material_request_grid.html" diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py index e1e4faf6825..291cfb53c90 100644 --- a/erpnext/stock/doctype/material_request/material_request_dashboard.py +++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from frappe import _ diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index b4776ba2492..5c2ac2584f7 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -5,11 +5,20 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, unittest, erpnext + +import unittest + +import frappe from frappe.utils import flt, today -from erpnext.stock.doctype.material_request.material_request \ - import raise_work_orders, make_stock_entry, make_purchase_order, make_supplier_quotation + from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.material_request.material_request import ( + make_purchase_order, + make_stock_entry, + make_supplier_quotation, + raise_work_orders, +) + class TestMaterialRequest(unittest.TestCase): def test_make_purchase_order(self): diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py index e0066e65d2c..0c98b97e57e 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.py +++ b/erpnext/stock/doctype/material_request_item/material_request_item.py @@ -4,10 +4,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe +import frappe from frappe.model.document import Document + class MaterialRequestItem(Document): pass diff --git a/erpnext/stock/doctype/packed_item/packed_item.json b/erpnext/stock/doctype/packed_item/packed_item.json index bb396e806f6..830d5469bf0 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.json +++ b/erpnext/stock/doctype/packed_item/packed_item.json @@ -16,6 +16,7 @@ "conversion_factor", "column_break_9", "qty", + "rate", "uom", "section_break_9", "serial_no", @@ -215,13 +216,23 @@ "fieldname": "conversion_factor", "fieldtype": "Float", "label": "Conversion Factor" + }, + { + "fetch_from": "item_code.valuation_rate", + "fetch_if_empty": 1, + "fieldname": "rate", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Rate", + "print_hide": 1, + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-05-26 07:08:05.111385", + "modified": "2021-09-01 15:10:29.646399", "modified_by": "Administrator", "module": "Stock", "name": "Packed Item", diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 4ab71bdf629..aec094b0cd5 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -4,10 +4,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import cstr, flt -from erpnext.stock.get_item_details import get_item_details + +import json + +import frappe from frappe.model.document import Document +from frappe.utils import cstr, flt + +from erpnext.stock.get_item_details import get_item_details + class PackedItem(Document): pass @@ -86,6 +91,9 @@ def make_packing_list(doc): cleanup_packing_list(doc, parent_items) + if frappe.db.get_single_value("Selling Settings", "editable_bundle_item_rates"): + update_product_bundle_price(doc, parent_items) + def cleanup_packing_list(doc, parent_items): """Remove all those child items which are no longer present in main item table""" delete_list = [] @@ -103,6 +111,40 @@ def cleanup_packing_list(doc, parent_items): if d not in delete_list: doc.append("packed_items", d) +def update_product_bundle_price(doc, parent_items): + """Updates the prices of Product Bundles based on the rates of the Items in the bundle.""" + + if not doc.get('items'): + return + + parent_items_index = 0 + bundle_price = 0 + + for bundle_item in doc.get("packed_items"): + if parent_items[parent_items_index][0] == bundle_item.parent_item: + bundle_item_rate = bundle_item.rate if bundle_item.rate else 0 + bundle_price += bundle_item.qty * bundle_item_rate + else: + update_parent_item_price(doc, parent_items[parent_items_index][0], bundle_price) + + bundle_price = 0 + parent_items_index += 1 + + # for the last product bundle + if doc.get("packed_items"): + update_parent_item_price(doc, parent_items[parent_items_index][0], bundle_price) + +def update_parent_item_price(doc, parent_item_code, bundle_price): + parent_item_doc = doc.get('items', {'item_code': parent_item_code})[0] + + current_parent_item_price = parent_item_doc.amount + if current_parent_item_price != bundle_price: + parent_item_doc.amount = bundle_price + update_parent_item_rate(parent_item_doc, bundle_price) + +def update_parent_item_rate(parent_item_doc, bundle_price): + parent_item_doc.rate = bundle_price/parent_item_doc.qty + @frappe.whitelist() def get_items_from_product_bundle(args): args = json.loads(args) diff --git a/erpnext/stock/doctype/packing_slip/test_packing_slip.py b/erpnext/stock/doctype/packing_slip/test_packing_slip.py index 1f2af02e209..193adfcf1cb 100644 --- a/erpnext/stock/doctype/packing_slip/test_packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/test_packing_slip.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest # test_records = frappe.get_test_records('Packing Slip') diff --git a/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py b/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py index b0a855961f9..8363968187b 100644 --- a/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py +++ b/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py @@ -4,9 +4,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PackingSlipItem(Document): pass diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 516ae43089b..dffbe80fa39 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -3,16 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json -from six import iteritems -from frappe.model.document import Document -from frappe import _ from collections import OrderedDict -from frappe.utils import floor, flt, today, cint -from frappe.model.mapper import get_mapped_doc, map_child_doc + +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.model.mapper import map_child_doc +from frappe.utils import cint, floor, flt, today +from six import iteritems + +from erpnext.selling.doctype.sales_order.sales_order import ( + make_delivery_note as create_delivery_note_from_sales_order, +) from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note as create_delivery_note_from_sales_order # TODO: Prioritize SO or WO group warehouse diff --git a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py index 7c321c450a6..50a767bafa7 100644 --- a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py +++ b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from frappe import _ + def get_data(): return { diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index 84566b8d8c7..aa710ad0e97 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -3,15 +3,19 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch'] -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.doctype.pick_list.pick_list import create_delivery_note -from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \ - import EmptyStockReconciliationItemsError +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( + EmptyStockReconciliationItemsError, +) + class TestPickList(unittest.TestCase): diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.py b/erpnext/stock/doctype/pick_list_item/pick_list_item.py index 8797b8dc219..4cd81f7f85b 100644 --- a/erpnext/stock/doctype/pick_list_item/pick_list_item.py +++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PickListItem(Document): pass diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py index 002d3d898eb..1a5a7ba23ff 100644 --- a/erpnext/stock/doctype/price_list/price_list.py +++ b/erpnext/stock/doctype/price_list/price_list.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _, throw -from frappe.utils import cint from frappe.model.document import Document -import frappe.defaults +from frappe.utils import cint + class PriceList(Document): def validate(self): @@ -36,12 +37,14 @@ class PriceList(Document): (self.currency, cint(self.buying), cint(self.selling), self.name)) def check_impact_on_shopping_cart(self): - "Check if Price List currency change impacts Shopping Cart." - from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import validate_cart_settings + "Check if Price List currency change impacts E Commerce Cart." + from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ( + validate_cart_settings, + ) doc_before_save = self.get_doc_before_save() currency_changed = self.currency != doc_before_save.currency - affects_cart = self.name == frappe.get_cached_value("Shopping Cart Settings", None, "price_list") + affects_cart = self.name == frappe.get_cached_value("E Commerce Settings", None, "price_list") if currency_changed and affects_cart: validate_cart_settings() diff --git a/erpnext/stock/doctype/price_list/test_price_list.py b/erpnext/stock/doctype/price_list/test_price_list.py index 2c287c9033c..baf6170e850 100644 --- a/erpnext/stock/doctype/price_list/test_price_list.py +++ b/erpnext/stock/doctype/price_list/test_price_list.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe # test_ignore = ["Item"] diff --git a/erpnext/stock/doctype/price_list_country/price_list_country.py b/erpnext/stock/doctype/price_list_country/price_list_country.py index db1a0607e62..a57729fb2e4 100644 --- a/erpnext/stock/doctype/price_list_country/price_list_country.py +++ b/erpnext/stock/doctype/price_list_country/price_list_country.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class PriceListCountry(Document): pass diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 4a4514f2497..475ac2f06f0 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -2,21 +2,19 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe - -from frappe.utils import flt, cint, nowdate - -from frappe import throw, _ -import frappe.defaults -from frappe.utils import getdate -from erpnext.controllers.buying_controller import BuyingController -from erpnext.accounts.utils import get_account_currency +from frappe import _, throw from frappe.desk.notifications import clear_doctype_notifications from frappe.model.mapper import get_mapped_doc -from erpnext.buying.utils import check_on_hold_or_closed_status +from frappe.utils import cint, flt, getdate, nowdate +from six import iteritems + +from erpnext.accounts.utils import get_account_currency from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account -from six import iteritems +from erpnext.buying.utils import check_on_hold_or_closed_status +from erpnext.controllers.buying_controller import BuyingController from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_transaction form_grid_templates = { diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py index 3832c827e27..b60850f2855 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals + from frappe import _ + def get_data(): return { 'fieldname': 'purchase_receipt_no', diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 0210702250e..c61304098f4 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -2,20 +2,22 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import unittest + import json -import frappe, erpnext -import frappe.defaults -from frappe.utils import cint, flt, cstr, today, random_string, add_days -from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice -from erpnext.stock.doctype.item.test_item import create_item -from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError -from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.stock.doctype.item.test_item import make_item +import unittest + +import frappe +from frappe.utils import add_days, cint, cstr, flt, today from six import iteritems -from erpnext.stock.stock_ledger import SerialNoExistsInFutureTransaction + +import erpnext +from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.stock.doctype.item.test_item import create_item, make_item +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice +from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError, get_serial_nos from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.stock_ledger import SerialNoExistsInFutureTransaction + class TestPurchaseReceipt(unittest.TestCase): def setUp(self): @@ -275,11 +277,16 @@ class TestPurchaseReceipt(unittest.TestCase): receive more than the required qty in the PO. Expected Result: Error Raised for Over Receipt against PO. """ + from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt + from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_rm_stock_entry as make_subcontract_transfer_entry, + ) + from erpnext.buying.doctype.purchase_order.test_purchase_order import ( + create_purchase_order, + make_subcontracted_item, + update_backflush_based_on, + ) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on, - make_subcontracted_item, create_purchase_order) - from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, - make_rm_stock_entry as make_subcontract_transfer_entry) update_backflush_based_on("Material Transferred for Subcontract") item_code = "_Test Subcontracted FG Item 1" @@ -526,7 +533,9 @@ class TestPurchaseReceipt(unittest.TestCase): pr.cancel() def test_closed_purchase_receipt(self): - from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_purchase_receipt_status + from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + update_purchase_receipt_status, + ) pr = make_purchase_receipt(do_not_submit=True) pr.submit() @@ -539,9 +548,11 @@ class TestPurchaseReceipt(unittest.TestCase): def test_pr_billing_status(self): # PO -> PR1 -> PI and PO -> PI and PO -> PR2 + from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_purchase_invoice as make_purchase_invoice_from_po, + ) + from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order - from erpnext.buying.doctype.purchase_order.purchase_order \ - import make_purchase_receipt, make_purchase_invoice as make_purchase_invoice_from_po po = create_purchase_order() @@ -748,7 +759,10 @@ class TestPurchaseReceipt(unittest.TestCase): pr.cancel() def test_make_purchase_invoice_from_pr_for_returned_qty(self): - from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po + from erpnext.buying.doctype.purchase_order.test_purchase_order import ( + create_pr_against_po, + create_purchase_order, + ) po = create_purchase_order() pr = create_pr_against_po(po.name) @@ -879,10 +893,15 @@ class TestPurchaseReceipt(unittest.TestCase): def test_subcontracted_pr_for_multi_transfer_batches(self): + from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_purchase_receipt, + make_rm_stock_entry, + ) + from erpnext.buying.doctype.purchase_order.test_purchase_order import ( + create_purchase_order, + update_backflush_based_on, + ) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry, make_purchase_receipt - from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on, - create_purchase_order) update_backflush_based_on("Material Transferred for Subcontract") item_code = "_Test Subcontracted FG Item 3" @@ -952,8 +971,7 @@ class TestPurchaseReceipt(unittest.TestCase): - Create PI from PO and submit - Create PR from PO and submit """ - from erpnext.buying.doctype.purchase_order import test_purchase_order - from erpnext.buying.doctype.purchase_order import purchase_order + from erpnext.buying.doctype.purchase_order import purchase_order, test_purchase_order po = test_purchase_order.create_purchase_order() @@ -974,8 +992,7 @@ class TestPurchaseReceipt(unittest.TestCase): - Create partial PI from PO and submit - Create PR from PO and submit """ - from erpnext.buying.doctype.purchase_order import test_purchase_order - from erpnext.buying.doctype.purchase_order import purchase_order + from erpnext.buying.doctype.purchase_order import purchase_order, test_purchase_order po = test_purchase_order.create_purchase_order() @@ -1038,10 +1055,18 @@ class TestPurchaseReceipt(unittest.TestCase): frappe.db.set_value('Company', company, 'enable_perpetual_inventory_for_non_stock_items', before_test_value) def test_payment_terms_are_fetched_when_creating_purchase_invoice(self): - from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.payment_entry.test_payment_entry import ( + create_payment_terms_template, + ) from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice - from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, make_pr_against_po - from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + from erpnext.buying.doctype.purchase_order.test_purchase_order import ( + create_purchase_order, + make_pr_against_po, + ) + from erpnext.selling.doctype.sales_order.test_sales_order import ( + automatically_fetch_payment_terms, + compare_payment_schedules, + ) automatically_fetch_payment_terms() diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 82cc98e7f75..3efa66e02ed 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -10,6 +10,7 @@ "barcode", "section_break_2", "item_code", + "product_bundle", "supplier_part_no", "column_break_2", "item_name", @@ -956,12 +957,19 @@ "no_copy": 1, "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "product_bundle", + "fieldtype": "Link", + "label": "Product Bundle", + "options": "Product Bundle", + "read_only": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-03-29 04:17:00.336298", + "modified": "2021-09-01 16:02:40.338597", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py index b79bb5d0430..2d25140d2b6 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class PurchaseReceiptItem(Document): pass diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index 315e723fabc..aa9d8968063 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -3,16 +3,20 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import copy import json from collections import defaultdict -from six import string_types + +import frappe from frappe import _ -from frappe.utils import flt, floor, nowdate, cint from frappe.model.document import Document -from erpnext.stock.utils import get_stock_balance +from frappe.utils import cint, floor, flt, nowdate +from six import string_types + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.utils import get_stock_balance + class PutawayRule(Document): def validate(self): diff --git a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py index 0590ae1abeb..0aa7610575e 100644 --- a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py @@ -2,14 +2,18 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals -import frappe + import unittest -from erpnext.stock.doctype.item.test_item import make_item -from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + +import frappe + from erpnext.stock.doctype.batch.test_batch import make_new_batch +from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry +from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse +from erpnext.stock.get_item_details import get_conversion_factor + class TestPutawayRule(unittest.TestCase): def setUp(self): diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 469511af60b..8b2f8da9dfd 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -2,13 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc -from frappe import _ -from frappe.utils import flt, cint -from erpnext.stock.doctype.quality_inspection_template.quality_inspection_template \ - import get_template_details +from frappe.utils import cint, flt + +from erpnext.stock.doctype.quality_inspection_template.quality_inspection_template import ( + get_template_details, +) + class QualityInspection(Document): def validate(self): diff --git a/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py b/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py index 86784221a0c..fa682012e59 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py +++ b/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityInspectionParameter(Document): pass diff --git a/erpnext/stock/doctype/quality_inspection_parameter/test_quality_inspection_parameter.py b/erpnext/stock/doctype/quality_inspection_parameter/test_quality_inspection_parameter.py index cefdc0867b1..f3041aa863d 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter/test_quality_inspection_parameter.py +++ b/erpnext/stock/doctype/quality_inspection_parameter/test_quality_inspection_parameter.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestQualityInspectionParameter(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py b/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py index 1a3b1a04639..b5e28f3ec9d 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py +++ b/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class QualityInspectionParameterGroup(Document): pass diff --git a/erpnext/stock/doctype/quality_inspection_parameter_group/test_quality_inspection_parameter_group.py b/erpnext/stock/doctype/quality_inspection_parameter_group/test_quality_inspection_parameter_group.py index 212d4b8c21b..ded47e8ca80 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter_group/test_quality_inspection_parameter_group.py +++ b/erpnext/stock/doctype/quality_inspection_parameter_group/test_quality_inspection_parameter_group.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestQualityInspectionParameterGroup(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py index b10fa310d66..7b56603321a 100644 --- a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py +++ b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class QualityInspectionReading(Document): pass diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py index 971b3c29825..50e28a6361f 100644 --- a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py +++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe.model.document import Document + class QualityInspectionTemplate(Document): pass diff --git a/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py index b16efa839db..6286523c861 100644 --- a/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py +++ b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestQualityInspectionTemplate(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py index efa951940ea..8ca5521de02 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.document import Document + from erpnext.stock.utils import get_stock_balance, get_stock_value_on + class QuickStockBalance(Document): pass diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 2e454a51596..5f97798974c 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -3,14 +3,22 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext -from rq.timeouts import JobTimeoutException -from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, add_to_date, now, today, time_diff_in_hours -from erpnext.stock.stock_ledger import repost_future_sle -from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced -from frappe.utils.user import get_users_with_role + +import frappe from frappe import _ +from frappe.model.document import Document +from frappe.utils import cint, get_link_to_form, now, today +from frappe.utils.user import get_users_with_role +from rq.timeouts import JobTimeoutException + +import erpnext +from erpnext.accounts.utils import ( + check_if_stock_and_account_balance_synced, + update_gl_entries_after, +) +from erpnext.stock.stock_ledger import repost_future_sle + + class RepostItemValuation(Document): def validate(self): self.set_status() diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py index 13ceb68669c..c70a9ec7a8b 100644 --- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestRepostItemValuation(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 70312bc543b..82d8aaed5b3 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -2,19 +2,20 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json +import frappe +from frappe import ValidationError, _ from frappe.model.naming import make_autoname -from frappe.utils import cint, cstr, flt, add_days, nowdate, getdate, get_link_to_form -from erpnext.stock.get_item_details import get_reserved_qty_for_so - -from frappe import _, ValidationError - -from erpnext.controllers.stock_controller import StockController +from frappe.utils import add_days, cint, cstr, flt, get_link_to_form, getdate, nowdate from six import string_types from six.moves import map +from erpnext.controllers.stock_controller import StockController +from erpnext.stock.get_item_details import get_reserved_qty_for_so + + class SerialNoCannotCreateDirectError(ValidationError): pass class SerialNoCannotCannotChangeError(ValidationError): pass class SerialNoNotRequiredError(ValidationError): pass @@ -573,7 +574,7 @@ def auto_fetch_serial_number(qty, item_code, warehouse, posting_date=None, batch if batch_nos: try: filters["batch_no"] = json.loads(batch_nos) if (type(json.loads(batch_nos)) == list) else [json.loads(batch_nos)] - except: + except Exception: filters["batch_no"] = [batch_nos] if posting_date: diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py index 0eccce3a58e..818c163c681 100644 --- a/erpnext/stock/doctype/serial_no/test_serial_no.py +++ b/erpnext/stock/doctype/serial_no/test_serial_no.py @@ -5,12 +5,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, unittest -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +import unittest + +import frappe + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse test_dependencies = ["Item"] @@ -18,6 +21,7 @@ test_records = frappe.get_test_records('Serial No') from erpnext.stock.doctype.serial_no.serial_no import * + class TestSerialNo(unittest.TestCase): def test_cannot_create_direct(self): frappe.delete_doc_if_exists("Serial No", "_TCSER0001") diff --git a/erpnext/stock/doctype/shipment/shipment.py b/erpnext/stock/doctype/shipment/shipment.py index 01fcee4cac2..2cacd0dfab4 100644 --- a/erpnext/stock/doctype/shipment/shipment.py +++ b/erpnext/stock/doctype/shipment/shipment.py @@ -3,12 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, get_time -from frappe.model.document import Document -from erpnext.accounts.party import get_party_shipping_address from frappe.contacts.doctype.contact.contact import get_default_contact +from frappe.model.document import Document +from frappe.utils import flt, get_time + +from erpnext.accounts.party import get_party_shipping_address + class Shipment(Document): def validate(self): diff --git a/erpnext/stock/doctype/shipment/test_shipment.py b/erpnext/stock/doctype/shipment/test_shipment.py index db2f1161743..9914cf80158 100644 --- a/erpnext/stock/doctype/shipment/test_shipment.py +++ b/erpnext/stock/doctype/shipment/test_shipment.py @@ -2,12 +2,15 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals + +import unittest from datetime import date, timedelta import frappe -import unittest + from erpnext.stock.doctype.delivery_note.delivery_note import make_shipment + class TestShipment(unittest.TestCase): def test_shipment_from_delivery_note(self): delivery_note = create_test_delivery_note() diff --git a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py index 43421516057..795c952bcdd 100644 --- a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py +++ b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ShipmentDeliveryNote(Document): pass diff --git a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py index 53e6ed55dd3..69fecb6e5ce 100644 --- a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py +++ b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ShipmentParcel(Document): pass diff --git a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py index 2a8d58d8305..0eaa2d3d5b8 100644 --- a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py +++ b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ShipmentParcelTemplate(Document): pass diff --git a/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py b/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py index 6e2caa768bf..5f2a3993353 100644 --- a/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py +++ b/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestShipmentParcelTemplate(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index efbc12ce841..350af2b6004 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -278,7 +278,7 @@ frappe.ui.form.on('Stock Entry', { get_query_filters: { docstatus: 1, material_request_type: ["in", allowed_request_types], - status: ["not in", ["Transferred", "Issued"]] + status: ["not in", ["Transferred", "Issued", "Cancelled", "Stopped"]] } }) }, __("Get Items From")); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index ba7c6d11337..df98b681106 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2,27 +2,39 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -import frappe.defaults -from frappe import _ -from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate, format_time -from erpnext.stock.utils import get_incoming_rate -from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate -from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor, get_reserved_qty_for_so -from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults -from erpnext.setup.doctype.brand.brand import get_brand_defaults -from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty -from erpnext.stock.doctype.item.item import get_item_defaults -from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, add_additional_cost -from erpnext.stock.utils import get_bin -from frappe.model.mapper import get_mapped_doc -from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit, get_serial_nos -from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError -from erpnext.accounts.general_ledger import process_gl_map -from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals + import json -from six import string_types, itervalues, iteritems +import frappe +from frappe import _ +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate +from six import iteritems, itervalues, string_types + +import erpnext +from erpnext.accounts.general_ledger import process_gl_map +from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals +from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, validate_bom_no +from erpnext.setup.doctype.brand.brand import get_brand_defaults +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults +from erpnext.stock.doctype.batch.batch import get_batch_no, get_batch_qty, set_batch_nos +from erpnext.stock.doctype.item.item import get_item_defaults +from erpnext.stock.doctype.serial_no.serial_no import ( + get_serial_nos, + update_serial_nos_after_submit, +) +from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( + OpeningEntryAccountError, +) +from erpnext.stock.get_item_details import ( + get_bin_details, + get_conversion_factor, + get_default_cost_center, + get_reserved_qty_for_so, +) +from erpnext.stock.stock_ledger import NegativeStockError, get_previous_sle, get_valuation_rate +from erpnext.stock.utils import get_bin, get_incoming_rate + class IncorrectValuationRateError(frappe.ValidationError): pass class DuplicateEntryForWorkOrderError(frappe.ValidationError): pass @@ -1200,10 +1212,10 @@ class StockEntry(StockController): wo_item_qty = item.transferred_qty or item.required_qty - req_qty_each = ( - (flt(wo_item_qty) - flt(item.consumed_qty)) / - (flt(work_order_qty) - flt(wo.produced_qty)) - ) + wo_qty_consumed = flt(wo_item_qty) - flt(item.consumed_qty) + wo_qty_to_produce = flt(work_order_qty) - flt(wo.produced_qty) + + req_qty_each = (wo_qty_consumed) / (wo_qty_to_produce or 1) qty = req_qty_each * flt(self.fg_completed_qty) @@ -1491,7 +1503,8 @@ class StockEntry(StockController): qty_to_reserve -= reserved_qty[0][0] if qty_to_reserve > 0: for item in self.items: - if item.item_code == item_code: + has_serial_no = frappe.get_cached_value("Item", item.item_code, "has_serial_no") + if item.item_code == item_code and has_serial_no: serial_nos = (item.serial_no).split("\n") for serial_no in serial_nos: if qty_to_reserve > 0: @@ -1582,7 +1595,7 @@ class StockEntry(StockController): if material_request and material_request not in material_requests: material_requests.append(material_request) frappe.db.set_value('Material Request', material_request, 'transfer_status', status) - + def update_items_for_process_loss(self): process_loss_dict = {} for d in self.get("items"): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index 563fcb03973..f54dc4604ed 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -2,11 +2,14 @@ # See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import cint, flt +import frappe +from frappe.utils import cint, flt from six import string_types +import erpnext + + @frappe.whitelist() def make_stock_entry(**args): '''Helper function to make a Stock Entry diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index a0e70516d4b..46619eb1f35 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -2,21 +2,33 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, unittest -import frappe.defaults -from frappe.utils import flt, nowdate, nowtime -from erpnext.stock.doctype.serial_no.serial_no import * -from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError -from erpnext.stock.stock_ledger import get_previous_sle + +import unittest + +import frappe from frappe.permissions import add_user_permission, remove_user_permission -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation -from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant, create_item -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry -from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError +from frappe.utils import flt, nowdate, nowtime from six import iteritems +from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.stock.doctype.item.test_item import ( + create_item, + make_item_variant, + set_item_variant_settings, +) +from erpnext.stock.doctype.serial_no.serial_no import * # noqa +from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry +from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError +from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( + OpeningEntryAccountError, +) +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, +) +from erpnext.stock.stock_ledger import get_previous_sle + + def get_sle(**args): condition, values = "", [] for key, value in iteritems(args): @@ -539,8 +551,9 @@ class TestStockEntry(unittest.TestCase): frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0) def test_work_order(self): - from erpnext.manufacturing.doctype.work_order.work_order \ - import make_stock_entry as _make_stock_entry + from erpnext.manufacturing.doctype.work_order.work_order import ( + make_stock_entry as _make_stock_entry, + ) bom_no, bom_operation_cost = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", "is_default": 1, "docstatus": 1}, ["name", "operating_cost"]) @@ -618,8 +631,8 @@ class TestStockEntry(unittest.TestCase): s2.cancel() def test_retain_sample(self): - from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse from erpnext.stock.doctype.batch.batch import get_batch_qty + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse create_warehouse("Test Warehouse for Sample Retention") frappe.db.set_value("Stock Settings", None, "sample_retention_warehouse", "Test Warehouse for Sample Retention - _TC") diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py index a5623fded23..6c03425a9e2 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class StockEntryDetail(Document): pass diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 1069ec8713e..3d6e26409e1 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -3,9 +3,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class StockEntryType(Document): def validate(self): if self.add_to_transit and self.purpose != 'Material Transfer': diff --git a/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py index 4fa73fd2dca..7eea8f5c35c 100644 --- a/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestStockEntryType(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index be1f00e37fa..caa1d42b662 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -3,14 +3,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + +from datetime import date + import frappe from frappe import _ -from frappe.utils import flt, getdate, add_days, formatdate, get_datetime, cint -from frappe.model.document import Document -from datetime import date -from erpnext.controllers.item_variant import ItemTemplateCannotHaveStock -from erpnext.accounts.utils import get_fiscal_year from frappe.core.doctype.role.role import get_users +from frappe.model.document import Document +from frappe.utils import add_days, cint, flt, formatdate, get_datetime, getdate + +from erpnext.accounts.utils import get_fiscal_year +from erpnext.controllers.item_variant import ItemTemplateCannotHaveStock + class StockFreezeError(frappe.ValidationError): pass class BackDatedStockTransaction(frappe.ValidationError): pass @@ -27,7 +31,7 @@ class StockLedgerEntry(Document): def validate(self): self.flags.ignore_submit_comment = True - from erpnext.stock.utils import validate_warehouse_company, validate_disabled_warehouse + from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company self.validate_mandatory() self.validate_item() self.validate_batch() diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index af2ada8c9a4..61bae49b0bd 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -3,19 +3,25 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from frappe.utils import today, add_days -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \ - import create_stock_reconciliation -from erpnext.stock.doctype.item.test_item import make_item -from erpnext.stock.stock_ledger import get_previous_sle -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt -from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import create_landed_cost_voucher -from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note -from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import BackDatedStockTransaction + +import frappe from frappe.core.page.permission_manager.permission_manager import reset +from frappe.utils import add_days, today + +from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import ( + create_landed_cost_voucher, +) +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry +from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import BackDatedStockTransaction +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, +) +from erpnext.stock.stock_ledger import get_previous_sle + class TestStockLedgerEntry(unittest.TestCase): def setUp(self): diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 4531652a13c..f2c1b9a5153 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -2,15 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -import frappe.defaults -from frappe import msgprint, _ -from frappe.utils import cstr, flt, cint -from erpnext.controllers.stock_controller import StockController + +import frappe +from frappe import _, msgprint +from frappe.utils import cint, cstr, flt + +import erpnext from erpnext.accounts.utils import get_company_default -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos -from erpnext.stock.utils import get_stock_balance, get_incoming_rate, get_available_serial_nos +from erpnext.controllers.stock_controller import StockController from erpnext.stock.doctype.batch.batch import get_batch_qty +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.utils import get_stock_balance + class OpeningEntryAccountError(frappe.ValidationError): pass class EmptyStockReconciliationItemsError(frappe.ValidationError): pass @@ -159,8 +162,11 @@ class StockReconciliation(StockController): raise frappe.ValidationError(self.validation_messages) def validate_item(self, item_code, row): - from erpnext.stock.doctype.item.item import validate_end_of_life, \ - validate_is_stock_item, validate_cancelled_item + from erpnext.stock.doctype.item.item import ( + validate_cancelled_item, + validate_end_of_life, + validate_is_stock_item, + ) # using try except to catch all validation msgs and display together diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index e4381271ed2..8647bee40ec 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -5,16 +5,23 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, unittest -from frappe.utils import flt, nowdate, nowtime, random_string, add_days + +import unittest + +import frappe +from frappe.utils import add_days, flt, nowdate, nowtime, random_string + from erpnext.accounts.utils import get_stock_and_account_balance -from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after -from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items -from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse from erpnext.stock.doctype.item.test_item import create_item -from erpnext.stock.utils import get_incoming_rate, get_stock_value_on, get_valuation_method -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( + EmptyStockReconciliationItemsError, + get_items, +) +from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse +from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after +from erpnext.stock.utils import get_incoming_rate, get_stock_value_on, get_valuation_method from erpnext.tests.utils import change_settings @@ -322,8 +329,8 @@ class TestStockReconciliation(unittest.TestCase): SR3 | Reco | 0 | 1 (posting date: today-1) [backdated & blocked] DN2 | DN | -2 | 8(-1) (posting date: today) """ - from erpnext.stock.stock_ledger import NegativeStockError from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + from erpnext.stock.stock_ledger import NegativeStockError item_code = "Backdated-Reco-Item" warehouse = "_Test Warehouse - _TC" @@ -363,8 +370,8 @@ class TestStockReconciliation(unittest.TestCase): SR | Reco | 100 | 100 (posting date: today-1) (shouldn't be cancelled after DN) DN | DN | 100 | 0 (posting date: today) """ - from erpnext.stock.stock_ledger import NegativeStockError from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + from erpnext.stock.stock_ledger import NegativeStockError frappe.db.commit() item_code = "Backdated-Reco-Cancellation-Item" diff --git a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py index cc1e19dcafb..227e72769b5 100644 --- a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py +++ b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py @@ -2,8 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class StockReconciliationItem(Document): pass diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index 2dd7c6f35b8..2a634b3d16b 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -4,12 +4,14 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document -from frappe.utils.html_utils import clean_html -from frappe.utils import cint from frappe.custom.doctype.property_setter.property_setter import make_property_setter +from frappe.model.document import Document +from frappe.utils import cint +from frappe.utils.html_utils import clean_html + class StockSettings(Document): def validate(self): diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py index 42a78f723d3..7e8090499fb 100644 --- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestStockSettings(unittest.TestCase): def setUp(self): frappe.db.set_value("Stock Settings", None, "clean_description_html", 0) diff --git a/erpnext/stock/doctype/uom_category/test_uom_category.py b/erpnext/stock/doctype/uom_category/test_uom_category.py index 33bd408a572..dd5510a3dd3 100644 --- a/erpnext/stock/doctype/uom_category/test_uom_category.py +++ b/erpnext/stock/doctype/uom_category/test_uom_category.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestUOMCategory(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/uom_category/uom_category.py b/erpnext/stock/doctype/uom_category/uom_category.py index d5c339e1bf3..282ebb2f4e2 100644 --- a/erpnext/stock/doctype/uom_category/uom_category.py +++ b/erpnext/stock/doctype/uom_category/uom_category.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class UOMCategory(Document): pass diff --git a/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py b/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py index fdead205670..9d9d4c6f25b 100644 --- a/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py +++ b/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document + class UOMConversionDetail(Document): pass diff --git a/erpnext/stock/doctype/variant_field/test_variant_field.py b/erpnext/stock/doctype/variant_field/test_variant_field.py index 53024bdac15..408e33b2f70 100644 --- a/erpnext/stock/doctype/variant_field/test_variant_field.py +++ b/erpnext/stock/doctype/variant_field/test_variant_field.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestVariantField(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/variant_field/variant_field.py b/erpnext/stock/doctype/variant_field/variant_field.py index a77301e0e54..abcfdc7030f 100644 --- a/erpnext/stock/doctype/variant_field/variant_field.py +++ b/erpnext/stock/doctype/variant_field/variant_field.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class VariantField(Document): pass diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index 6e429a22552..1ca7181f279 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -5,13 +5,13 @@ from __future__ import unicode_literals import unittest import frappe -from frappe.utils import cint from frappe.test_runner import make_test_records +from frappe.utils import cint import erpnext -from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry -from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account +from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry test_records = frappe.get_test_records('Warehouse') diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 3abc13907cf..ecd8707fa69 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -2,13 +2,18 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe.utils import cint, flt -from frappe import throw, _ + from collections import defaultdict -from frappe.utils.nestedset import NestedSet -from erpnext.stock import get_warehouse_account + +import frappe +from frappe import _, throw from frappe.contacts.address_and_contact import load_address_and_contact +from frappe.utils import cint, flt +from frappe.utils.nestedset import NestedSet + +import erpnext +from erpnext.stock import get_warehouse_account + class Warehouse(NestedSet): nsm_parent_field = 'parent_warehouse' diff --git a/erpnext/stock/doctype/warehouse_type/test_warehouse_type.py b/erpnext/stock/doctype/warehouse_type/test_warehouse_type.py index 39f4b2391bd..846e63be30a 100644 --- a/erpnext/stock/doctype/warehouse_type/test_warehouse_type.py +++ b/erpnext/stock/doctype/warehouse_type/test_warehouse_type.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestWarehouseType(unittest.TestCase): pass diff --git a/erpnext/stock/doctype/warehouse_type/warehouse_type.py b/erpnext/stock/doctype/warehouse_type/warehouse_type.py index 4b7d8d829f9..fd83d787796 100644 --- a/erpnext/stock/doctype/warehouse_type/warehouse_type.py +++ b/erpnext/stock/doctype/warehouse_type/warehouse_type.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class WarehouseType(Document): pass diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index c72073c6143..19597c3d993 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -2,22 +2,27 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + +import json + import frappe from frappe import _, throw -from frappe.utils import flt, cint, add_days, cstr, add_months, getdate -import json, copy -from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item, set_transaction_type -from erpnext.setup.utils import get_exchange_rate from frappe.model.meta import get_field_precision -from erpnext.stock.doctype.batch.batch import get_batch_no -from erpnext import get_company_currency -from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor -from erpnext.stock.doctype.price_list.price_list import get_price_list_details -from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults -from erpnext.setup.doctype.brand.brand import get_brand_defaults -from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no +from frappe.utils import add_days, add_months, cint, cstr, flt, getdate +from six import iteritems, string_types -from six import string_types, iteritems +from erpnext import get_company_currency +from erpnext.accounts.doctype.pricing_rule.pricing_rule import ( + get_pricing_rule_for_item, + set_transaction_type, +) +from erpnext.setup.doctype.brand.brand import get_brand_defaults +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults +from erpnext.setup.utils import get_exchange_rate +from erpnext.stock.doctype.batch.batch import get_batch_no +from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor +from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no +from erpnext.stock.doctype.price_list.price_list import get_price_list_details sales_doctypes = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', 'POS Invoice'] purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice'] @@ -316,8 +321,8 @@ def get_basic_details(args, item, overwrite_warehouse=True): "transaction_date": args.get("transaction_date"), "against_blanket_order": args.get("against_blanket_order"), "bom_no": item.get("default_bom"), - "weight_per_unit": item.get("weight_per_unit"), - "weight_uom": item.get("weight_uom") + "weight_per_unit": args.get("weight_per_unit") or item.get("weight_per_unit"), + "weight_uom": args.get("weight_uom") or item.get("weight_uom") }) if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"): diff --git a/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json b/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json deleted file mode 100644 index 5ee316786ca..00000000000 --- a/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "add_more_button": 1, - "app": "ERPNext", - "creation": "2019-11-15 14:41:12.007359", - "docstatus": 0, - "doctype": "Onboarding Slide", - "domains": [], - "help_links": [], - "idx": 0, - "image_src": "", - "is_completed": 0, - "max_count": 3, - "modified": "2019-12-09 17:54:09.602885", - "modified_by": "Administrator", - "name": "Add A Few Products You Buy Or Sell", - "owner": "Administrator", - "ref_doctype": "Item", - "slide_desc": "", - "slide_fields": [ - { - "align": "", - "fieldname": "item", - "fieldtype": "Data", - "label": "Item", - "placeholder": "Product Name", - "reqd": 1 - }, - { - "align": "", - "fieldname": "item_price", - "fieldtype": "Currency", - "label": "Item Price", - "reqd": 1 - }, - { - "align": "", - "fieldtype": "Column Break", - "reqd": 0 - }, - { - "align": "", - "fieldname": "uom", - "fieldtype": "Link", - "label": "UOM", - "options": "UOM", - "reqd": 1 - } - ], - "slide_order": 30, - "slide_title": "Add A Few Products You Buy Or Sell", - "slide_type": "Create" -} \ No newline at end of file diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 4c721acdc12..3cd4cd27617 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -2,11 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -import erpnext + import json -from frappe.utils import flt, nowdate, add_days, cint + +import frappe from frappe import _ +from frappe.utils import add_days, cint, flt, nowdate + +import erpnext + def reorder_item(): """ Reorder item if stock reaches reorder level""" @@ -166,7 +170,7 @@ def create_material_request(material_requests): mr.submit() mr_list.append(mr) - except: + except Exception: _log_exception() if mr_list: diff --git a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py index 29689b1a912..da57baddc8c 100644 --- a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py +++ b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, cint, getdate +from frappe.utils import cint, getdate + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/stock/report/bom_search/bom_search.py b/erpnext/stock/report/bom_search/bom_search.py index e3955c9a37f..8b583f35880 100644 --- a/erpnext/stock/report/bom_search/bom_search.py +++ b/erpnext/stock/report/bom_search/bom_search.py @@ -2,10 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json +import frappe from six import iteritems + def execute(filters=None): data = [] parents = { diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py index da593a40d68..5f6184d6f35 100644 --- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py +++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py @@ -1,8 +1,8 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from collections import OrderedDict import datetime +from collections import OrderedDict from typing import Dict, List, Tuple, Union import frappe @@ -11,7 +11,6 @@ from frappe.utils import date_diff from erpnext.accounts.report.general_ledger.general_ledger import get_gl_entries - Filters = frappe._dict Row = frappe._dict Data = List[Row] @@ -43,13 +42,13 @@ def validate_filters(filters: Filters) -> None: def get_columns() -> Columns: return [ { - 'label': 'Item Group', + 'label': _('Item Group'), 'fieldname': 'item_group', 'fieldtype': 'Data', 'width': '200' }, { - 'label': 'COGS Debit', + 'label': _('COGS Debit'), 'fieldname': 'cogs_debit', 'fieldtype': 'Currency', 'width': '200' diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.py b/erpnext/stock/report/delayed_item_report/delayed_item_report.py index 61306662c0d..1dd0478b40c 100644 --- a/erpnext/stock/report/delayed_item_report/delayed_item_report.py +++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.py @@ -2,10 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import date_diff + def execute(filters=None, consolidated = False): data, columns = DelayedItemReport(filters).run() diff --git a/erpnext/stock/report/delayed_order_report/delayed_order_report.py b/erpnext/stock/report/delayed_order_report/delayed_order_report.py index d9151606884..677e30c5a41 100644 --- a/erpnext/stock/report/delayed_order_report/delayed_order_report.py +++ b/erpnext/stock/report/delayed_order_report/delayed_order_report.py @@ -2,9 +2,12 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe import _ + from erpnext.stock.report.delayed_item_report.delayed_item_report import DelayedItemReport + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py index 77fd2ff2447..6d03ec1c050 100644 --- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py +++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe import _ -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py index 00125e71a9a..cf273265599 100644 --- a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py +++ b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py @@ -3,8 +3,9 @@ import frappe from frappe import _ -from six import iteritems from frappe.utils import flt +from six import iteritems + def execute(filters=None): columns, data = [], [] diff --git a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py index b3b7594ffd7..5f03c7cbe0a 100644 --- a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py +++ b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py @@ -1,12 +1,15 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -import frappe import copy + +import frappe from frappe import _ from six import iteritems + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + def execute(filters=None): columns, data = [], [] columns = get_columns() diff --git a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py index c8f60a15d64..bc520ae27d9 100644 --- a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py +++ b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py @@ -2,13 +2,16 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe -import erpnext from frappe import _ +from frappe.utils import add_days, getdate, today from six import iteritems -from frappe.utils import add_days, today, getdate -from erpnext.stock.utils import get_stock_value_on + +import erpnext from erpnext.accounts.utils import get_stock_and_account_balance +from erpnext.stock.utils import get_stock_value_on + def execute(filters=None): if not erpnext.is_perpetual_inventory_enabled(filters.company): diff --git a/erpnext/stock/report/item_price_stock/item_price_stock.py b/erpnext/stock/report/item_price_stock/item_price_stock.py index db7498bb215..6ffb5c8a983 100644 --- a/erpnext/stock/report/item_price_stock/item_price_stock.py +++ b/erpnext/stock/report/item_price_stock/item_price_stock.py @@ -1,9 +1,11 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns, data = [], [] columns=get_columns() diff --git a/erpnext/stock/report/item_prices/item_prices.py b/erpnext/stock/report/item_prices/item_prices.py index 12f32972039..aa5ae0ed3d4 100644 --- a/erpnext/stock/report/item_prices/item_prices.py +++ b/erpnext/stock/report/item_prices/item_prices.py @@ -2,10 +2,12 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe -from frappe import msgprint, _ +from frappe import _ from frappe.utils import flt + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.py b/erpnext/stock/report/item_shortage_report/item_shortage_report.py index c67eed7e926..1438e6cda02 100644 --- a/erpnext/stock/report/item_shortage_report/item_shortage_report.py +++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns() conditions = get_conditions(filters) diff --git a/erpnext/stock/report/item_variant_details/item_variant_details.py b/erpnext/stock/report/item_variant_details/item_variant_details.py index d8563d79271..eedda53bed2 100644 --- a/erpnext/stock/report/item_variant_details/item_variant_details.py +++ b/erpnext/stock/report/item_variant_details/item_variant_details.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): columns = get_columns(filters.item) data = get_data(filters.item) diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py index 2e13aa0b040..08869af44ae 100644 --- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py +++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py @@ -4,7 +4,8 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import getdate, flt +from frappe.utils import flt, getdate + def execute(filters=None): if not filters: filters = {} diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.py b/erpnext/stock/report/process_loss_report/process_loss_report.py index 3d48ebde1a5..5c6a3bb4566 100644 --- a/erpnext/stock/report/process_loss_report/process_loss_report.py +++ b/erpnext/stock/report/process_loss_report/process_loss_report.py @@ -1,9 +1,10 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +from typing import Dict, List, Tuple + import frappe from frappe import _ -from typing import Dict, List, Tuple Filters = frappe._dict Row = frappe._dict @@ -92,7 +93,7 @@ def get_query_args(filters: Filters) -> QueryArgs: def run_query(query_args: QueryArgs) -> Data: return frappe.db.sql(""" - SELECT + SELECT wo.name, wo.status, wo.production_item, wo.qty, wo.produced_qty, wo.process_loss_qty, (wo.produced_qty - wo.process_loss_qty) as actual_produced_qty, diff --git a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py index 8fffbccab3c..2e298e7da4d 100644 --- a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py +++ b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt -from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition from six import iteritems +from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition + def execute(filters=None): if not filters: diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py index 0d96ea6aa8e..29595323980 100644 --- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py +++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py @@ -2,9 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + from frappe import _ -from erpnext.controllers.trends import get_columns,get_data + +from erpnext.controllers.trends import get_columns, get_data + def execute(filters=None): if not filters: filters ={} diff --git a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py index cc3aa3522d8..897a130a51a 100644 --- a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py +++ b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe import _ + from erpnext.stock.stock_ledger import get_stock_ledger_entries -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + def execute(filters=None): columns = get_columns(filters) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 8a9f0a5e583..b4eca0ba96a 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -2,17 +2,22 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + +from operator import itemgetter + import frappe from frappe import _ -from frappe.utils import date_diff, flt, cint +from frappe.utils import cint, date_diff, flt from six import iteritems + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + def execute(filters=None): columns = get_columns(filters) item_details = get_fifo_queue(filters) to_date = filters["to_date"] - _func = lambda x: x[1] + _func = itemgetter(1) data = [] for item, item_dict in iteritems(item_details): diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.py b/erpnext/stock/report/stock_analytics/stock_analytics.py index a1e1e7fce7c..ddc831037bf 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/stock_analytics.py @@ -4,13 +4,18 @@ import datetime import frappe from frappe import _, scrub -from frappe.utils import getdate, get_quarter_start, get_first_day_of_week from frappe.utils import get_first_day as get_first_day_of_month +from frappe.utils import get_first_day_of_week, get_quarter_start, getdate -from erpnext.stock.report.stock_balance.stock_balance import (get_items, get_stock_ledger_entries, get_item_details) from erpnext.accounts.utils import get_fiscal_year +from erpnext.stock.report.stock_balance.stock_balance import ( + get_item_details, + get_items, + get_stock_ledger_entries, +) from erpnext.stock.utils import is_reposting_item_valuation_in_progress + def execute(filters=None): is_reposting_item_valuation_in_progress() filters = frappe._dict(filters or {}) diff --git a/erpnext/stock/report/stock_analytics/test_stock_analytics.py b/erpnext/stock/report/stock_analytics/test_stock_analytics.py index 00e268b4e0e..21e1205bfcc 100644 --- a/erpnext/stock/report/stock_analytics/test_stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/test_stock_analytics.py @@ -2,8 +2,8 @@ import datetime import unittest from frappe import _dict -from erpnext.accounts.utils import get_fiscal_year +from erpnext.accounts.utils import get_fiscal_year from erpnext.stock.report.stock_analytics.stock_analytics import get_period_date_ranges diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index 7e0c0e8ab35..f64774a20a8 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -2,12 +2,15 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext + +import frappe from frappe import _ -from erpnext.accounts.utils import get_stock_accounts -from erpnext.accounts.utils import get_currency_precision + +import erpnext +from erpnext.accounts.utils import get_currency_precision, get_stock_accounts from erpnext.stock.doctype.warehouse.warehouse import get_warehouses_based_on_account + def execute(filters=None): if not erpnext.is_perpetual_inventory_enabled(filters.company): frappe.throw(_("Perpetual inventory required for the company {0} to view this report.") diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index fc3d719a780..fc5d5c12da4 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -2,16 +2,20 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe import _ -from frappe.utils import flt, cint, getdate, now, date_diff -from erpnext.stock.utils import add_additional_uom_columns -from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition -from erpnext.stock.utils import is_reposting_item_valuation_in_progress -from erpnext.stock.report.stock_ageing.stock_ageing import get_fifo_queue, get_average_age +from operator import itemgetter + +import frappe +from frappe import _ +from frappe.utils import cint, date_diff, flt, getdate from six import iteritems +import erpnext +from erpnext.stock.report.stock_ageing.stock_ageing import get_average_age, get_fifo_queue +from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition +from erpnext.stock.utils import add_additional_uom_columns, is_reposting_item_valuation_in_progress + + def execute(filters=None): is_reposting_item_valuation_in_progress() if not filters: filters = {} @@ -44,7 +48,7 @@ def execute(filters=None): data = [] conversion_factors = {} - _func = lambda x: x[1] + _func = itemgetter(1) for (company, item, warehouse) in sorted(iwb_map): if item_map.get(item): diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index b6923e97c4f..1ea58fed191 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -4,10 +4,15 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, flt -from erpnext.stock.utils import update_included_uom_in_report, is_reposting_item_valuation_in_progress from frappe import _ +from frappe.utils import cint, flt + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.utils import ( + is_reposting_item_valuation_in_progress, + update_included_uom_in_report, +) + def execute(filters=None): is_reposting_item_valuation_in_progress() diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py index 7956f2e8648..16f7c305a3c 100644 --- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py +++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py @@ -2,11 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt, today -from erpnext.stock.utils import update_included_uom_in_report, is_reposting_item_valuation_in_progress + from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_pos_reserved_qty +from erpnext.stock.utils import ( + is_reposting_item_valuation_in_progress, + update_included_uom_in_report, +) + def execute(filters=None): is_reposting_item_valuation_in_progress() diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py index fa19eeba58b..5580636703e 100644 --- a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py +++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): validate_warehouse(filters) columns = get_columns() diff --git a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py index 4108a575542..f15557b00bf 100644 --- a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py +++ b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import flt from six import iteritems + def execute(filters=None): columns = get_columns(filters) consumed_details = get_consumed_details(filters) diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.py b/erpnext/stock/report/total_stock_summary/total_stock_summary.py index 59c253c425b..779b5aabdbc 100644 --- a/erpnext/stock/report/total_stock_summary/total_stock_summary.py +++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.py @@ -2,9 +2,11 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ + def execute(filters=None): if not filters: filters = {} validate_filters(filters) diff --git a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py index 04f7d347ba8..6cb37513666 100644 --- a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py +++ b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py @@ -5,15 +5,22 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import flt, cint, getdate -from erpnext.stock.report.stock_balance.stock_balance import (get_item_details, - get_item_reorder_details, get_item_warehouse_map, get_items, get_stock_ledger_entries) -from erpnext.stock.report.stock_ageing.stock_ageing import get_fifo_queue, get_average_age -from erpnext.stock.utils import is_reposting_item_valuation_in_progress +from frappe.utils import flt from six import iteritems +from erpnext.stock.report.stock_ageing.stock_ageing import get_average_age, get_fifo_queue +from erpnext.stock.report.stock_balance.stock_balance import ( + get_item_details, + get_item_warehouse_map, + get_items, + get_stock_ledger_entries, +) +from erpnext.stock.utils import is_reposting_item_valuation_in_progress + + def execute(filters=None): is_reposting_item_valuation_in_progress() if not filters: filters = {} diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 8917bfeae4f..1cb0f0d0a49 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -2,11 +2,13 @@ # License: GNU General Public License v3. See license.txt from __future__ import print_function, unicode_literals + import frappe -from frappe.utils import flt, cstr, nowdate, nowtime -from erpnext.stock.utils import update_bin -from erpnext.stock.stock_ledger import update_entries_after +from frappe.utils import cstr, flt, nowdate, nowtime + from erpnext.controllers.stock_controller import create_repost_item_valuation_entry +from erpnext.stock.utils import update_bin + def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False): """ @@ -29,7 +31,7 @@ def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, try: repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin, allow_negative_stock) frappe.db.commit() - except: + except Exception: frappe.db.rollback() if allow_negative_stock: @@ -247,5 +249,5 @@ def reset_serial_no_status_and_warehouse(serial_nos=None): sr.via_stock_ledger = True sr.save() - except: + except Exception: pass diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index afd3ab2b5ae..6f98e314e2a 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -2,17 +2,22 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe -import erpnext import copy -from frappe import _ -from frappe.utils import cint, flt, cstr, now, get_link_to_form, getdate -from frappe.model.meta import get_field_precision -from erpnext.stock.utils import get_valuation_method, get_incoming_outgoing_rate_for_cancel -from erpnext.stock.utils import get_bin import json + +import frappe +from frappe import _ +from frappe.model.meta import get_field_precision +from frappe.utils import cint, cstr, flt, get_link_to_form, getdate, now from six import iteritems +import erpnext +from erpnext.stock.utils import ( + get_bin, + get_incoming_outgoing_rate_for_cancel, + get_valuation_method, +) + # future reposting class NegativeStockError(frappe.ValidationError): pass @@ -271,13 +276,15 @@ class update_entries_after(object): } """ + self.data.setdefault(args.warehouse, frappe._dict()) + warehouse_dict = self.data[args.warehouse] previous_sle = get_previous_sle_of_current_voucher(args) + warehouse_dict.previous_sle = previous_sle - self.data[args.warehouse] = frappe._dict({ - "previous_sle": previous_sle, - "qty_after_transaction": flt(previous_sle.qty_after_transaction), - "valuation_rate": flt(previous_sle.valuation_rate), - "stock_value": flt(previous_sle.stock_value), + for key in ("qty_after_transaction", "valuation_rate", "stock_value"): + setattr(warehouse_dict, key, flt(previous_sle.get(key))) + + warehouse_dict.update({ "prev_stock_value": previous_sle.stock_value or 0.0, "stock_queue": json.loads(previous_sle.stock_queue or "[]"), "stock_value_difference": 0.0 @@ -468,7 +475,9 @@ class update_entries_after(object): # Sales and Purchase Return elif sle.voucher_type in ("Purchase Receipt", "Purchase Invoice", "Delivery Note", "Sales Invoice"): if frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_return"): - from erpnext.controllers.sales_and_purchase_return import get_rate_for_return # don't move this import to top + from erpnext.controllers.sales_and_purchase_return import ( + get_rate_for_return, # don't move this import to top + ) rate = get_rate_for_return(sle.voucher_type, sle.voucher_no, sle.item_code, voucher_detail_no=sle.voucher_detail_no, sle = sle) else: diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 9f6d0a8addd..aeb06e987f8 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -2,13 +2,17 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, erpnext -from frappe import _ -import json -from frappe.utils import flt, cstr, nowdate, nowtime, get_link_to_form +import json + +import frappe +from frappe import _ +from frappe.utils import cstr, flt, get_link_to_form, nowdate, nowtime from six import string_types +import erpnext + + class InvalidWarehouseCompany(frappe.ValidationError): pass def get_stock_value_from_bin(warehouse=None, item_code=None): diff --git a/erpnext/support/__init__.py b/erpnext/support/__init__.py index cc26c14433c..bd1b3f88adc 100644 --- a/erpnext/support/__init__.py +++ b/erpnext/support/__init__.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + install_docs = [ {'doctype':'Role', 'role_name':'Support Team', 'name':'Support Team'}, {'doctype':'Role', 'role_name':'Maintenance User', 'name':'Maintenance User'}, diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 074f1aca0e2..272e3be2648 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -2,17 +2,33 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe + import json -from frappe import _ -from frappe import utils -from frappe.model.document import Document -from frappe.utils import cint, now_datetime, getdate, get_weekdays, add_to_date, get_time, get_datetime, time_diff_in_seconds from datetime import datetime, timedelta -from frappe.model.mapper import get_mapped_doc -from frappe.utils.user import is_website_user -from erpnext.support.doctype.service_level_agreement.service_level_agreement import get_active_service_level_agreement_for + +import frappe +from frappe import _ +from frappe.core.utils import get_parent_doc from frappe.email.inbox import link_communication_to_document +from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc +from frappe.utils import ( + add_to_date, + cint, + date_diff, + get_datetime, + get_time, + get_weekdays, + getdate, + now_datetime, + time_diff_in_seconds, +) +from frappe.utils.user import is_website_user + +from erpnext.support.doctype.service_level_agreement.service_level_agreement import ( + get_active_service_level_agreement_for, +) + class Issue(Document): def get_feed(self): @@ -24,11 +40,9 @@ class Issue(Document): if not self.raised_by: self.raised_by = frappe.session.user - self.change_service_level_agreement_and_priority() self.update_status() self.set_lead_contact(self.raised_by) - if not self.service_level_agreement: self.reset_sla_fields() @@ -293,10 +307,6 @@ class Issue(Document): self.agreement_status = "Ongoing" self.save() - def reset_issue_metrics(self): - self.db_set("resolution_time", None) - self.db_set("user_resolution_time", None) - def get_priority(issue): service_level_agreement = frappe.get_doc("Service Level Agreement", issue.service_level_agreement) @@ -524,5 +534,120 @@ def get_time_in_timedelta(time): """ Converts datetime.time(10, 36, 55, 961454) to datetime.timedelta(seconds=38215) """ - import datetime - return datetime.timedelta(hours=time.hour, minutes=time.minute, seconds=time.second) + return timedelta(hours=time.hour, minutes=time.minute, seconds=time.second) + +def set_first_response_time(communication, method): + if communication.get('reference_doctype') == "Issue": + issue = get_parent_doc(communication) + if is_first_response(issue): + first_response_time = calculate_first_response_time(issue, get_datetime(issue.first_responded_on)) + issue.db_set("first_response_time", first_response_time) + +def is_first_response(issue): + responses = frappe.get_all('Communication', filters = {'reference_name': issue.name, 'sent_or_received': 'Sent'}) + if len(responses) == 1: + return True + return False + +def calculate_first_response_time(issue, first_responded_on): + issue_creation_date = issue.creation + issue_creation_time = get_time_in_seconds(issue_creation_date) + first_responded_on_in_seconds = get_time_in_seconds(first_responded_on) + support_hours = frappe.get_cached_doc("Service Level Agreement", issue.service_level_agreement).support_and_resolution + + if issue_creation_date.day == first_responded_on.day: + if is_work_day(issue_creation_date, support_hours): + start_time, end_time = get_working_hours(issue_creation_date, support_hours) + + # issue creation and response on the same day during working hours + if is_during_working_hours(issue_creation_date, support_hours) and is_during_working_hours(first_responded_on, support_hours): + return get_elapsed_time(issue_creation_date, first_responded_on) + + # issue creation is during working hours, but first response was after working hours + elif is_during_working_hours(issue_creation_date, support_hours): + return get_elapsed_time(issue_creation_time, end_time) + + # issue creation was before working hours but first response is during working hours + elif is_during_working_hours(first_responded_on, support_hours): + return get_elapsed_time(start_time, first_responded_on_in_seconds) + + # both issue creation and first response were after working hours + else: + return 1.0 # this should ideally be zero, but it gets reset when the next response is sent if the value is zero + + else: + return 1.0 + + else: + # response on the next day + if date_diff(first_responded_on, issue_creation_date) == 1: + first_response_time = 0 + else: + first_response_time = calculate_initial_frt(issue_creation_date, date_diff(first_responded_on, issue_creation_date)- 1, support_hours) + + # time taken on day of issue creation + if is_work_day(issue_creation_date, support_hours): + start_time, end_time = get_working_hours(issue_creation_date, support_hours) + + if is_during_working_hours(issue_creation_date, support_hours): + first_response_time += get_elapsed_time(issue_creation_time, end_time) + elif is_before_working_hours(issue_creation_date, support_hours): + first_response_time += get_elapsed_time(start_time, end_time) + + # time taken on day of first response + if is_work_day(first_responded_on, support_hours): + start_time, end_time = get_working_hours(first_responded_on, support_hours) + + if is_during_working_hours(first_responded_on, support_hours): + first_response_time += get_elapsed_time(start_time, first_responded_on_in_seconds) + elif not is_before_working_hours(first_responded_on, support_hours): + first_response_time += get_elapsed_time(start_time, end_time) + + if first_response_time: + return first_response_time + else: + return 1.0 + +def get_time_in_seconds(date): + return timedelta(hours=date.hour, minutes=date.minute, seconds=date.second) + +def get_working_hours(date, support_hours): + if is_work_day(date, support_hours): + weekday = frappe.utils.get_weekday(date) + for day in support_hours: + if day.workday == weekday: + return day.start_time, day.end_time + +def is_work_day(date, support_hours): + weekday = frappe.utils.get_weekday(date) + for day in support_hours: + if day.workday == weekday: + return True + return False + +def is_during_working_hours(date, support_hours): + start_time, end_time = get_working_hours(date, support_hours) + time = get_time_in_seconds(date) + if time >= start_time and time <= end_time: + return True + return False + +def get_elapsed_time(start_time, end_time): + return round(time_diff_in_seconds(end_time, start_time), 2) + +def calculate_initial_frt(issue_creation_date, days_in_between, support_hours): + initial_frt = 0 + for i in range(days_in_between): + date = issue_creation_date + timedelta(days = (i+1)) + if is_work_day(date, support_hours): + start_time, end_time = get_working_hours(date, support_hours) + initial_frt += get_elapsed_time(start_time, end_time) + + return initial_frt + +def is_before_working_hours(date, support_hours): + start_time, end_time = get_working_hours(date, support_hours) + time = get_time_in_seconds(date) + if time < start_time: + return True + return False diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 7da5d7f0ed4..7de5b9abb91 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -2,72 +2,77 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest -from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import create_service_level_agreements_for_issues -from frappe.utils import now_datetime, get_datetime, flt -import datetime -from datetime import timedelta -class TestIssue(unittest.TestCase): +import frappe +from frappe.core.doctype.user_permission.test_user_permission import create_user +from frappe.utils import flt, get_datetime + +from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import ( + create_service_level_agreements_for_issues, +) + + +class TestSetUp(unittest.TestCase): def setUp(self): frappe.db.sql("delete from `tabService Level Agreement`") frappe.db.set_value("Support Settings", None, "track_service_level_agreement", 1) create_service_level_agreements_for_issues() +class TestIssue(TestSetUp): def test_response_time_and_resolution_time_based_on_different_sla(self): - creation = datetime.datetime(2019, 3, 4, 12, 0) + creation = get_datetime("2019-03-04 12:00") # make issue with customer specific SLA customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "_Test Customer", 1) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with customer_group specific SLA customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "__Test Customer", 2) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with territory specific SLA customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory") issue = make_issue(creation, "___Test Customer", 3) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with default SLA issue = make_issue(creation=creation, index=4) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 16:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 18:00")) # make issue with default SLA before working hours - creation = datetime.datetime(2019, 3, 4, 7, 0) + creation = get_datetime("2019-03-04 7:00") issue = make_issue(creation=creation, index=5) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 16, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 16:00")) # make issue with default SLA after working hours - creation = datetime.datetime(2019, 3, 4, 20, 0) + creation = get_datetime("2019-03-04 20:00") issue = make_issue(creation, index=6) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 6, 14, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 6, 16, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-06 14:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 16:00")) # make issue with default SLA next day - creation = datetime.datetime(2019, 3, 4, 14, 0) + creation = get_datetime("2019-03-04 14:00") issue = make_issue(creation=creation, index=7) - self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 18, 0)) - self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0)) + self.assertEqual(issue.response_by, get_datetime("2019-03-04 18:00")) + self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 12:00")) - frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 0) + frappe.flags.current_time = get_datetime("2019-03-04 15:00") issue.status = 'Closed' issue.save() @@ -75,21 +80,21 @@ class TestIssue(unittest.TestCase): self.assertEqual(issue.agreement_status, 'Fulfilled') def test_issue_metrics(self): - creation = datetime.datetime(2020, 3, 4, 4, 0) + creation = get_datetime("2020-03-04 4:00") issue = make_issue(creation, index=1) create_communication(issue.name, "test@example.com", "Received", creation) - creation = datetime.datetime(2020, 3, 4, 4, 15) + creation = get_datetime("2020-03-04 4:15") create_communication(issue.name, "test@admin.com", "Sent", creation) - creation = datetime.datetime(2020, 3, 4, 5, 0) + creation = get_datetime("2020-03-04 5:00") create_communication(issue.name, "test@example.com", "Received", creation) - creation = datetime.datetime(2020, 3, 4, 5, 5) + creation = get_datetime("2020-03-04 5:05") create_communication(issue.name, "test@admin.com", "Sent", creation) - frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 5) + frappe.flags.current_time = get_datetime("2020-03-04 5:05") issue.reload() issue.status = 'Closed' issue.save() @@ -99,33 +104,33 @@ class TestIssue(unittest.TestCase): self.assertEqual(issue.user_resolution_time, 1200) def test_hold_time_on_replied(self): - creation = datetime.datetime(2020, 3, 4, 4, 0) + creation = get_datetime("2020-03-04 4:00") issue = make_issue(creation, index=1) create_communication(issue.name, "test@example.com", "Received", creation) - creation = datetime.datetime(2020, 3, 4, 4, 15) + creation = get_datetime("2020-03-04 4:15") create_communication(issue.name, "test@admin.com", "Sent", creation) - frappe.flags.current_time = datetime.datetime(2020, 3, 4, 4, 15) + frappe.flags.current_time = get_datetime("2020-03-04 4:15") issue.reload() issue.status = 'Replied' issue.save() self.assertEqual(issue.on_hold_since, frappe.flags.current_time) - creation = datetime.datetime(2020, 3, 4, 5, 0) - frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 0) + creation = get_datetime("2020-03-04 5:00") + frappe.flags.current_time = get_datetime("2020-03-04 5:00") create_communication(issue.name, "test@example.com", "Received", creation) issue.reload() self.assertEqual(flt(issue.total_hold_time, 2), 2700) - self.assertEqual(issue.resolution_by, datetime.datetime(2020, 3, 4, 16, 45)) + self.assertEqual(issue.resolution_by, get_datetime("2020-03-04 16:45")) - creation = datetime.datetime(2020, 3, 4, 5, 5) + creation = get_datetime("2020-03-04 5:05") create_communication(issue.name, "test@admin.com", "Sent", creation) - frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 5) + frappe.flags.current_time = get_datetime("2020-03-04 5:05") issue.reload() issue.status = 'Closed' issue.save() @@ -133,6 +138,223 @@ class TestIssue(unittest.TestCase): issue.reload() self.assertEqual(flt(issue.total_hold_time, 2), 2700) +class TestFirstResponseTime(TestSetUp): + # working hours used in all cases: Mon-Fri, 10am to 6pm + # all dates are in the mm-dd-yyyy format + + # issue creation and first response are on the same day + def test_first_response_time_case1(self): + """ + Test frt when issue creation and first response are during working hours on the same day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 11:00"), get_datetime("06-28-2021 12:00")) + self.assertEqual(issue.first_response_time, 3600.0) + + def test_first_response_time_case2(self): + """ + Test frt when issue creation was during working hours, but first response is sent after working hours on the same day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("06-28-2021 20:00")) + self.assertEqual(issue.first_response_time, 21600.0) + + def test_first_response_time_case3(self): + """ + Test frt when issue creation was before working hours but first response is sent during working hours on the same day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("06-28-2021 12:00")) + self.assertEqual(issue.first_response_time, 7200.0) + + def test_first_response_time_case4(self): + """ + Test frt when both issue creation and first response were after working hours on the same day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 19:00"), get_datetime("06-28-2021 20:00")) + self.assertEqual(issue.first_response_time, 1.0) + + def test_first_response_time_case5(self): + """ + Test frt when both issue creation and first response are on the same day, but it's not a work day. + """ + issue = create_issue_and_communication(get_datetime("06-27-2021 10:00"), get_datetime("06-27-2021 11:00")) + self.assertEqual(issue.first_response_time, 1.0) + + # issue creation and first response are on consecutive days + def test_first_response_time_case6(self): + """ + Test frt when the issue was created before working hours and the first response is also sent before working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("06-29-2021 6:00")) + self.assertEqual(issue.first_response_time, 28800.0) + + def test_first_response_time_case7(self): + """ + Test frt when the issue was created before working hours and the first response is sent during working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("06-29-2021 11:00")) + self.assertEqual(issue.first_response_time, 32400.0) + + def test_first_response_time_case8(self): + """ + Test frt when the issue was created before working hours and the first response is sent after working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("06-29-2021 20:00")) + self.assertEqual(issue.first_response_time, 57600.0) + + def test_first_response_time_case9(self): + """ + Test frt when the issue was created before working hours and the first response is sent on the next day, which is not a work day. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 6:00"), get_datetime("06-26-2021 11:00")) + self.assertEqual(issue.first_response_time, 28800.0) + + def test_first_response_time_case10(self): + """ + Test frt when the issue was created during working hours and the first response is sent before working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("06-29-2021 6:00")) + self.assertEqual(issue.first_response_time, 21600.0) + + def test_first_response_time_case11(self): + """ + Test frt when the issue was created during working hours and the first response is also sent during working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("06-29-2021 11:00")) + self.assertEqual(issue.first_response_time, 25200.0) + + def test_first_response_time_case12(self): + """ + Test frt when the issue was created during working hours and the first response is sent after working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("06-29-2021 20:00")) + self.assertEqual(issue.first_response_time, 50400.0) + + def test_first_response_time_case13(self): + """ + Test frt when the issue was created during working hours and the first response is sent on the next day, which is not a work day. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 12:00"), get_datetime("06-26-2021 11:00")) + self.assertEqual(issue.first_response_time, 21600.0) + + def test_first_response_time_case14(self): + """ + Test frt when the issue was created after working hours and the first response is sent before working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("06-29-2021 6:00")) + self.assertEqual(issue.first_response_time, 1.0) + + def test_first_response_time_case15(self): + """ + Test frt when the issue was created after working hours and the first response is sent during working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("06-29-2021 11:00")) + self.assertEqual(issue.first_response_time, 3600.0) + + def test_first_response_time_case16(self): + """ + Test frt when the issue was created after working hours and the first response is also sent after working hours, but on the next day. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("06-29-2021 20:00")) + self.assertEqual(issue.first_response_time, 28800.0) + + def test_first_response_time_case17(self): + """ + Test frt when the issue was created after working hours and the first response is sent on the next day, which is not a work day. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 20:00"), get_datetime("06-26-2021 11:00")) + self.assertEqual(issue.first_response_time, 1.0) + + # issue creation and first response are a few days apart + def test_first_response_time_case18(self): + """ + Test frt when the issue was created before working hours and the first response is also sent before working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("07-01-2021 6:00")) + self.assertEqual(issue.first_response_time, 86400.0) + + def test_first_response_time_case19(self): + """ + Test frt when the issue was created before working hours and the first response is sent during working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("07-01-2021 11:00")) + self.assertEqual(issue.first_response_time, 90000.0) + + def test_first_response_time_case20(self): + """ + Test frt when the issue was created before working hours and the first response is sent after working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 6:00"), get_datetime("07-01-2021 20:00")) + self.assertEqual(issue.first_response_time, 115200.0) + + def test_first_response_time_case21(self): + """ + Test frt when the issue was created before working hours and the first response is sent after a few days, on a holiday. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 6:00"), get_datetime("06-27-2021 11:00")) + self.assertEqual(issue.first_response_time, 28800.0) + + def test_first_response_time_case22(self): + """ + Test frt when the issue was created during working hours and the first response is sent before working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("07-01-2021 6:00")) + self.assertEqual(issue.first_response_time, 79200.0) + + def test_first_response_time_case23(self): + """ + Test frt when the issue was created during working hours and the first response is also sent during working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("07-01-2021 11:00")) + self.assertEqual(issue.first_response_time, 82800.0) + + def test_first_response_time_case24(self): + """ + Test frt when the issue was created during working hours and the first response is sent after working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 12:00"), get_datetime("07-01-2021 20:00")) + self.assertEqual(issue.first_response_time, 108000.0) + + def test_first_response_time_case25(self): + """ + Test frt when the issue was created during working hours and the first response is sent after a few days, on a holiday. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 12:00"), get_datetime("06-27-2021 11:00")) + self.assertEqual(issue.first_response_time, 21600.0) + + def test_first_response_time_case26(self): + """ + Test frt when the issue was created after working hours and the first response is sent before working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("07-01-2021 6:00")) + self.assertEqual(issue.first_response_time, 57600.0) + + def test_first_response_time_case27(self): + """ + Test frt when the issue was created after working hours and the first response is sent during working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("07-01-2021 11:00")) + self.assertEqual(issue.first_response_time, 61200.0) + + def test_first_response_time_case28(self): + """ + Test frt when the issue was created after working hours and the first response is also sent after working hours, but after a few days. + """ + issue = create_issue_and_communication(get_datetime("06-28-2021 20:00"), get_datetime("07-01-2021 20:00")) + self.assertEqual(issue.first_response_time, 86400.0) + + def test_first_response_time_case29(self): + """ + Test frt when the issue was created after working hours and the first response is sent after a few days, on a holiday. + """ + issue = create_issue_and_communication(get_datetime("06-25-2021 20:00"), get_datetime("06-27-2021 11:00")) + self.assertEqual(issue.first_response_time, 1.0) + +def create_issue_and_communication(issue_creation, first_responded_on): + issue = make_issue(issue_creation, index=1) + sender = create_user("test@admin.com") + create_communication(issue.name, sender.email, "Sent", first_responded_on) + issue.reload() + + return issue def make_issue(creation=None, customer=None, index=0, priority=None, issue_type=None): issue = frappe.get_doc({ @@ -185,7 +407,7 @@ def create_territory(territory): def create_communication(reference_name, sender, sent_or_received, creation): - issue = frappe.get_doc({ + communication = frappe.get_doc({ "doctype": "Communication", "communication_type": "Communication", "communication_medium": "Email", @@ -199,4 +421,4 @@ def create_communication(reference_name, sender, sent_or_received, creation): "creation": creation, "reference_name": reference_name }) - issue.save() + communication.save() \ No newline at end of file diff --git a/erpnext/support/doctype/issue_priority/issue_priority.py b/erpnext/support/doctype/issue_priority/issue_priority.py index 514b6cc26ba..1a7daf693d2 100644 --- a/erpnext/support/doctype/issue_priority/issue_priority.py +++ b/erpnext/support/doctype/issue_priority/issue_priority.py @@ -3,9 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import _ + from frappe.model.document import Document + class IssuePriority(Document): pass diff --git a/erpnext/support/doctype/issue_priority/test_issue_priority.py b/erpnext/support/doctype/issue_priority/test_issue_priority.py index 618c93ea9d8..fc9ae687c93 100644 --- a/erpnext/support/doctype/issue_priority/test_issue_priority.py +++ b/erpnext/support/doctype/issue_priority/test_issue_priority.py @@ -3,9 +3,11 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + + class TestIssuePriority(unittest.TestCase): def test_priorities(self): diff --git a/erpnext/support/doctype/issue_type/issue_type.py b/erpnext/support/doctype/issue_type/issue_type.py index f95d09cbf3e..089ae28491a 100644 --- a/erpnext/support/doctype/issue_type/issue_type.py +++ b/erpnext/support/doctype/issue_type/issue_type.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class IssueType(Document): pass diff --git a/erpnext/support/doctype/issue_type/test_issue_type.py b/erpnext/support/doctype/issue_type/test_issue_type.py index 4e3b66a8a4d..06a2de283b5 100644 --- a/erpnext/support/doctype/issue_type/test_issue_type.py +++ b/erpnext/support/doctype/issue_type/test_issue_type.py @@ -3,8 +3,8 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + class TestIssueType(unittest.TestCase): pass diff --git a/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py b/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py index a3b547e4801..37c1f2bff7d 100644 --- a/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py +++ b/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class PauseSLAOnStatus(Document): pass diff --git a/erpnext/support/doctype/service_day/service_day.py b/erpnext/support/doctype/service_day/service_day.py index 3805b5aa390..da96cad4172 100644 --- a/erpnext/support/doctype/service_day/service_day.py +++ b/erpnext/support/doctype/service_day/service_day.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ServiceDay(Document): pass diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 00060b95300..62784f450f0 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -2,7 +2,7 @@ // For license information, please see license.txt frappe.ui.form.on('Service Level Agreement', { - setup: function(frm) { + refresh: function(frm) { let allow_statuses = []; const exclude_statuses = ['Open', 'Closed', 'Resolved']; diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 11812426d67..0c292d25830 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -5,11 +5,12 @@ from __future__ import unicode_literals import frappe -from frappe.model.document import Document from frappe import _ -from frappe.utils import getdate, get_weekdays, get_link_to_form, nowdate +from frappe.model.document import Document +from frappe.utils import get_link_to_form, get_weekdays, getdate, nowdate from frappe.utils.safe_exec import get_safe_globals + class ServiceLevelAgreement(Document): def validate(self): diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py index 7e7a405d6e7..22e2c374e12 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py @@ -1,5 +1,6 @@ from frappe import _ + def get_data(): return { 'fieldname': 'service_level_agreement', diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 07ef368cbe3..824ce051906 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -3,11 +3,14 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest + +import frappe + from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group from erpnext.support.doctype.issue_priority.test_issue_priority import make_priorities + class TestServiceLevelAgreement(unittest.TestCase): def setUp(self): frappe.db.sql("delete from `tabService Level Agreement`") @@ -145,16 +148,6 @@ def create_service_level_agreement(default_service_level_agreement, holiday_list "workday": "Friday", "start_time": "10:00:00", "end_time": "18:00:00", - }, - { - "workday": "Saturday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Sunday", - "start_time": "10:00:00", - "end_time": "18:00:00", } ] }) diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.py b/erpnext/support/doctype/service_level_priority/service_level_priority.py index 0c0fe4a0669..3b2d124a692 100644 --- a/erpnext/support/doctype/service_level_priority/service_level_priority.py +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class ServiceLevelPriority(Document): pass diff --git a/erpnext/support/doctype/support_search_source/support_search_source.py b/erpnext/support/doctype/support_search_source/support_search_source.py index 93e503a4366..50f4714f731 100644 --- a/erpnext/support/doctype/support_search_source/support_search_source.py +++ b/erpnext/support/doctype/support_search_source/support_search_source.py @@ -3,7 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals + from frappe.model.document import Document + class SupportSearchSource(Document): pass diff --git a/erpnext/support/doctype/support_settings/support_settings.py b/erpnext/support/doctype/support_settings/support_settings.py index bb3c53ab6db..73aad9d82fd 100644 --- a/erpnext/support/doctype/support_settings/support_settings.py +++ b/erpnext/support/doctype/support_settings/support_settings.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + from frappe.model.document import Document + class SupportSettings(Document): pass diff --git a/erpnext/support/doctype/support_settings/test_support_settings.py b/erpnext/support/doctype/support_settings/test_support_settings.py index 9c47f968119..e9ec070b3aa 100644 --- a/erpnext/support/doctype/support_settings/test_support_settings.py +++ b/erpnext/support/doctype/support_settings/test_support_settings.py @@ -5,5 +5,6 @@ from __future__ import unicode_literals import unittest + class TestSupportSettings(unittest.TestCase): pass diff --git a/erpnext/support/doctype/warranty_claim/test_warranty_claim.py b/erpnext/support/doctype/warranty_claim/test_warranty_claim.py index 909675a0d51..dac8f034c30 100644 --- a/erpnext/support/doctype/warranty_claim/test_warranty_claim.py +++ b/erpnext/support/doctype/warranty_claim/test_warranty_claim.py @@ -2,9 +2,10 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest +import frappe + test_records = frappe.get_test_records('Warranty Claim') class TestWarrantyClaim(unittest.TestCase): diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.py b/erpnext/support/doctype/warranty_claim/warranty_claim.py index a20e7a801b0..5fb11242a9d 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.py +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.py @@ -3,14 +3,14 @@ from __future__ import unicode_literals + import frappe -from frappe import session, _ -from frappe.utils import today, now_datetime - - +from frappe import _, session +from frappe.utils import now_datetime from erpnext.utilities.transaction_base import TransactionBase + class WarrantyClaim(TransactionBase): def get_feed(self): return _("{0}: From {1}").format(self.status, self.customer_name) diff --git a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py index 69bf2730d35..cb7a8a629e5 100644 --- a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py +++ b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py @@ -2,8 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe + def execute(filters=None): columns = [ { diff --git a/erpnext/support/report/issue_analytics/issue_analytics.py b/erpnext/support/report/issue_analytics/issue_analytics.py index 54fce0b3592..ac8bce104fa 100644 --- a/erpnext/support/report/issue_analytics/issue_analytics.py +++ b/erpnext/support/report/issue_analytics/issue_analytics.py @@ -2,13 +2,17 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json -from six import iteritems + +import frappe from frappe import _, scrub -from frappe.utils import getdate, flt, add_to_date, add_days +from frappe.utils import add_days, add_to_date, flt, getdate +from six import iteritems + from erpnext.accounts.utils import get_fiscal_year + def execute(filters=None): return IssueAnalytics(filters).run() @@ -103,7 +107,7 @@ class IssueAnalytics(object): return period def get_period_date_ranges(self): - from dateutil.relativedelta import relativedelta, MO + from dateutil.relativedelta import MO, relativedelta from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date) increment = { diff --git a/erpnext/support/report/issue_analytics/test_issue_analytics.py b/erpnext/support/report/issue_analytics/test_issue_analytics.py index a9d961a4592..1de03ab28dc 100644 --- a/erpnext/support/report/issue_analytics/test_issue_analytics.py +++ b/erpnext/support/report/issue_analytics/test_issue_analytics.py @@ -1,11 +1,16 @@ from __future__ import unicode_literals + import unittest + import frappe -from frappe.utils import getdate, add_months -from erpnext.support.report.issue_analytics.issue_analytics import execute -from erpnext.support.doctype.issue.test_issue import make_issue, create_customer -from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import create_service_level_agreements_for_issues from frappe.desk.form.assign_to import add as add_assignment +from frappe.utils import add_months, getdate + +from erpnext.support.doctype.issue.test_issue import create_customer, make_issue +from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import ( + create_service_level_agreements_for_issues, +) +from erpnext.support.report.issue_analytics.issue_analytics import execute months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] diff --git a/erpnext/support/report/issue_summary/issue_summary.py b/erpnext/support/report/issue_summary/issue_summary.py index 7c4af39f104..04819966095 100644 --- a/erpnext/support/report/issue_summary/issue_summary.py +++ b/erpnext/support/report/issue_summary/issue_summary.py @@ -2,11 +2,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe + import json -from six import iteritems + +import frappe from frappe import _, scrub from frappe.utils import flt +from six import iteritems + def execute(filters=None): return IssueSummary(filters).run() diff --git a/erpnext/support/report/support_hour_distribution/support_hour_distribution.py b/erpnext/support/report/support_hour_distribution/support_hour_distribution.py index 08802b4f5ea..c0bec3c9552 100644 --- a/erpnext/support/report/support_hour_distribution/support_hour_distribution.py +++ b/erpnext/support/report/support_hour_distribution/support_hour_distribution.py @@ -2,9 +2,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.utils import add_to_date, getdate, get_datetime +from frappe.utils import add_to_date, get_datetime, getdate from six import iteritems time_slots = { diff --git a/erpnext/support/web_form/issues/issues.py b/erpnext/support/web_form/issues/issues.py index 2334f8b26d8..f57de916dd1 100644 --- a/erpnext/support/web_form/issues/issues.py +++ b/erpnext/support/web_form/issues/issues.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import frappe def get_context(context): # do your magic here diff --git a/erpnext/telephony/doctype/call_log/call_log.py b/erpnext/telephony/doctype/call_log/call_log.py index 6f8e4116956..0c1ea1657a7 100644 --- a/erpnext/telephony/doctype/call_log/call_log.py +++ b/erpnext/telephony/doctype/call_log/call_log.py @@ -3,14 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals + import frappe from frappe import _ -from frappe.model.document import Document -from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup, strip_number from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links +from frappe.model.document import Document from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number +from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup, strip_number END_CALL_STATUSES = ['No Answer', 'Completed', 'Busy', 'Failed'] ONGOING_CALL_STATUSES = ['Ringing', 'In Progress'] diff --git a/erpnext/telephony/doctype/call_log/test_call_log.py b/erpnext/telephony/doctype/call_log/test_call_log.py index faa63041ba3..f8d458d5415 100644 --- a/erpnext/telephony/doctype/call_log/test_call_log.py +++ b/erpnext/telephony/doctype/call_log/test_call_log.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestCallLog(unittest.TestCase): pass diff --git a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py index fcf29745e2b..f48c808331d 100644 --- a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py +++ b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class IncomingCallHandlingSchedule(Document): pass diff --git a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py index 2b2008a8ab7..faeff9024da 100644 --- a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py +++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py @@ -3,11 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe.model.document import Document + from datetime import datetime from typing import Tuple + +import frappe from frappe import _ +from frappe.model.document import Document + class IncomingCallSettings(Document): def validate(self): diff --git a/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py b/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py index c058c117b32..243e3d9aeab 100644 --- a/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py +++ b/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestIncomingCallSettings(unittest.TestCase): pass diff --git a/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py b/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py index 85d6adda093..810b717ae61 100644 --- a/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py +++ b/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py @@ -6,5 +6,6 @@ from __future__ import unicode_literals # import frappe import unittest + class TestVoiceCallSettings(unittest.TestCase): pass diff --git a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py index ad3bbf1784d..fc0e338c15e 100644 --- a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py +++ b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py @@ -3,8 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals + # import frappe from frappe.model.document import Document + class VoiceCallSettings(Document): pass diff --git a/erpnext/templates/generators/item/item.html b/erpnext/templates/generators/item/item.html index 663ea79f4ec..89436343c7a 100644 --- a/erpnext/templates/generators/item/item.html +++ b/erpnext/templates/generators/item/item.html @@ -1,4 +1,5 @@ {% extends "templates/web.html" %} +{% from "erpnext/templates/includes/macros.html" import recommended_item_row %} {% block title %} {{ title }} {% endblock %} @@ -9,21 +10,65 @@ {% endblock %} {% block page_content %} -
    +
    {% from "erpnext/templates/includes/macros.html" import product_image %}
    +
    {% include "templates/generators/item/item_image.html" %} {% include "templates/generators/item/item_details.html" %}
    - - {% include "templates/generators/item/item_specifications.html" %} - - {{ doc.website_content or '' }}
    + + +
    + {% set show_recommended_items = recommended_items and shopping_cart.cart_settings.enable_recommendations %} + {% set info_col = 'col-9' if show_recommended_items else 'col-12' %} + + {% set padding_top = 'pt-0' if (show_tabs and tabs) else '' %} + +
    +
    +
    + + {% if show_tabs and tabs %} +
    + + {{ web_block("Section with Tabs", values=tabs, add_container=0, + add_top_padding=0, add_bottom_padding=0) + }} +
    + {% elif website_specifications %} + {% include "templates/generators/item/item_specifications.html"%} + {% endif %} + + + {{ doc.website_content or '' }} + + + {% if shopping_cart.cart_settings.enable_reviews and not doc.has_variants %} + {% include "templates/generators/item/item_reviews.html"%} + {% endif %} +
    +
    +
    + + + {% if show_recommended_items %} + + {% endif %} + +
    {% endblock %} {% block base_scripts %} diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html index 167c848eff1..8000a2446be 100644 --- a/erpnext/templates/generators/item/item_add_to_cart.html +++ b/erpnext/templates/generators/item/item_add_to_cart.html @@ -5,54 +5,115 @@
    + {% if cart_settings.show_price and product_info.price %} -
    - {{ product_info.price.formatted_price_sales_uom }} - ({{ product_info.price.formatted_price }} / {{ product_info.uom }}) -
    + {% set price_info = product_info.price %} + +
    + + {{ price_info.formatted_price_sales_uom }} + + + {% if price_info.formatted_mrp %} + + MRP {{ price_info.formatted_mrp }} + + + -{{ price_info.get("formatted_discount_percent") or price_info.get("formatted_discount_rate")}} + + {% endif %} + + + + ({{ price_info.formatted_price }} / {{ product_info.uom }}) + +
    {% else %} {{ _("UOM") }} : {{ product_info.uom }} {% endif %} {% if cart_settings.show_stock_availability %} -
    - {% if product_info.in_stock == 0 %} - - {{ _('Not in stock') }} - +
    + {% if product_info.get("on_backorder") %} + + {{ _('Available on backorder') }} + + {% elif product_info.in_stock == 0 %} + + {{ _('Out of stock') }} + {% elif product_info.in_stock == 1 %} - - {{ _('In stock') }} - {% if product_info.show_stock_qty and product_info.stock_qty %} - ({{ product_info.stock_qty[0][0] }}) - {% endif %} - + + {{ _('In stock') }} + {% if product_info.show_stock_qty and product_info.stock_qty %} + ({{ product_info.stock_qty[0][0] }}) + {% endif %} + {% endif %}
    {% endif %} -
    - {% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %} - - {{ _("View in Cart") }} - - - {% endif %} - {% if cart_settings.show_contact_us_button %} - {% include "templates/generators/item/item_inquiry.html" %} - {% endif %} +
    +

    + {{ _(offer.offer_title) }}: + {{ _(offer.offer_subtitle) if offer.offer_subtitle else '' }} + + {{ _("More") }} + +

    +
    + {% endfor %} +
    + {% endif %} + + +
    +
    + + {% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %} + + + {% endif %} + + + {% if cart_settings.show_contact_us_button %} + {% include "templates/generators/item/item_inquiry.html" %} + {% endif %} +
    @@ -60,10 +121,11 @@ {% endif %} diff --git a/erpnext/templates/generators/item/item_configure.html b/erpnext/templates/generators/item/item_configure.html index b61ac73072d..fcab594402b 100644 --- a/erpnext/templates/generators/item/item_configure.html +++ b/erpnext/templates/generators/item/item_configure.html @@ -3,11 +3,11 @@
    {% if cart_settings.enable_variants | int %} - {% endif %} {% if cart_settings.show_contact_us_button %} diff --git a/erpnext/templates/generators/item/item_configure.js b/erpnext/templates/generators/item/item_configure.js index 8eadb842899..b5f92989ef4 100644 --- a/erpnext/templates/generators/item/item_configure.js +++ b/erpnext/templates/generators/item/item_configure.js @@ -29,7 +29,7 @@ class ItemConfigure { }); this.dialog = new frappe.ui.Dialog({ - title: __('Configure {0}', [this.item_name]), + title: __('Select Variant for {0}', [this.item_name]), fields, on_hide: () => { set_continue_configuration(); @@ -201,7 +201,7 @@ class ItemConfigure { ${frappe.utils.icon('assets', 'md')} - ${__("Add to Cart")}s + ${__("Add to Cart")} ` : ''; @@ -214,7 +214,7 @@ class ItemConfigure { ? `