Merge branch 'version-13-hotfix' into version-13-pre-release
This commit is contained in:
commit
27299cfcc5
12
.git-blame-ignore-revs
Normal file
12
.git-blame-ignore-revs
Normal file
@ -0,0 +1,12 @@
|
||||
# Since version 2.23 (released in August 2019), git-blame has a feature
|
||||
# to ignore or bypass certain commits.
|
||||
#
|
||||
# This file contains a list of commits that are not likely what you
|
||||
# are looking for in a blame, such as mass reformatting or renaming.
|
||||
# You can set this file as a default ignore file for blame by running
|
||||
# the following command.
|
||||
#
|
||||
# $ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
|
||||
# This commit just changes spaces to tabs for indentation in some files
|
||||
5f473611bd6ed57703716244a054d3fb5ba9cd23
|
73
.github/workflows/patch.yml
vendored
Normal file
73
.github/workflows/patch.yml
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
name: Patch
|
||||
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
name: Patch Test
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.3
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: YES
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.6
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
|
||||
- name: Run Patch Tests
|
||||
run: |
|
||||
cd ~/frappe-bench/
|
||||
wget https://erpnext.com/files/v10-erpnext.sql.gz
|
||||
bench --site test_site --force restore ~/frappe-bench/v10-erpnext.sql.gz
|
||||
bench --site test_site migrate
|
@ -1,6 +1,6 @@
|
||||
name: CI
|
||||
name: Server
|
||||
|
||||
on: [pull_request, workflow_dispatch, push]
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@ -10,15 +10,9 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- TYPE: "server"
|
||||
JOB_NAME: "Server"
|
||||
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --coverage
|
||||
- TYPE: "patch"
|
||||
JOB_NAME: "Patch"
|
||||
RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
|
||||
container: [1, 2, 3]
|
||||
|
||||
name: ${{ matrix.JOB_NAME }}
|
||||
name: Python Unit Tests
|
||||
|
||||
services:
|
||||
mysql:
|
||||
@ -36,7 +30,7 @@ jobs:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.6
|
||||
python-version: 3.7
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
@ -49,6 +43,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
@ -60,6 +55,7 @@ jobs:
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
@ -76,33 +72,39 @@ jobs:
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
|
||||
- name: Run Tests
|
||||
run: ${{ matrix.RUN_COMMAND }}
|
||||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator --with-coverage
|
||||
env:
|
||||
TYPE: ${{ matrix.TYPE }}
|
||||
TYPE: server
|
||||
CI_BUILD_ID: ${{ github.run_id }}
|
||||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
||||
|
||||
- name: Coverage - Pull Request
|
||||
if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
|
||||
- name: Upload Coverage Data
|
||||
run: |
|
||||
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
||||
cd ${GITHUB_WORKSPACE}
|
||||
pip install coveralls==2.2.0
|
||||
pip install coverage==4.5.4
|
||||
coveralls --service=github
|
||||
pip3 install coverage==5.5
|
||||
pip3 install coveralls==3.0.1
|
||||
coveralls
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||
COVERALLS_SERVICE_NAME: github
|
||||
|
||||
- name: Coverage - Push
|
||||
if: matrix.TYPE == 'server' && github.event_name == 'push'
|
||||
run: |
|
||||
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
||||
cd ${GITHUB_WORKSPACE}
|
||||
pip install coveralls==2.2.0
|
||||
pip install coverage==4.5.4
|
||||
coveralls --service=github-actions
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||
COVERALLS_SERVICE_NAME: github-actions
|
||||
COVERALLS_FLAG_NAME: run-${{ matrix.container }}
|
||||
COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }}
|
||||
COVERALLS_PARALLEL: true
|
||||
|
||||
coveralls:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
container: python:3-slim
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Coveralls Finished
|
||||
run: |
|
||||
cd ${GITHUB_WORKSPACE}
|
||||
pip3 install coverage==5.5
|
||||
pip3 install coveralls==3.0.1
|
||||
coveralls --finish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@ -27,7 +27,7 @@ class AccountingDimension(Document):
|
||||
exists = frappe.db.get_value("Accounting Dimension", {'document_type': self.document_type}, ['name'])
|
||||
|
||||
if exists and self.is_new():
|
||||
frappe.throw("Document Type already used as a dimension")
|
||||
frappe.throw(_("Document Type already used as a dimension"))
|
||||
|
||||
if not self.is_new():
|
||||
self.validate_document_type_change()
|
||||
|
@ -7,7 +7,8 @@ import frappe
|
||||
import unittest
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import delete_accounting_dimension
|
||||
|
||||
test_dependencies = ['Cost Center', 'Location', 'Warehouse', 'Department']
|
||||
|
||||
class TestAccountingDimension(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -9,6 +9,8 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
|
||||
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']
|
||||
|
||||
class TestAccountingDimensionFilter(unittest.TestCase):
|
||||
def setUp(self):
|
||||
create_dimension()
|
||||
|
@ -10,6 +10,8 @@ from erpnext.accounts.general_ledger import ClosedAccountingPeriod
|
||||
from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
test_dependencies = ['Item']
|
||||
|
||||
class TestAccountingPeriod(unittest.TestCase):
|
||||
def test_overlap(self):
|
||||
ap1 = create_accounting_period(start_date = "2018-04-01",
|
||||
@ -38,7 +40,7 @@ def create_accounting_period(**args):
|
||||
accounting_period.start_date = args.start_date or nowdate()
|
||||
accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
|
||||
accounting_period.company = args.company or "_Test Company"
|
||||
accounting_period.period_name =args.period_name or "_Test_Period_Name_1"
|
||||
accounting_period.period_name = args.period_name or "_Test_Period_Name_1"
|
||||
accounting_period.append("closed_documents", {
|
||||
"document_type": 'Sales Invoice', "closed": 1
|
||||
})
|
||||
|
@ -18,6 +18,7 @@
|
||||
"delete_linked_ledger_entries",
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"unlink_advance_payment_on_cancelation_of_order",
|
||||
"post_change_gl_entries",
|
||||
"tax_settings_section",
|
||||
"determine_address_tax_category_from",
|
||||
"column_break_19",
|
||||
@ -253,6 +254,12 @@
|
||||
{
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "post_change_gl_entries",
|
||||
"fieldtype": "Check",
|
||||
"label": "Post Ledger Entries for Given Change"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
@ -260,7 +267,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-30 15:25:10.381008",
|
||||
"modified": "2021-05-25 12:34:05.858669",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
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
|
||||
@ -24,7 +25,7 @@ class AccountsSettings(Document):
|
||||
def validate_stale_days(self):
|
||||
if not self.allow_stale and cint(self.stale_days) <= 0:
|
||||
frappe.msgprint(
|
||||
"Stale Days should start from 1.", title='Error', indicator='red',
|
||||
_("Stale Days should start from 1."), title='Error', indicator='red',
|
||||
raise_exception=1)
|
||||
|
||||
def enable_payment_schedule_in_print(self):
|
||||
|
@ -120,4 +120,4 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||
plaid_success(token, response) {
|
||||
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
|
||||
}
|
||||
};
|
||||
};
|
@ -11,6 +11,8 @@ from erpnext.buying.doctype.purchase_order.test_purchase_order import create_pur
|
||||
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']
|
||||
|
||||
class TestBudget(unittest.TestCase):
|
||||
def test_monthly_budget_crossed_ignore(self):
|
||||
set_total_expense_zero(nowdate(), "cost_center")
|
||||
|
@ -22,7 +22,7 @@ def validate_company(company):
|
||||
'allow_account_creation_against_child_company'])
|
||||
|
||||
if parent_company and (not allow_account_creation_against_child_company):
|
||||
msg = _("{} is a child company. ").format(frappe.bold(company))
|
||||
msg = _("{} is a child company.").format(frappe.bold(company)) + " "
|
||||
msg += _("Please import accounts against parent company or enable {} in company master.").format(
|
||||
frappe.bold('Allow Account Creation Against Child Company'))
|
||||
frappe.throw(msg, title=_('Wrong Company'))
|
||||
@ -56,7 +56,7 @@ def get_file(file_name):
|
||||
extension = extension.lstrip(".")
|
||||
|
||||
if extension not in ('csv', 'xlsx', 'xls'):
|
||||
frappe.throw("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload")
|
||||
frappe.throw(_("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload"))
|
||||
|
||||
return file_doc, extension
|
||||
|
||||
@ -293,7 +293,7 @@ def validate_accounts(file_name):
|
||||
accounts_dict = {}
|
||||
for account in accounts:
|
||||
accounts_dict.setdefault(account["account_name"], account)
|
||||
if not hasattr(account, "parent_account"):
|
||||
if "parent_account" not in account:
|
||||
msg = _("Please make sure the file you are using has 'Parent Account' column present in the header.")
|
||||
msg += "<br><br>"
|
||||
msg += _("Alternatively, you can download the template and fill your data in.")
|
||||
|
@ -29,7 +29,7 @@ class TestDunning(unittest.TestCase):
|
||||
self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
|
||||
self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
|
||||
self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
|
||||
|
||||
|
||||
def test_gl_entries(self):
|
||||
dunning = create_dunning()
|
||||
dunning.submit()
|
||||
|
@ -49,11 +49,11 @@ class InvoiceDiscounting(AccountsController):
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.set_status()
|
||||
self.set_status(cancel=1)
|
||||
self.update_sales_invoice()
|
||||
self.make_gl_entries()
|
||||
|
||||
def set_status(self, status=None):
|
||||
def set_status(self, status=None, cancel=0):
|
||||
if status:
|
||||
self.status = status
|
||||
self.db_set("status", status)
|
||||
@ -66,6 +66,9 @@ class InvoiceDiscounting(AccountsController):
|
||||
elif self.docstatus == 2:
|
||||
self.status = "Cancelled"
|
||||
|
||||
if cancel:
|
||||
self.db_set('status', self.status, update_modified = True)
|
||||
|
||||
def update_sales_invoice(self):
|
||||
for d in self.invoices:
|
||||
if self.docstatus == 1:
|
||||
|
@ -65,7 +65,6 @@ class PaymentEntry(AccountsController):
|
||||
self.set_status()
|
||||
|
||||
def on_submit(self):
|
||||
self.setup_party_account_field()
|
||||
if self.difference_amount:
|
||||
frappe.throw(_("Difference Amount must be zero"))
|
||||
self.make_gl_entries()
|
||||
@ -78,7 +77,6 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||
self.setup_party_account_field()
|
||||
self.make_gl_entries(cancel=1)
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
@ -122,6 +120,11 @@ class PaymentEntry(AccountsController):
|
||||
if flt(d.allocated_amount) > flt(d.outstanding_amount):
|
||||
frappe.throw(_("Row #{0}: Allocated Amount cannot be greater than outstanding amount.").format(d.idx))
|
||||
|
||||
# Check for negative outstanding invoices as well
|
||||
if flt(d.allocated_amount) < 0:
|
||||
if flt(d.allocated_amount) < flt(d.outstanding_amount):
|
||||
frappe.throw(_("Row #{0}: Allocated Amount cannot be greater than outstanding amount.").format(d.idx))
|
||||
|
||||
def delink_advance_entry_references(self):
|
||||
for reference in self.references:
|
||||
if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
@ -177,7 +180,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
for field, value in iteritems(ref_details):
|
||||
if field == 'exchange_rate' or not d.get(field) or force:
|
||||
d.set(field, value)
|
||||
d.db_set(field, value)
|
||||
|
||||
def validate_payment_type(self):
|
||||
if self.payment_type not in ("Receive", "Pay", "Internal Transfer"):
|
||||
@ -386,6 +389,8 @@ class PaymentEntry(AccountsController):
|
||||
else:
|
||||
self.status = 'Draft'
|
||||
|
||||
self.db_set('status', self.status, update_modified = True)
|
||||
|
||||
def set_amounts(self):
|
||||
self.set_amounts_in_company_currency()
|
||||
self.set_total_allocated_amount()
|
||||
@ -791,7 +796,7 @@ def split_invoices_based_on_payment_terms(outstanding_invoices):
|
||||
|
||||
outstanding_invoices.pop(idx - 1)
|
||||
outstanding_invoices += invoice_ref_based_on_payment_terms[idx]
|
||||
|
||||
|
||||
return outstanding_invoices
|
||||
|
||||
def get_orders_to_be_billed(posting_date, party_type, party,
|
||||
@ -989,6 +994,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
outstanding_amount = ref_doc.get("outstanding_amount")
|
||||
elif reference_doctype == "Donation":
|
||||
total_amount = ref_doc.get("amount")
|
||||
outstanding_amount = total_amount
|
||||
exchange_rate = 1
|
||||
elif reference_doctype == "Dunning":
|
||||
total_amount = ref_doc.get("dunning_amount")
|
||||
|
@ -101,7 +101,7 @@ class PaymentRequest(Document):
|
||||
|
||||
controller.validate_transaction_currency(self.currency)
|
||||
controller.request_for_payment(**payment_record)
|
||||
|
||||
|
||||
def get_request_amount(self):
|
||||
data_of_completed_requests = frappe.get_all("Integration Request", filters={
|
||||
'reference_doctype': self.doctype,
|
||||
@ -492,7 +492,6 @@ def update_payment_req_status(doc, method):
|
||||
status = 'Requested'
|
||||
|
||||
pay_req_doc.db_set('status', status)
|
||||
frappe.db.commit()
|
||||
|
||||
def get_dummy_message(doc):
|
||||
return frappe.render_template("""{% if doc.contact_person -%}
|
||||
|
@ -1,350 +1,138 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ACC-PCV-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:07",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"autoname": "ACC-PCV-.YYYY.-.#####",
|
||||
"creation": "2013-01-10 16:34:07",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"transaction_date",
|
||||
"posting_date",
|
||||
"fiscal_year",
|
||||
"amended_from",
|
||||
"company",
|
||||
"cost_center_wise_pnl",
|
||||
"column_break1",
|
||||
"closing_account_head",
|
||||
"remarks"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Transaction Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "transaction_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Transaction Date",
|
||||
"oldfieldname": "transaction_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "posting_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Posting Date",
|
||||
"oldfieldname": "posting_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Closing Fiscal Year",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"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": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Closing Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "amended_from",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Period Closing Voucher",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "amended_from",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Period Closing Voucher",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Select",
|
||||
"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",
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
|
||||
"fieldname": "closing_account_head",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Closing Account Head",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "closing_account_head",
|
||||
"oldfieldtype": "Link",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
|
||||
"fieldname": "closing_account_head",
|
||||
"fieldtype": "Link",
|
||||
"label": "Closing Account Head",
|
||||
"oldfieldname": "closing_account_head",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "remarks",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Remarks",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "remarks",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "remarks",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Remarks",
|
||||
"oldfieldname": "remarks",
|
||||
"oldfieldtype": "Small Text",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "cost_center_wise_pnl",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Cost Center Wise Profit/Loss"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2020-09-18 17:26:09.703215",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Period Closing Voucher",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-05-20 15:27:37.210458",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Period Closing Voucher",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "posting_date, fiscal_year",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "closing_account_head",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"search_fields": "posting_date, fiscal_year",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "closing_account_head"
|
||||
}
|
@ -51,63 +51,96 @@ class PeriodClosingVoucher(AccountsController):
|
||||
|
||||
def make_gl_entries(self):
|
||||
gl_entries = []
|
||||
net_pl_balance = 0
|
||||
dimension_fields = ['t1.cost_center']
|
||||
net_pl_balance = 0
|
||||
|
||||
accounting_dimensions = get_accounting_dimensions()
|
||||
for dimension in accounting_dimensions:
|
||||
dimension_fields.append('t1.{0}'.format(dimension))
|
||||
|
||||
dimension_filters, default_dimensions = get_dimensions()
|
||||
|
||||
pl_accounts = self.get_pl_balances(dimension_fields)
|
||||
pl_accounts = self.get_pl_balances()
|
||||
|
||||
for acc in pl_accounts:
|
||||
if flt(acc.balance_in_company_currency):
|
||||
if flt(acc.bal_in_company_currency):
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": acc.account,
|
||||
"cost_center": acc.cost_center,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
|
||||
if flt(acc.balance_in_account_currency) < 0 else 0,
|
||||
"debit": abs(flt(acc.balance_in_company_currency)) \
|
||||
if flt(acc.balance_in_company_currency) < 0 else 0,
|
||||
"credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
|
||||
if flt(acc.balance_in_account_currency) > 0 else 0,
|
||||
"credit": abs(flt(acc.balance_in_company_currency)) \
|
||||
if flt(acc.balance_in_company_currency) > 0 else 0
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
|
||||
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
||||
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
|
||||
}, item=acc))
|
||||
|
||||
net_pl_balance += flt(acc.balance_in_company_currency)
|
||||
net_pl_balance += flt(acc.bal_in_company_currency)
|
||||
|
||||
if net_pl_balance:
|
||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"cost_center": cost_center
|
||||
})
|
||||
|
||||
for dimension in accounting_dimensions:
|
||||
gl_entry.update({
|
||||
dimension: default_dimensions.get(self.company, {}).get(dimension)
|
||||
})
|
||||
|
||||
gl_entries.append(gl_entry)
|
||||
if self.cost_center_wise_pnl:
|
||||
costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
|
||||
gl_entries += costcenter_wise_gl_entries
|
||||
else:
|
||||
gl_entry = self.get_pnl_gl_entry(net_pl_balance)
|
||||
gl_entries.append(gl_entry)
|
||||
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def get_pnl_gl_entry(self, net_pl_balance):
|
||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"cost_center": cost_center
|
||||
})
|
||||
|
||||
self.update_default_dimensions(gl_entry)
|
||||
|
||||
return gl_entry
|
||||
|
||||
def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
|
||||
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entries = []
|
||||
|
||||
for acc in pl_accounts:
|
||||
if flt(acc.bal_in_company_currency):
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"cost_center": acc.cost_center or company_cost_center,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
|
||||
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
||||
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0
|
||||
}, item=acc)
|
||||
|
||||
self.update_default_dimensions(gl_entry)
|
||||
|
||||
gl_entries.append(gl_entry)
|
||||
|
||||
return gl_entries
|
||||
|
||||
def update_default_dimensions(self, gl_entry):
|
||||
if not self.accounting_dimensions:
|
||||
self.accounting_dimensions = get_accounting_dimensions()
|
||||
|
||||
_, default_dimensions = get_dimensions()
|
||||
for dimension in self.accounting_dimensions:
|
||||
gl_entry.update({
|
||||
dimension: default_dimensions.get(self.company, {}).get(dimension)
|
||||
})
|
||||
|
||||
def get_pl_balances(self):
|
||||
"""Get balance for dimension-wise pl accounts"""
|
||||
|
||||
dimension_fields = ['t1.cost_center']
|
||||
|
||||
self.accounting_dimensions = get_accounting_dimensions()
|
||||
for dimension in self.accounting_dimensions:
|
||||
dimension_fields.append('t1.{0}'.format(dimension))
|
||||
|
||||
def get_pl_balances(self, dimension_fields):
|
||||
"""Get balance for pl accounts"""
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
t1.account, t2.account_currency, {dimension_fields},
|
||||
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as balance_in_account_currency,
|
||||
sum(t1.debit) - sum(t1.credit) as balance_in_company_currency
|
||||
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as bal_in_account_currency,
|
||||
sum(t1.debit) - sum(t1.credit) as bal_in_company_currency
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and t2.report_type = 'Profit and Loss'
|
||||
and t2.docstatus < 2 and t2.company = %s
|
||||
|
@ -8,6 +8,7 @@ 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 erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
def test_closing_entry(self):
|
||||
@ -65,6 +66,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
|
||||
-1*random_expense_account[0].balance_in_account_currency)
|
||||
|
||||
def test_cost_center_wise_posting(self):
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
|
||||
company = create_company()
|
||||
surplus_account = create_account()
|
||||
|
||||
cost_center1 = create_cost_center("Test Cost Center 1")
|
||||
cost_center2 = create_cost_center("Test Cost Center 2")
|
||||
|
||||
create_sales_invoice(
|
||||
company=company,
|
||||
cost_center=cost_center1,
|
||||
income_account="Sales - TPC",
|
||||
expense_account="Cost of Goods Sold - TPC",
|
||||
rate=400,
|
||||
debit_to="Debtors - TPC"
|
||||
)
|
||||
create_sales_invoice(
|
||||
company=company,
|
||||
cost_center=cost_center2,
|
||||
income_account="Sales - TPC",
|
||||
expense_account="Cost of Goods Sold - TPC",
|
||||
rate=200,
|
||||
debit_to="Debtors - TPC"
|
||||
)
|
||||
|
||||
pcv = frappe.get_doc({
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"company": "Test PCV Company",
|
||||
"cost_center_wise_pnl": 1,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "Test",
|
||||
"doctype": "Period Closing Voucher"
|
||||
})
|
||||
pcv.insert()
|
||||
pcv.submit()
|
||||
|
||||
expected_gle = (
|
||||
('Sales - TPC', 200.0, 0.0, cost_center2),
|
||||
(surplus_account, 0.0, 200.0, cost_center2),
|
||||
('Sales - TPC', 400.0, 0.0, cost_center1),
|
||||
(surplus_account, 0.0, 400.0, cost_center1)
|
||||
)
|
||||
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
|
||||
def make_period_closing_voucher(self):
|
||||
pcv = frappe.get_doc({
|
||||
"doctype": "Period Closing Voucher",
|
||||
@ -80,6 +133,38 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
|
||||
return pcv
|
||||
|
||||
def create_company():
|
||||
company = frappe.get_doc({
|
||||
'doctype': 'Company',
|
||||
'company_name': "Test PCV Company",
|
||||
'country': 'United States',
|
||||
'default_currency': 'USD'
|
||||
})
|
||||
company.insert(ignore_if_duplicate = True)
|
||||
return company.name
|
||||
|
||||
def create_account():
|
||||
account = frappe.get_doc({
|
||||
"account_name": "Reserve and Surplus",
|
||||
"is_group": 0,
|
||||
"company": "Test PCV Company",
|
||||
"root_type": "Liability",
|
||||
"report_type": "Balance Sheet",
|
||||
"account_currency": "USD",
|
||||
"parent_account": "Current Liabilities - TPC",
|
||||
"doctype": "Account"
|
||||
}).insert(ignore_if_duplicate = True)
|
||||
return account.name
|
||||
|
||||
def create_cost_center(cc_name):
|
||||
costcenter = frappe.get_doc({
|
||||
"company": "Test PCV Company",
|
||||
"cost_center_name": cc_name,
|
||||
"doctype": "Cost Center",
|
||||
"parent_cost_center": "Test PCV Company - TPC"
|
||||
})
|
||||
costcenter.insert(ignore_if_duplicate = True)
|
||||
return costcenter.name
|
||||
|
||||
test_dependencies = ["Customer", "Cost Center"]
|
||||
test_records = frappe.get_test_records("Period Closing Voucher")
|
||||
|
@ -107,7 +107,7 @@ frappe.ui.form.on('POS Closing Entry', {
|
||||
frm.set_value("taxes", []);
|
||||
|
||||
for (let row of frm.doc.payment_reconciliation) {
|
||||
row.expected_amount = 0;
|
||||
row.expected_amount = row.opening_amount;
|
||||
}
|
||||
|
||||
for (let row of frm.doc.pos_transactions) {
|
||||
@ -154,6 +154,9 @@ function add_to_pos_transaction(d, frm) {
|
||||
function refresh_payments(d, frm) {
|
||||
d.payments.forEach(p => {
|
||||
const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment);
|
||||
if (p.account == d.account_for_change_amount) {
|
||||
p.amount -= flt(d.change_amount);
|
||||
}
|
||||
if (payment) {
|
||||
payment.expected_amount += flt(p.amount);
|
||||
payment.difference = payment.closing_amount - payment.expected_amount;
|
||||
|
@ -140,6 +140,7 @@ class POSInvoice(SalesInvoice):
|
||||
return
|
||||
|
||||
available_stock = get_stock_availability(d.item_code, d.warehouse)
|
||||
|
||||
item_code, warehouse, qty = frappe.bold(d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty)
|
||||
if flt(available_stock) <= 0:
|
||||
frappe.throw(_('Row #{}: Item Code: {} is not available under warehouse {}.')
|
||||
@ -213,8 +214,9 @@ class POSInvoice(SalesInvoice):
|
||||
for d in self.get("items"):
|
||||
is_stock_item = frappe.get_cached_value("Item", d.get("item_code"), "is_stock_item")
|
||||
if not is_stock_item:
|
||||
frappe.throw(_("Row #{}: Item {} is a non stock item. You can only include stock items in a POS Invoice. ")
|
||||
.format(d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
|
||||
if not frappe.db.exists('Product Bundle', d.item_code):
|
||||
frappe.throw(_("Row #{}: Item {} is a non stock item. You can only include stock items in a POS Invoice.")
|
||||
.format(d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
|
||||
|
||||
def validate_mode_of_payment(self):
|
||||
if len(self.payments) == 0:
|
||||
@ -455,15 +457,36 @@ class POSInvoice(SalesInvoice):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_stock_availability(item_code, warehouse):
|
||||
if frappe.db.get_value('Item', item_code, 'is_stock_item'):
|
||||
bin_qty = get_bin_qty(item_code, warehouse)
|
||||
pos_sales_qty = get_pos_reserved_qty(item_code, warehouse)
|
||||
return bin_qty - pos_sales_qty
|
||||
else:
|
||||
if frappe.db.exists('Product Bundle', item_code):
|
||||
return get_bundle_availability(item_code, warehouse)
|
||||
|
||||
def get_bundle_availability(bundle_item_code, warehouse):
|
||||
product_bundle = frappe.get_doc('Product Bundle', bundle_item_code)
|
||||
|
||||
bundle_bin_qty = 1000000
|
||||
for item in product_bundle.items:
|
||||
item_bin_qty = get_bin_qty(item.item_code, warehouse)
|
||||
item_pos_reserved_qty = get_pos_reserved_qty(item.item_code, warehouse)
|
||||
available_qty = item_bin_qty - item_pos_reserved_qty
|
||||
|
||||
max_available_bundles = available_qty / item.qty
|
||||
if bundle_bin_qty > max_available_bundles:
|
||||
bundle_bin_qty = max_available_bundles
|
||||
|
||||
pos_sales_qty = get_pos_reserved_qty(bundle_item_code, warehouse)
|
||||
return bundle_bin_qty - pos_sales_qty
|
||||
|
||||
def get_bin_qty(item_code, warehouse):
|
||||
bin_qty = frappe.db.sql("""select actual_qty from `tabBin`
|
||||
where item_code = %s and warehouse = %s
|
||||
limit 1""", (item_code, warehouse), as_dict=1)
|
||||
|
||||
pos_sales_qty = get_pos_reserved_qty(item_code, warehouse)
|
||||
|
||||
bin_qty = bin_qty[0].actual_qty or 0 if bin_qty else 0
|
||||
|
||||
return bin_qty - pos_sales_qty
|
||||
return bin_qty[0].actual_qty or 0 if bin_qty else 0
|
||||
|
||||
def get_pos_reserved_qty(item_code, warehouse):
|
||||
reserved_qty = frappe.db.sql("""select sum(p_item.qty) as qty
|
||||
@ -522,4 +545,4 @@ def add_return_modes(doc, pos_profile):
|
||||
mode_of_payment = pos_payment_method.mode_of_payment
|
||||
if pos_payment_method.allow_in_returns and not [d for d in doc.get('payments') if d.mode_of_payment == mode_of_payment]:
|
||||
payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company)
|
||||
append_payment(payment_mode[0])
|
||||
append_payment(payment_mode[0])
|
||||
|
@ -152,7 +152,7 @@ class PricingRule(Document):
|
||||
frappe.throw(_("Valid from date must be less than valid upto date"))
|
||||
|
||||
def validate_condition(self):
|
||||
if self.condition and ("=" in self.condition) and re.match("""[\w\.:_]+\s*={1}\s*[\w\.@'"]+""", self.condition):
|
||||
if self.condition and ("=" in self.condition) and re.match(r'[\w\.:_]+\s*={1}\s*[\w\.@\'"]+', self.condition):
|
||||
frappe.throw(_("Invalid condition expression"))
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
@ -19,7 +19,7 @@ frappe.ui.form.on('Process Statement Of Accounts', {
|
||||
frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
|
||||
}
|
||||
else{
|
||||
frappe.msgprint('No Records for these settings.')
|
||||
frappe.msgprint(__('No Records for these settings.'))
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -33,7 +33,7 @@ frappe.ui.form.on('Process Statement Of Accounts', {
|
||||
type: 'GET',
|
||||
success: function(result) {
|
||||
if(jQuery.isEmptyObject(result)){
|
||||
frappe.msgprint('No Records for these settings.');
|
||||
frappe.msgprint(__('No Records for these settings.'));
|
||||
}
|
||||
else{
|
||||
window.location = url;
|
||||
@ -92,7 +92,7 @@ frappe.ui.form.on('Process Statement Of Accounts', {
|
||||
frm.refresh_field('customers');
|
||||
}
|
||||
else{
|
||||
frappe.throw('No Customers found with selected options.');
|
||||
frappe.throw(__('No Customers found with selected options.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,4 +129,4 @@ frappe.ui.form.on('Process Statement Of Accounts Customer', {
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -837,6 +837,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "base_rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment (Company Currency)",
|
||||
@ -883,6 +884,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment",
|
||||
@ -1380,7 +1382,7 @@
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-30 22:45:58.334107",
|
||||
"modified": "2021-06-09 12:30:25.632109",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
@ -636,8 +636,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
|
||||
def test_rejected_serial_no(self):
|
||||
pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
|
||||
rejected_qty=1, rate=500, update_stock=1,
|
||||
rejected_warehouse = "_Test Rejected Warehouse - _TC")
|
||||
rejected_qty=1, rate=500, update_stock=1, rejected_warehouse = "_Test Rejected Warehouse - _TC",
|
||||
allow_zero_valuation_rate=1)
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Serial No", pi.get("items")[0].serial_no, "warehouse"),
|
||||
pi.get("items")[0].warehouse)
|
||||
@ -994,7 +994,8 @@ def make_purchase_invoice(**args):
|
||||
"project": args.project,
|
||||
"rejected_warehouse": args.rejected_warehouse or "",
|
||||
"rejected_serial_no": args.rejected_serial_no or "",
|
||||
"asset_location": args.location or ""
|
||||
"asset_location": args.location or "",
|
||||
"allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0
|
||||
})
|
||||
|
||||
if args.get_taxes_and_charges:
|
||||
|
@ -17,7 +17,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
var me = this;
|
||||
this._super();
|
||||
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet'];
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet', 'POS Invoice Merge Log', 'POS Closing Entry'];
|
||||
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
|
||||
// show debit_to in print format
|
||||
this.frm.set_df_property("debit_to", "print_hide", 0);
|
||||
|
@ -531,7 +531,7 @@ class SalesInvoice(SellingController):
|
||||
# set pos values in items
|
||||
for item in self.get("items"):
|
||||
if item.get('item_code'):
|
||||
profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos)
|
||||
profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos, update_data=True)
|
||||
for fname, val in iteritems(profile_details):
|
||||
if (not for_validate) or (for_validate and not item.get(fname)):
|
||||
item.set(fname, val)
|
||||
@ -849,7 +849,6 @@ class SalesInvoice(SellingController):
|
||||
|
||||
self.make_loyalty_point_redemption_gle(gl_entries)
|
||||
self.make_pos_gl_entries(gl_entries)
|
||||
self.make_gle_for_change_amount(gl_entries)
|
||||
|
||||
self.make_write_off_gl_entry(gl_entries)
|
||||
self.make_gle_for_rounding_adjustment(gl_entries)
|
||||
@ -983,7 +982,13 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def make_pos_gl_entries(self, gl_entries):
|
||||
if cint(self.is_pos):
|
||||
|
||||
skip_change_gl_entries = not cint(frappe.db.get_single_value('Accounts Settings', 'post_change_gl_entries'))
|
||||
|
||||
for payment_mode in self.payments:
|
||||
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
|
||||
payment_mode.base_amount -= self.change_amount
|
||||
|
||||
if payment_mode.amount:
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
@ -1015,8 +1020,11 @@ class SalesInvoice(SellingController):
|
||||
}, payment_mode_account_currency, item=self)
|
||||
)
|
||||
|
||||
if not skip_change_gl_entries:
|
||||
self.make_gle_for_change_amount(gl_entries)
|
||||
|
||||
def make_gle_for_change_amount(self, gl_entries):
|
||||
if cint(self.is_pos) and self.change_amount:
|
||||
if self.change_amount:
|
||||
if self.account_for_change_amount:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
|
@ -713,7 +713,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.submit()
|
||||
self.assertEqual(si.paid_amount, 100.0)
|
||||
|
||||
self.pos_gl_entry(si, pos, 50)
|
||||
self.validate_pos_gl_entry(si, pos, 50)
|
||||
|
||||
def test_pos_returns_with_repayment(self):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
|
||||
@ -749,7 +749,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
|
||||
expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
|
||||
|
||||
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
|
||||
make_purchase_receipt(company= "_Test Company with perpetual inventory",
|
||||
item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
|
||||
|
||||
pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
|
||||
@ -770,7 +770,45 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEqual(pos.grand_total, 100.0)
|
||||
self.assertEqual(pos.write_off_amount, -5)
|
||||
|
||||
def pos_gl_entry(self, si, pos, cash_amount):
|
||||
def test_pos_with_no_gl_entry_for_change_amount(self):
|
||||
frappe.db.set_value('Accounts Settings', None, 'post_change_gl_entries', 0)
|
||||
|
||||
make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
|
||||
expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
|
||||
|
||||
make_purchase_receipt(company= "_Test Company with perpetual inventory",
|
||||
item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
|
||||
|
||||
pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
|
||||
debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
|
||||
income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
|
||||
cost_center = "Main - TCP1", do_not_save=True)
|
||||
|
||||
pos.is_pos = 1
|
||||
pos.update_stock = 1
|
||||
|
||||
taxes = get_taxes_and_charges()
|
||||
pos.taxes = []
|
||||
for tax in taxes:
|
||||
pos.append("taxes", tax)
|
||||
|
||||
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
|
||||
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 60})
|
||||
|
||||
pos.insert()
|
||||
pos.submit()
|
||||
|
||||
self.assertEqual(pos.grand_total, 100.0)
|
||||
self.assertEqual(pos.change_amount, 10)
|
||||
|
||||
self.validate_pos_gl_entry(pos, pos, 60, validate_without_change_gle=True)
|
||||
|
||||
frappe.db.set_value('Accounts Settings', None, 'post_change_gl_entries', 1)
|
||||
|
||||
def validate_pos_gl_entry(self, si, pos, cash_amount, validate_without_change_gle=False):
|
||||
if validate_without_change_gle:
|
||||
cash_amount -= pos.change_amount
|
||||
|
||||
# check stock ledger entries
|
||||
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
|
||||
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
|
||||
@ -1963,6 +2001,33 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEqual(value_details['TotInvVal'], si.base_grand_total)
|
||||
self.assertTrue(einvoice['EwbDtls'])
|
||||
|
||||
def test_item_tax_net_range(self):
|
||||
item = create_item("T Shirt")
|
||||
|
||||
item.set('taxes', [])
|
||||
item.append("taxes", {
|
||||
"item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
|
||||
"minimum_net_rate": 0,
|
||||
"maximum_net_rate": 500
|
||||
})
|
||||
|
||||
item.append("taxes", {
|
||||
"item_tax_template": "_Test Account Excise Duty @ 12 - _TC",
|
||||
"minimum_net_rate": 501,
|
||||
"maximum_net_rate": 1000
|
||||
})
|
||||
|
||||
item.save()
|
||||
|
||||
sales_invoice = create_sales_invoice(item = "T Shirt", rate=700, do_not_submit=True)
|
||||
self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC")
|
||||
|
||||
# Apply discount
|
||||
sales_invoice.apply_discount_on = 'Net Total'
|
||||
sales_invoice.discount_amount = 300
|
||||
sales_invoice.save()
|
||||
self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC")
|
||||
|
||||
def make_test_address_for_ewaybill():
|
||||
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
||||
address = frappe.get_doc({
|
||||
@ -2085,27 +2150,6 @@ def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
doc.assertEqual(expected_gle[i][2], gle.credit)
|
||||
doc.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
|
||||
|
||||
def test_item_tax_validity(self):
|
||||
item = frappe.get_doc("Item", "_Test Item 2")
|
||||
|
||||
if item.taxes:
|
||||
item.taxes = []
|
||||
item.save()
|
||||
|
||||
item.append("taxes", {
|
||||
"item_tax_template": "_Test Item Tax Template 1 - _TC",
|
||||
"valid_from": add_days(nowdate(), 1)
|
||||
})
|
||||
|
||||
item.save()
|
||||
|
||||
sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
|
||||
sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1 - _TC"
|
||||
self.assertRaises(frappe.ValidationError, sales_invoice.save)
|
||||
|
||||
item.taxes = []
|
||||
item.save()
|
||||
|
||||
def create_sales_invoice(**args):
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
args = frappe._dict(args)
|
||||
|
@ -185,10 +185,10 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
|
||||
for d in gl_map:
|
||||
if d.account == round_off_account:
|
||||
round_off_gle = d
|
||||
if d.debit_in_account_currency:
|
||||
debit_credit_diff -= flt(d.debit_in_account_currency)
|
||||
if d.debit:
|
||||
debit_credit_diff -= flt(d.debit)
|
||||
else:
|
||||
debit_credit_diff += flt(d.credit_in_account_currency)
|
||||
debit_credit_diff += flt(d.credit)
|
||||
round_off_account_exists = True
|
||||
|
||||
if round_off_account_exists and abs(debit_credit_diff) <= (1.0 / (10**precision)):
|
||||
|
@ -58,11 +58,9 @@ def get_conditions(filters):
|
||||
def get_data(filters):
|
||||
|
||||
data = []
|
||||
|
||||
conditions = get_conditions(filters)
|
||||
|
||||
accounts = frappe.db.get_all("Account", fields=["name", "account_currency"],
|
||||
filters=conditions)
|
||||
filters=conditions, order_by='name')
|
||||
|
||||
for d in accounts:
|
||||
balance = get_balance_on(d.name, date=filters.report_date)
|
||||
|
@ -23,7 +23,7 @@ class TestAccountBalance(unittest.TestCase):
|
||||
|
||||
expected_data = [
|
||||
{
|
||||
"account": 'Sales - _TC2',
|
||||
"account": 'Direct Income - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": -100.0,
|
||||
},
|
||||
@ -32,21 +32,21 @@ class TestAccountBalance(unittest.TestCase):
|
||||
"currency": 'EUR',
|
||||
"balance": -100.0,
|
||||
},
|
||||
{
|
||||
"account": 'Service - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": 0.0,
|
||||
},
|
||||
{
|
||||
"account": 'Direct Income - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": -100.0,
|
||||
},
|
||||
{
|
||||
"account": 'Indirect Income - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": 0.0,
|
||||
},
|
||||
{
|
||||
"account": 'Sales - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": -100.0,
|
||||
},
|
||||
{
|
||||
"account": 'Service - _TC2',
|
||||
"currency": 'EUR',
|
||||
"balance": 0.0,
|
||||
}
|
||||
]
|
||||
|
||||
self.assertEqual(expected_data, report[1])
|
||||
|
@ -584,6 +584,7 @@ class ReceivablePayableReport(object):
|
||||
`tabGL Entry`
|
||||
where
|
||||
docstatus < 2
|
||||
and is_cancelled = 0
|
||||
and party_type=%s
|
||||
and (party is not null and party != '')
|
||||
{1} {2} {3}"""
|
||||
|
@ -445,15 +445,15 @@
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "GL Entry",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "UAE VAT 201",
|
||||
"link_to": "UAE VAT 201",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
"dependencies": "GL Entry",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "UAE VAT 201",
|
||||
"link_to": "UAE VAT 201",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -684,6 +684,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Goods and Services Tax (GST India)",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
@ -694,6 +695,7 @@
|
||||
"link_to": "GST Settings",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -704,6 +706,7 @@
|
||||
"link_to": "GST HSN Code",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -714,6 +717,7 @@
|
||||
"link_to": "GSTR-1",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -724,6 +728,7 @@
|
||||
"link_to": "GSTR-2",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -734,6 +739,7 @@
|
||||
"link_to": "GSTR 3B Report",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -744,6 +750,7 @@
|
||||
"link_to": "GST Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -754,6 +761,7 @@
|
||||
"link_to": "GST Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -764,6 +772,7 @@
|
||||
"link_to": "GST Itemised Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -774,6 +783,7 @@
|
||||
"link_to": "GST Itemised Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -784,6 +794,7 @@
|
||||
"link_to": "C-Form",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -794,6 +805,7 @@
|
||||
"link_to": "Lower Deduction Certificate",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@ -1052,7 +1064,7 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2021-05-12 11:48:01.905144",
|
||||
"modified": "2021-06-10 03:17:31.427945",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting",
|
||||
@ -1107,4 +1119,4 @@
|
||||
"type": "Dashboard"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -566,7 +566,7 @@ class TestAsset(unittest.TestCase):
|
||||
doc = make_invoice(pr.name)
|
||||
|
||||
self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
|
||||
|
||||
|
||||
def test_asset_cwip_toggling_cases(self):
|
||||
cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
|
||||
name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
|
||||
|
@ -765,6 +765,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "base_rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment (Company Currency)",
|
||||
@ -810,6 +811,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment",
|
||||
@ -1124,7 +1126,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-01-20 22:07:23.487138",
|
||||
"modified": "2021-04-19 00:55:30.781375",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
@ -576,6 +576,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "base_rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment (Company Currency",
|
||||
@ -620,6 +621,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.disable_rounded_total",
|
||||
"fieldname": "rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rounding Adjustment",
|
||||
@ -802,7 +804,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-12-03 15:18:29.073368",
|
||||
"modified": "2021-04-19 00:58:20.995491",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
@ -9,12 +9,12 @@ 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 TestSubcontractedItemToBeReceived(unittest.TestCase):
|
||||
class TestSubcontractedItemToBeTransferred(unittest.TestCase):
|
||||
|
||||
def test_pending_and_received_qty(self):
|
||||
def test_pending_and_transferred_qty(self):
|
||||
po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes')
|
||||
make_stock_entry(item_code='_Test Item', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
|
||||
make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
|
||||
make_stock_entry(item_code='_Test Item', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
|
||||
make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
|
||||
transfer_subcontracted_raw_materials(po.name)
|
||||
col, data = execute(filters=frappe._dict({'supplier': po.supplier,
|
||||
'from_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=-10)),
|
||||
@ -38,7 +38,8 @@ def transfer_subcontracted_raw_materials(po):
|
||||
'warehouse': '_Test Warehouse - _TC', 'rate': 100, 'amount': 200, 'stock_uom': 'Nos'}]
|
||||
rm_item_string = json.dumps(rm_item)
|
||||
se = frappe.get_doc(make_rm_stock_entry(po, rm_item_string))
|
||||
se.from_warehouse = '_Test Warehouse 1 - _TC'
|
||||
se.to_warehouse = '_Test Warehouse 1 - _TC'
|
||||
se.stock_entry_type = 'Send to Subcontractor'
|
||||
se.save()
|
||||
se.submit()
|
||||
se.submit()
|
||||
|
@ -225,7 +225,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
def validate_date_with_fiscal_year(self):
|
||||
if self.meta.get_field("fiscal_year"):
|
||||
date_field = ""
|
||||
date_field = None
|
||||
if self.meta.get_field("posting_date"):
|
||||
date_field = "posting_date"
|
||||
elif self.meta.get_field("transaction_date"):
|
||||
@ -1011,7 +1011,6 @@ class AccountsController(TransactionBase):
|
||||
else:
|
||||
grand_total -= self.get("total_advance")
|
||||
base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
|
||||
|
||||
if total != flt(grand_total, self.precision("grand_total")) or \
|
||||
base_total != flt(base_grand_total, self.precision("base_grand_total")):
|
||||
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
||||
@ -1450,6 +1449,7 @@ def validate_and_delete_children(parent, data):
|
||||
for d in deleted_children:
|
||||
update_bin_on_delete(d, parent.doctype)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
|
||||
def check_doc_permissions(doc, perm_type='create'):
|
||||
|
@ -1,17 +1,21 @@
|
||||
# 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, erpnext
|
||||
from frappe.utils import cint, flt, cstr, get_link_to_form, today, getdate
|
||||
from frappe import _
|
||||
import frappe.defaults
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from erpnext.accounts.utils import get_fiscal_year, check_if_stock_and_account_balance_synced
|
||||
|
||||
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.utils import check_if_stock_and_account_balance_synced, get_fiscal_year
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||
from erpnext.stock import get_warehouse_account_map
|
||||
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||
|
||||
|
||||
class QualityInspectionRequiredError(frappe.ValidationError): pass
|
||||
class QualityInspectionRejectedError(frappe.ValidationError): pass
|
||||
@ -189,7 +193,6 @@ class StockController(AccountsController):
|
||||
if hasattr(self, "items"):
|
||||
item_doclist = self.get("items")
|
||||
elif self.doctype == "Stock Reconciliation":
|
||||
import json
|
||||
item_doclist = []
|
||||
data = json.loads(self.reconciliation_json)
|
||||
for row in data[data.index(self.head_row)+1:]:
|
||||
@ -319,7 +322,7 @@ class StockController(AccountsController):
|
||||
return serialized_items
|
||||
|
||||
def validate_warehouse(self):
|
||||
from erpnext.stock.utils import validate_warehouse_company, validate_disabled_warehouse
|
||||
from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company
|
||||
|
||||
warehouses = list(set([d.warehouse for d in
|
||||
self.get("items") if getattr(d, "warehouse", None)]))
|
||||
@ -498,6 +501,39 @@ class StockController(AccountsController):
|
||||
check_if_stock_and_account_balance_synced(self.posting_date,
|
||||
self.company, self.doctype, self.name)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_quality_inspections(doctype, docname, items):
|
||||
if isinstance(items, str):
|
||||
items = json.loads(items)
|
||||
|
||||
inspections = []
|
||||
for item in items:
|
||||
if flt(item.get("sample_size")) > flt(item.get("qty")):
|
||||
frappe.throw(_("{item_name}'s Sample Size ({sample_size}) cannot be greater than the Accepted Quantity ({accepted_quantity})").format(
|
||||
item_name=item.get("item_name"),
|
||||
sample_size=item.get("sample_size"),
|
||||
accepted_quantity=item.get("qty")
|
||||
))
|
||||
|
||||
quality_inspection = frappe.get_doc({
|
||||
"doctype": "Quality Inspection",
|
||||
"inspection_type": "Incoming",
|
||||
"inspected_by": frappe.session.user,
|
||||
"reference_type": doctype,
|
||||
"reference_name": docname,
|
||||
"item_code": item.get("item_code"),
|
||||
"description": item.get("description"),
|
||||
"sample_size": flt(item.get("sample_size")),
|
||||
"item_serial_no": item.get("serial_no").split("\n")[0] if item.get("serial_no") else None,
|
||||
"batch_no": item.get("batch_no")
|
||||
}).insert()
|
||||
quality_inspection.save()
|
||||
inspections.append(quality_inspection.name)
|
||||
|
||||
return inspections
|
||||
|
||||
|
||||
def is_reposting_pending():
|
||||
return frappe.db.exists("Repost Item Valuation",
|
||||
{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})
|
||||
|
@ -54,6 +54,7 @@ class calculate_taxes_and_totals(object):
|
||||
if item.item_code and item.get('item_tax_template'):
|
||||
item_doc = frappe.get_cached_doc("Item", item.item_code)
|
||||
args = {
|
||||
'net_rate': item.net_rate or item.rate,
|
||||
'tax_category': self.doc.get('tax_category'),
|
||||
'posting_date': self.doc.get('posting_date'),
|
||||
'bill_date': self.doc.get('bill_date'),
|
||||
@ -77,10 +78,12 @@ class calculate_taxes_and_totals(object):
|
||||
|
||||
taxes = _get_item_tax_template(args, item_taxes + item_group_taxes, for_validate=True)
|
||||
|
||||
if item.item_tax_template not in taxes:
|
||||
frappe.throw(_("Row {0}: Invalid Item Tax Template for item {1}").format(
|
||||
item.idx, frappe.bold(item.item_code)
|
||||
))
|
||||
if taxes:
|
||||
if item.item_tax_template not in taxes:
|
||||
item.item_tax_template = taxes[0]
|
||||
frappe.msgprint(_("Row {0}: Item Tax template updated as per validity and rate applied").format(
|
||||
item.idx, frappe.bold(item.item_code)
|
||||
))
|
||||
|
||||
def validate_conversion_rate(self):
|
||||
# validate conversion rate
|
||||
|
@ -38,7 +38,7 @@ class Appointment(Document):
|
||||
number_of_agents = frappe.db.get_single_value('Appointment Booking Settings', 'number_of_agents')
|
||||
if not number_of_agents == 0:
|
||||
if (number_of_appointments_in_same_slot >= number_of_agents):
|
||||
frappe.throw('Time slot is not available')
|
||||
frappe.throw(_('Time slot is not available'))
|
||||
# Link lead
|
||||
if not self.party:
|
||||
lead = self.find_lead_by_email()
|
||||
@ -75,10 +75,10 @@ class Appointment(Document):
|
||||
subject=_('Appointment Confirmation'))
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.msgprint(
|
||||
'Please check your email to confirm the appointment')
|
||||
_('Please check your email to confirm the appointment'))
|
||||
else :
|
||||
frappe.msgprint(
|
||||
'Appointment was created. But no lead was found. Please check the email to confirm')
|
||||
_('Appointment was created. But no lead was found. Please check the email to confirm'))
|
||||
|
||||
def on_change(self):
|
||||
# Sync Calendar
|
||||
@ -91,7 +91,7 @@ class Appointment(Document):
|
||||
|
||||
def set_verified(self, email):
|
||||
if not email == self.customer_email:
|
||||
frappe.throw('Email verification failed.')
|
||||
frappe.throw(_('Email verification failed.'))
|
||||
# Create new lead
|
||||
self.create_lead_and_link()
|
||||
# Remove unverified status
|
||||
@ -184,7 +184,7 @@ class Appointment(Document):
|
||||
appointment_event.insert(ignore_permissions=True)
|
||||
self.calendar_event = appointment_event.name
|
||||
self.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def _get_verify_url(self):
|
||||
verify_route = '/book_appointment/verify'
|
||||
params = {
|
||||
|
@ -280,7 +280,6 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"label": "Territory",
|
||||
@ -431,7 +430,7 @@
|
||||
"icon": "fa fa-info-sign",
|
||||
"idx": 195,
|
||||
"links": [],
|
||||
"modified": "2021-01-06 19:42:46.190051",
|
||||
"modified": "2021-06-04 10:11:22.831139",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity",
|
||||
|
@ -75,7 +75,7 @@ class CourseSchedulingTool(Document):
|
||||
"""Validates if Course Start Date is greater than Course End Date"""
|
||||
if self.course_start_date > self.course_end_date:
|
||||
frappe.throw(
|
||||
"Course Start Date cannot be greater than Course End Date.")
|
||||
_("Course Start Date cannot be greater than Course End Date."))
|
||||
|
||||
def delete_course_schedule(self, rescheduled, reschedule_errors):
|
||||
"""Delete all course schedule within the Date range and specified filters"""
|
||||
|
@ -9,8 +9,7 @@ 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_records = frappe.get_test_records('Fees')
|
||||
|
||||
test_dependencies = ['Company']
|
||||
class TestFees(unittest.TestCase):
|
||||
|
||||
def test_fees(self):
|
||||
|
@ -74,7 +74,6 @@ class Student(Document):
|
||||
student_user.flags.ignore_permissions = True
|
||||
student_user.add_roles("Student")
|
||||
student_user.save()
|
||||
update_password_link = student_user.reset_password()
|
||||
|
||||
def update_applicant_status(self):
|
||||
"""Updates Student Applicant status to Admitted"""
|
||||
|
@ -219,7 +219,6 @@ def get_quiz(quiz_name, course):
|
||||
try:
|
||||
quiz = frappe.get_doc("Quiz", quiz_name)
|
||||
questions = quiz.get_questions()
|
||||
duration = quiz.duration
|
||||
except:
|
||||
frappe.throw(_("Quiz {0} does not exist").format(quiz_name), frappe.DoesNotExistError)
|
||||
return None
|
||||
@ -236,15 +235,17 @@ def get_quiz(quiz_name, course):
|
||||
return {
|
||||
'questions': questions,
|
||||
'activity': None,
|
||||
'duration':duration
|
||||
'is_time_bound': quiz.is_time_bound,
|
||||
'duration': quiz.duration
|
||||
}
|
||||
|
||||
student = get_current_student()
|
||||
course_enrollment = get_enrollment("course", course, student.name)
|
||||
status, score, result, time_taken = check_quiz_completion(quiz, course_enrollment)
|
||||
return {
|
||||
'questions': questions,
|
||||
'questions': questions,
|
||||
'activity': {'is_complete': status, 'score': score, 'result': result, 'time_taken': time_taken},
|
||||
'is_time_bound': quiz.is_time_bound,
|
||||
'duration': quiz.duration
|
||||
}
|
||||
|
||||
@ -372,9 +373,9 @@ def check_content_completion(content_name, content_type, enrollment_name):
|
||||
def check_quiz_completion(quiz, enrollment_name):
|
||||
attempts = frappe.get_all("Quiz Activity",
|
||||
filters={
|
||||
'enrollment': enrollment_name,
|
||||
'enrollment': enrollment_name,
|
||||
'quiz': quiz.name
|
||||
},
|
||||
},
|
||||
fields=["name", "activity_date", "score", "status", "time_taken"]
|
||||
)
|
||||
status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts)
|
||||
@ -389,4 +390,4 @@ def check_quiz_completion(quiz, enrollment_name):
|
||||
time_taken = attempts[0]['time_taken']
|
||||
if result == 'Pass':
|
||||
status = True
|
||||
return status, score, result, time_taken
|
||||
return status, score, result, time_taken
|
||||
|
@ -81,7 +81,7 @@ class TestMpesaSettings(unittest.TestCase):
|
||||
integration_request.reload()
|
||||
self.assertEqual(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R")
|
||||
self.assertEqual(integration_request.status, "Completed")
|
||||
|
||||
|
||||
frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
|
||||
integration_request.delete()
|
||||
pr.reload()
|
||||
@ -139,7 +139,7 @@ class TestMpesaSettings(unittest.TestCase):
|
||||
pr.cancel()
|
||||
pr.delete()
|
||||
pos_invoice.delete()
|
||||
|
||||
|
||||
def test_processing_of_only_one_succes_callback_payload(self):
|
||||
create_mpesa_settings(payment_gateway_name="Payment")
|
||||
mpesa_account = frappe.db.get_value("Payment Gateway Account", {"payment_gateway": 'Mpesa-Payment'}, "payment_account")
|
||||
|
@ -99,5 +99,7 @@ class PlaidConnector():
|
||||
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions))
|
||||
transactions.extend(response["transactions"])
|
||||
return transactions
|
||||
except ItemError as e:
|
||||
raise e
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||
|
@ -16,6 +16,10 @@ frappe.ui.form.on('Plaid Settings', {
|
||||
new erpnext.integrations.plaidLink(frm);
|
||||
});
|
||||
|
||||
frm.add_custom_button(__('Reset Plaid Link'), () => {
|
||||
new erpnext.integrations.plaidLink(frm);
|
||||
});
|
||||
|
||||
frm.add_custom_button(__("Sync Now"), () => {
|
||||
frappe.call({
|
||||
method: "erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.enqueue_synchronization",
|
||||
|
@ -12,6 +12,7 @@ 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
|
||||
|
||||
class PlaidSettings(Document):
|
||||
@staticmethod
|
||||
@ -51,7 +52,7 @@ def add_institution(token, response):
|
||||
})
|
||||
bank.insert()
|
||||
except Exception:
|
||||
frappe.throw(frappe.get_traceback())
|
||||
frappe.log_error(frappe.get_traceback(), title=_('Plaid Link Error'))
|
||||
else:
|
||||
bank = frappe.get_doc("Bank", response["institution"]["name"])
|
||||
bank.plaid_access_token = access_token
|
||||
@ -83,7 +84,12 @@ def add_bank_accounts(response, bank, company):
|
||||
if not acc_subtype:
|
||||
add_account_subtype(account["subtype"])
|
||||
|
||||
if not frappe.db.exists("Bank Account", dict(integration_id=account["id"])):
|
||||
existing_bank_account = frappe.db.exists("Bank Account", {
|
||||
'account_name': account["name"],
|
||||
'bank': bank["bank_name"]
|
||||
})
|
||||
|
||||
if not existing_bank_account:
|
||||
try:
|
||||
new_account = frappe.get_doc({
|
||||
"doctype": "Bank Account",
|
||||
@ -103,10 +109,27 @@ def add_bank_accounts(response, bank, company):
|
||||
except frappe.UniqueValidationError:
|
||||
frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(account["name"]))
|
||||
except Exception:
|
||||
frappe.throw(frappe.get_traceback())
|
||||
frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
|
||||
frappe.throw(_("There was an error creating Bank Account while linking with Plaid."),
|
||||
title=_("Plaid Link Failed"))
|
||||
|
||||
else:
|
||||
result.append(frappe.db.get_value("Bank Account", dict(integration_id=account["id"]), "name"))
|
||||
try:
|
||||
existing_account = frappe.get_doc('Bank Account', existing_bank_account)
|
||||
existing_account.update({
|
||||
"bank": bank["bank_name"],
|
||||
"account_name": account["name"],
|
||||
"account_type": account.get("type", ""),
|
||||
"account_subtype": account.get("subtype", ""),
|
||||
"mask": account.get("mask", ""),
|
||||
"integration_id": account["id"]
|
||||
})
|
||||
existing_account.save()
|
||||
result.append(existing_bank_account)
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
|
||||
frappe.throw(_("There was an error updating Bank Account {} while linking with Plaid.").format(
|
||||
existing_bank_account), title=_("Plaid Link Failed"))
|
||||
|
||||
return result
|
||||
|
||||
@ -172,9 +195,16 @@ def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
|
||||
account_id = None
|
||||
|
||||
plaid = PlaidConnector(access_token)
|
||||
transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
|
||||
|
||||
return transactions
|
||||
try:
|
||||
transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
|
||||
except ItemError as e:
|
||||
if e.code == "ITEM_LOGIN_REQUIRED":
|
||||
msg = _("There was an error syncing transactions.") + " "
|
||||
msg += _("Please refresh or reset the Plaid linking of the Bank {}.").format(bank) + " "
|
||||
frappe.log_error(msg, title=_("Plaid Link Refresh Required"))
|
||||
|
||||
return transactions or []
|
||||
|
||||
|
||||
def new_bank_transaction(transaction):
|
||||
|
@ -29,7 +29,7 @@ class TestTherapyPlan(unittest.TestCase):
|
||||
self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
|
||||
|
||||
patient, medical_department, 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)
|
||||
session.submit()
|
||||
|
@ -4,8 +4,7 @@
|
||||
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, \
|
||||
comma_or, get_fullname, add_days, nowdate, get_datetime_str
|
||||
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
|
||||
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
|
||||
@ -85,7 +84,7 @@ class LeaveApplication(Document):
|
||||
|
||||
def validate_dates(self):
|
||||
if frappe.db.get_single_value("HR Settings", "restrict_backdated_leave_application"):
|
||||
if self.from_date and self.from_date < frappe.utils.today():
|
||||
if self.from_date and getdate(self.from_date) < getdate():
|
||||
allowed_role = frappe.db.get_single_value("HR Settings", "role_allowed_to_create_backdated_leave_application")
|
||||
if allowed_role not in frappe.get_roles():
|
||||
frappe.throw(_("Only users with the {0} role can create backdated leave applications").format(allowed_role))
|
||||
@ -248,9 +247,9 @@ class LeaveApplication(Document):
|
||||
self.throw_overlap_error(d)
|
||||
|
||||
def throw_overlap_error(self, d):
|
||||
msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(self.employee,
|
||||
d['leave_type'], formatdate(d['from_date']), formatdate(d['to_date'])) \
|
||||
+ """ <b><a href="/app/Form/Leave Application/{0}">{0}</a></b>""".format(d["name"])
|
||||
form_link = get_link_to_form("Leave Application", d.name)
|
||||
msg = _("Employee {0} has already applied for {1} between {2} and {3} : {4}").format(self.employee,
|
||||
d['leave_type'], formatdate(d['from_date']), formatdate(d['to_date']), form_link)
|
||||
frappe.throw(msg, OverlapError)
|
||||
|
||||
def get_total_leaves_on_half_day(self):
|
||||
@ -356,7 +355,7 @@ class LeaveApplication(Document):
|
||||
|
||||
sender = dict()
|
||||
sender['email'] = frappe.get_doc('User', frappe.session.user).email
|
||||
sender['full_name'] = frappe.utils.get_fullname(sender['email'])
|
||||
sender['full_name'] = get_fullname(sender['email'])
|
||||
|
||||
try:
|
||||
frappe.sendmail(
|
||||
@ -823,4 +822,4 @@ def get_leave_approver(employee):
|
||||
leave_approver = frappe.db.get_value('Department Approver', {'parent': department,
|
||||
'parentfield': 'leave_approvers', 'idx': 1}, 'approver')
|
||||
|
||||
return leave_approver
|
||||
return leave_approver
|
||||
|
@ -5,11 +5,18 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
import erpnext
|
||||
from frappe.utils import getdate
|
||||
from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
|
||||
test_dependencies = ['Holiday List']
|
||||
|
||||
class TestUploadAttendance(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", '_Test Holiday List')
|
||||
|
||||
def test_date_range(self):
|
||||
employee = make_employee("test_employee@company.com")
|
||||
employee_doc = frappe.get_doc("Employee", employee)
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils import nowdate,flt, cstr,random_string
|
||||
from frappe.utils import nowdate, flt, cstr, random_string
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
from erpnext.hr.doctype.vehicle_log.vehicle_log import make_expense_claim
|
||||
|
||||
@ -18,23 +18,13 @@ class TestVehicleLog(unittest.TestCase):
|
||||
self.employee_id = make_employee("testdriver@example.com", company="_Test Company")
|
||||
|
||||
self.license_plate = get_vehicle(self.employee_id)
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
frappe.delete_doc("Vehicle", self.license_plate, force=1)
|
||||
frappe.delete_doc("Employee", self.employee_id, force=1)
|
||||
|
||||
def test_make_vehicle_log_and_syncing_of_odometer_value(self):
|
||||
vehicle_log = frappe.get_doc({
|
||||
"doctype": "Vehicle Log",
|
||||
"license_plate": cstr(self.license_plate),
|
||||
"employee": self.employee_id,
|
||||
"date":frappe.utils.nowdate(),
|
||||
"odometer":5010,
|
||||
"fuel_qty":frappe.utils.flt(50),
|
||||
"price": frappe.utils.flt(500)
|
||||
})
|
||||
vehicle_log.save()
|
||||
vehicle_log.submit()
|
||||
vehicle_log = make_vehicle_log(self.license_plate, self.employee_id)
|
||||
|
||||
#checking value of vehicle odometer value on submit.
|
||||
vehicle = frappe.get_doc("Vehicle", self.license_plate)
|
||||
@ -51,19 +41,9 @@ class TestVehicleLog(unittest.TestCase):
|
||||
self.assertEqual(vehicle.last_odometer, current_odometer - distance_travelled)
|
||||
|
||||
vehicle_log.delete()
|
||||
|
||||
|
||||
def test_vehicle_log_fuel_expense(self):
|
||||
vehicle_log = frappe.get_doc({
|
||||
"doctype": "Vehicle Log",
|
||||
"license_plate": cstr(self.license_plate),
|
||||
"employee": self.employee_id,
|
||||
"date": frappe.utils.nowdate(),
|
||||
"odometer":5010,
|
||||
"fuel_qty":frappe.utils.flt(50),
|
||||
"price": frappe.utils.flt(500)
|
||||
})
|
||||
vehicle_log.save()
|
||||
vehicle_log.submit()
|
||||
vehicle_log = make_vehicle_log(self.license_plate, self.employee_id)
|
||||
|
||||
expense_claim = make_expense_claim(vehicle_log.name)
|
||||
fuel_expense = expense_claim.expenses[0].amount
|
||||
@ -73,6 +53,18 @@ class TestVehicleLog(unittest.TestCase):
|
||||
frappe.delete_doc("Expense Claim", expense_claim.name)
|
||||
frappe.delete_doc("Vehicle Log", vehicle_log.name)
|
||||
|
||||
def test_vehicle_log_with_service_expenses(self):
|
||||
vehicle_log = make_vehicle_log(self.license_plate, self.employee_id, with_services=True)
|
||||
|
||||
expense_claim = make_expense_claim(vehicle_log.name)
|
||||
expenses = expense_claim.expenses[0].amount
|
||||
self.assertEqual(expenses, 27000)
|
||||
|
||||
vehicle_log.cancel()
|
||||
frappe.delete_doc("Expense Claim", expense_claim.name)
|
||||
frappe.delete_doc("Vehicle Log", vehicle_log.name)
|
||||
|
||||
|
||||
def get_vehicle(employee_id):
|
||||
license_plate=random_string(10).upper()
|
||||
vehicle = frappe.get_doc({
|
||||
@ -81,15 +73,46 @@ def get_vehicle(employee_id):
|
||||
"make": "Maruti",
|
||||
"model": "PCM",
|
||||
"employee": employee_id,
|
||||
"last_odometer":5000,
|
||||
"acquisition_date":frappe.utils.nowdate(),
|
||||
"last_odometer": 5000,
|
||||
"acquisition_date": nowdate(),
|
||||
"location": "Mumbai",
|
||||
"chassis_no": "1234ABCD",
|
||||
"uom": "Litre",
|
||||
"vehicle_value":frappe.utils.flt(500000)
|
||||
"vehicle_value": flt(500000)
|
||||
})
|
||||
try:
|
||||
vehicle.insert()
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
return license_plate
|
||||
return license_plate
|
||||
|
||||
|
||||
def make_vehicle_log(license_plate, employee_id, with_services=False):
|
||||
vehicle_log = frappe.get_doc({
|
||||
"doctype": "Vehicle Log",
|
||||
"license_plate": cstr(license_plate),
|
||||
"employee": employee_id,
|
||||
"date": nowdate(),
|
||||
"odometer": 5010,
|
||||
"fuel_qty": flt(50),
|
||||
"price": flt(500)
|
||||
})
|
||||
|
||||
if with_services:
|
||||
vehicle_log.append("service_detail", {
|
||||
"service_item": "Oil Change",
|
||||
"type": "Inspection",
|
||||
"frequency": "Mileage",
|
||||
"expense_amount": flt(500)
|
||||
})
|
||||
vehicle_log.append("service_detail", {
|
||||
"service_item": "Wheels",
|
||||
"type": "Change",
|
||||
"frequency": "Half Yearly",
|
||||
"expense_amount": flt(1500)
|
||||
})
|
||||
|
||||
vehicle_log.save()
|
||||
vehicle_log.submit()
|
||||
|
||||
return vehicle_log
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2016-09-03 14:14:51.788550",
|
||||
"doctype": "DocType",
|
||||
@ -10,7 +11,6 @@
|
||||
"naming_series",
|
||||
"license_plate",
|
||||
"employee",
|
||||
"column_break_4",
|
||||
"column_break_7",
|
||||
"model",
|
||||
"make",
|
||||
@ -65,10 +65,6 @@
|
||||
"options": "Employee",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
@ -142,7 +138,6 @@
|
||||
{
|
||||
"fieldname": "service_detail",
|
||||
"fieldtype": "Table",
|
||||
"label": "Service Detail",
|
||||
"options": "Vehicle Service"
|
||||
},
|
||||
{
|
||||
@ -158,7 +153,7 @@
|
||||
"fetch_from": "license_plate.last_odometer",
|
||||
"fieldname": "last_odometer",
|
||||
"fieldtype": "Int",
|
||||
"label": "last Odometer Value ",
|
||||
"label": "Last Odometer Value ",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
@ -168,7 +163,8 @@
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"modified": "2020-03-18 16:45:45.060761",
|
||||
"links": [],
|
||||
"modified": "2021-05-17 00:10:21.188352",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Vehicle Log",
|
||||
|
@ -37,5 +37,22 @@ frappe.query_reports["Employee Leave Balance"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Employee",
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
onload: () => {
|
||||
frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.hr.utils.get_leave_period",
|
||||
args: {
|
||||
"from_date": frappe.defaults.get_default("year_start_date"),
|
||||
"to_date": frappe.defaults.get_default("year_end_date"),
|
||||
"company": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
freeze: true,
|
||||
callback: (data) => {
|
||||
frappe.query_report.set_filter_value("from_date", data.message[0].from_date);
|
||||
frappe.query_report.set_filter_value("to_date", data.message[0].to_date);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,16 @@ 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
|
||||
|
||||
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"'))
|
||||
frappe.throw(_('"From Date" can not be greater than or equal to "To Date"'))
|
||||
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
|
||||
return columns, data
|
||||
charts = get_chart_data(data)
|
||||
return columns, data, None, charts
|
||||
|
||||
def get_columns():
|
||||
columns = [{
|
||||
@ -31,9 +32,10 @@ def get_columns():
|
||||
'options': 'Employee'
|
||||
}, {
|
||||
'label': _('Employee Name'),
|
||||
'fieldtype': 'Data',
|
||||
'fieldtype': 'Dynamic Link',
|
||||
'fieldname': 'employee_name',
|
||||
'width': 100,
|
||||
'options': 'employee'
|
||||
}, {
|
||||
'label': _('Opening Balance'),
|
||||
'fieldtype': 'float',
|
||||
@ -64,8 +66,7 @@ def get_columns():
|
||||
return columns
|
||||
|
||||
def get_data(filters):
|
||||
leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
|
||||
|
||||
leave_types = frappe.db.get_list('Leave Type', pluck='name', order_by='name')
|
||||
conditions = get_conditions(filters)
|
||||
|
||||
user = frappe.session.user
|
||||
@ -113,12 +114,8 @@ def get_data(filters):
|
||||
|
||||
# not be shown on the basis of days left it create in user mind for carry_forward leave
|
||||
row.closing_balance = (new_allocation + opening - (row.leaves_expired + leaves_taken))
|
||||
|
||||
|
||||
row.indent = 1
|
||||
data.append(row)
|
||||
new_leaves_allocated = 0
|
||||
|
||||
|
||||
return data
|
||||
|
||||
@ -129,27 +126,37 @@ def get_conditions(filters):
|
||||
if filters.get('employee'):
|
||||
conditions['name'] = filters.get('employee')
|
||||
|
||||
if filters.get('employee'):
|
||||
conditions['name'] = filters.get('employee')
|
||||
|
||||
if filters.get('company'):
|
||||
conditions['company'] = filters.get('company')
|
||||
|
||||
if filters.get('department'):
|
||||
conditions['department'] = filters.get('department')
|
||||
|
||||
return conditions
|
||||
|
||||
def get_department_leave_approver_map(department=None):
|
||||
conditions=''
|
||||
if department:
|
||||
conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
|
||||
|
||||
# get current department and all its child
|
||||
department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
|
||||
|
||||
department_list = frappe.get_list('Department',
|
||||
filters={
|
||||
'disabled': 0
|
||||
},
|
||||
or_filters={
|
||||
'name': department,
|
||||
'parent_department': department
|
||||
},
|
||||
fields=['name'],
|
||||
pluck='name'
|
||||
)
|
||||
# retrieve approvers list from current department and from its subsequent child departments
|
||||
approver_list = frappe.get_all('Department Approver', filters={
|
||||
'parentfield': 'leave_approvers',
|
||||
'parent': ('in', department_list)
|
||||
}, fields=['parent', 'approver'], as_list=1)
|
||||
approver_list = frappe.get_all('Department Approver',
|
||||
filters={
|
||||
'parentfield': 'leave_approvers',
|
||||
'parent': ('in', department_list)
|
||||
},
|
||||
fields=['parent', 'approver'],
|
||||
as_list=1
|
||||
)
|
||||
|
||||
approvers = {}
|
||||
|
||||
@ -190,3 +197,40 @@ def get_allocated_and_expired_leaves(from_date, to_date, employee, leave_type):
|
||||
new_allocation += record.leaves
|
||||
|
||||
return new_allocation, expired_leaves
|
||||
|
||||
def get_chart_data(data):
|
||||
labels = []
|
||||
datasets = []
|
||||
employee_data = data
|
||||
|
||||
if data and data[0].get('employee_name'):
|
||||
get_dataset_for_chart(employee_data, datasets, labels)
|
||||
|
||||
chart = {
|
||||
'data': {
|
||||
'labels': labels,
|
||||
'datasets': datasets
|
||||
},
|
||||
'type': 'bar',
|
||||
'colors': ['#456789', '#EE8888', '#7E77BF']
|
||||
}
|
||||
|
||||
return chart
|
||||
|
||||
def get_dataset_for_chart(employee_data, datasets, labels):
|
||||
leaves = []
|
||||
employee_data = sorted(employee_data, key=lambda k: k['employee_name'])
|
||||
|
||||
for key, group in groupby(employee_data, lambda x: x['employee_name']):
|
||||
for grp in group:
|
||||
if grp.closing_balance:
|
||||
leaves.append(frappe._dict({
|
||||
'leave_type': grp.leave_type,
|
||||
'closing_balance': grp.closing_balance
|
||||
}))
|
||||
|
||||
if leaves:
|
||||
labels.append(key)
|
||||
|
||||
for leave in leaves:
|
||||
datasets.append({'name': leave.leave_type, 'values': [leave.closing_balance]})
|
||||
|
73
erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py
Normal file
73
erpnext/hr/report/vehicle_expenses/test_vehicle_expenses.py
Normal file
@ -0,0 +1,73 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# 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
|
||||
|
||||
class TestVehicleExpenses(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
frappe.db.sql('delete from `tabVehicle Log`')
|
||||
|
||||
employee_id = frappe.db.sql('''select name from `tabEmployee` where name="testdriver@example.com"''')
|
||||
self.employee_id = employee_id[0][0] if employee_id else None
|
||||
if not self.employee_id:
|
||||
self.employee_id = make_employee('testdriver@example.com', company='_Test Company')
|
||||
|
||||
self.license_plate = get_vehicle(self.employee_id)
|
||||
|
||||
def test_vehicle_expenses_based_on_fiscal_year(self):
|
||||
vehicle_log = make_vehicle_log(self.license_plate, self.employee_id, with_services=True)
|
||||
expense_claim = make_expense_claim(vehicle_log.name)
|
||||
|
||||
# Based on Fiscal Year
|
||||
filters = {
|
||||
'filter_based_on': 'Fiscal Year',
|
||||
'fiscal_year': get_fiscal_year(getdate())[0]
|
||||
}
|
||||
|
||||
report = execute(filters)
|
||||
|
||||
expected_data = [{
|
||||
'vehicle': self.license_plate,
|
||||
'make': 'Maruti',
|
||||
'model': 'PCM',
|
||||
'location': 'Mumbai',
|
||||
'log_name': vehicle_log.name,
|
||||
'odometer': 5010,
|
||||
'date': getdate(),
|
||||
'fuel_qty': 50.0,
|
||||
'fuel_price': 500.0,
|
||||
'fuel_expense': 25000.0,
|
||||
'service_expense': 2000.0,
|
||||
'employee': self.employee_id
|
||||
}]
|
||||
|
||||
self.assertEqual(report[1], expected_data)
|
||||
|
||||
# Based on Date Range
|
||||
fiscal_year = get_fiscal_year(getdate(), as_dict=True)
|
||||
filters = {
|
||||
'filter_based_on': 'Date Range',
|
||||
'from_date': fiscal_year.year_start_date,
|
||||
'to_date': fiscal_year.year_end_date
|
||||
}
|
||||
|
||||
report = execute(filters)
|
||||
self.assertEqual(report[1], expected_data)
|
||||
|
||||
# clean up
|
||||
vehicle_log.cancel()
|
||||
frappe.delete_doc('Expense Claim', expense_claim.name)
|
||||
frappe.delete_doc('Vehicle Log', vehicle_log.name)
|
||||
|
||||
def tearDown(self):
|
||||
frappe.delete_doc('Vehicle', self.license_plate, force=1)
|
||||
frappe.delete_doc('Employee', self.employee_id, force=1)
|
@ -1,31 +1,52 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Vehicle Expenses"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"label": __("Fiscal Year"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Fiscal Year",
|
||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
||||
"reqd": 1,
|
||||
"on_change": function(query_report) {
|
||||
var fiscal_year = query_report.get_values().fiscal_year;
|
||||
if (!fiscal_year) {
|
||||
return;
|
||||
}
|
||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||
|
||||
frappe.query_report.set_filter({
|
||||
from_date: fy.year_start_date,
|
||||
to_date: fy.year_end_date
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
frappe.query_reports["Vehicle Expenses"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "filter_based_on",
|
||||
"label": __("Filter Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Fiscal Year", "Date Range"],
|
||||
"default": ["Fiscal Year"],
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"label": __("Fiscal Year"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Fiscal Year",
|
||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
||||
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
|
||||
"default": frappe.datetime.add_months(frappe.datetime.nowdate(), -12)
|
||||
},
|
||||
{
|
||||
"fieldname": "to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
|
||||
"default": frappe.datetime.nowdate()
|
||||
},
|
||||
{
|
||||
"fieldname": "vehicle",
|
||||
"label": __("Vehicle"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Vehicle"
|
||||
},
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"label": __("Employee"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Employee"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
@ -1,20 +1,23 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2016-09-09 03:33:40.605734",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 2,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2017-02-24 19:59:18.641284",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Vehicle Expenses",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "Vehicle",
|
||||
"report_name": "Vehicle Expenses",
|
||||
"report_type": "Script Report",
|
||||
"add_total_row": 1,
|
||||
"columns": [],
|
||||
"creation": "2016-09-09 03:33:40.605734",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 2,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2021-05-16 22:48:22.767535",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Vehicle Expenses",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Vehicle",
|
||||
"report_name": "Vehicle Expenses",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Fleet Manager"
|
||||
|
@ -5,86 +5,209 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
import erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt,cstr
|
||||
from frappe.utils import flt
|
||||
from erpnext.accounts.report.financial_statements import get_period_list
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data, chart = [], [], []
|
||||
if filters.get('fiscal_year'):
|
||||
company = erpnext.get_default_company()
|
||||
period_list = get_period_list(filters.get('fiscal_year'), filters.get('fiscal_year'),
|
||||
'', '', 'Fiscal Year', 'Monthly', company=company)
|
||||
columns=get_columns()
|
||||
data=get_log_data(filters)
|
||||
chart=get_chart_data(data,period_list)
|
||||
filters = frappe._dict(filters or {})
|
||||
|
||||
columns = get_columns()
|
||||
data = get_vehicle_log_data(filters)
|
||||
chart = get_chart_data(data, filters)
|
||||
|
||||
return columns, data, None, chart
|
||||
|
||||
def get_columns():
|
||||
columns = [_("License") + ":Link/Vehicle:100", _('Create') + ":data:50",
|
||||
_("Model") + ":data:50", _("Location") + ":data:100",
|
||||
_("Log") + ":Link/Vehicle Log:100", _("Odometer") + ":Int:80",
|
||||
_("Date") + ":Date:100", _("Fuel Qty") + ":Float:80",
|
||||
_("Fuel Price") + ":Float:100",_("Fuel Expense") + ":Float:100",
|
||||
_("Service Expense") + ":Float:100"
|
||||
return [
|
||||
{
|
||||
'fieldname': 'vehicle',
|
||||
'fieldtype': 'Link',
|
||||
'label': _('Vehicle'),
|
||||
'options': 'Vehicle',
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'fieldname': 'make',
|
||||
'fieldtype': 'Data',
|
||||
'label': _('Make'),
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'model',
|
||||
'fieldtype': 'Data',
|
||||
'label': _('Model'),
|
||||
'width': 80
|
||||
},
|
||||
{
|
||||
'fieldname': 'location',
|
||||
'fieldtype': 'Data',
|
||||
'label': _('Location'),
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'log_name',
|
||||
'fieldtype': 'Link',
|
||||
'label': _('Vehicle Log'),
|
||||
'options': 'Vehicle Log',
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'odometer',
|
||||
'fieldtype': 'Int',
|
||||
'label': _('Odometer Value'),
|
||||
'width': 120
|
||||
},
|
||||
{
|
||||
'fieldname': 'date',
|
||||
'fieldtype': 'Date',
|
||||
'label': _('Date'),
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'fuel_qty',
|
||||
'fieldtype': 'Float',
|
||||
'label': _('Fuel Qty'),
|
||||
'width': 80
|
||||
},
|
||||
{
|
||||
'fieldname': 'fuel_price',
|
||||
'fieldtype': 'Float',
|
||||
'label': _('Fuel Price'),
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'fuel_expense',
|
||||
'fieldtype': 'Currency',
|
||||
'label': _('Fuel Expense'),
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'fieldname': 'service_expense',
|
||||
'fieldtype': 'Currency',
|
||||
'label': _('Service Expense'),
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'fieldname': 'employee',
|
||||
'fieldtype': 'Link',
|
||||
'label': _('Employee'),
|
||||
'options': 'Employee',
|
||||
'width': 150
|
||||
}
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_log_data(filters):
|
||||
fy = frappe.db.get_value('Fiscal Year', filters.get('fiscal_year'), ['year_start_date', 'year_end_date'], as_dict=True)
|
||||
data = frappe.db.sql("""select
|
||||
vhcl.license_plate as "License", vhcl.make as "Make", vhcl.model as "Model",
|
||||
vhcl.location as "Location", log.name as "Log", log.odometer as "Odometer",
|
||||
log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price",
|
||||
log.fuel_qty * log.price as "Fuel Expense"
|
||||
from
|
||||
|
||||
def get_vehicle_log_data(filters):
|
||||
start_date, end_date = get_period_dates(filters)
|
||||
conditions, values = get_conditions(filters)
|
||||
|
||||
data = frappe.db.sql("""
|
||||
SELECT
|
||||
vhcl.license_plate as vehicle, vhcl.make, vhcl.model,
|
||||
vhcl.location, log.name as log_name, log.odometer,
|
||||
log.date, log.employee, log.fuel_qty,
|
||||
log.price as fuel_price,
|
||||
log.fuel_qty * log.price as fuel_expense
|
||||
FROM
|
||||
`tabVehicle` vhcl,`tabVehicle Log` log
|
||||
where
|
||||
vhcl.license_plate = log.license_plate and log.docstatus = 1 and date between %s and %s
|
||||
order by date""" ,(fy.year_start_date, fy.year_end_date), as_dict=1)
|
||||
dl=list(data)
|
||||
for row in dl:
|
||||
row["Service Expense"]= get_service_expense(row["Log"])
|
||||
return dl
|
||||
WHERE
|
||||
vhcl.license_plate = log.license_plate
|
||||
and log.docstatus = 1
|
||||
and date between %(start_date)s and %(end_date)s
|
||||
{0}
|
||||
ORDER BY date""".format(conditions), values, as_dict=1)
|
||||
|
||||
for row in data:
|
||||
row['service_expense'] = get_service_expense(row.log_name)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ''
|
||||
|
||||
start_date, end_date = get_period_dates(filters)
|
||||
values = {
|
||||
'start_date': start_date,
|
||||
'end_date': end_date
|
||||
}
|
||||
|
||||
if filters.employee:
|
||||
conditions += ' and log.employee = %(employee)s'
|
||||
values['employee'] = filters.employee
|
||||
|
||||
if filters.vehicle:
|
||||
conditions += ' and vhcl.license_plate = %(vehicle)s'
|
||||
values['vehicle'] = filters.vehicle
|
||||
|
||||
return conditions, values
|
||||
|
||||
|
||||
def get_period_dates(filters):
|
||||
if filters.filter_based_on == 'Fiscal Year' and filters.fiscal_year:
|
||||
fy = frappe.db.get_value('Fiscal Year', filters.fiscal_year,
|
||||
['year_start_date', 'year_end_date'], as_dict=True)
|
||||
return fy.year_start_date, fy.year_end_date
|
||||
else:
|
||||
return filters.from_date, filters.to_date
|
||||
|
||||
|
||||
def get_service_expense(logname):
|
||||
expense_amount = frappe.db.sql("""select sum(expense_amount)
|
||||
from `tabVehicle Log` log,`tabVehicle Service` ser
|
||||
where ser.parent=log.name and log.name=%s""",logname)
|
||||
return flt(expense_amount[0][0]) if expense_amount else 0
|
||||
expense_amount = frappe.db.sql("""
|
||||
SELECT sum(expense_amount)
|
||||
FROM
|
||||
`tabVehicle Log` log, `tabVehicle Service` service
|
||||
WHERE
|
||||
service.parent=log.name and log.name=%s
|
||||
""", logname)
|
||||
|
||||
return flt(expense_amount[0][0]) if expense_amount else 0.0
|
||||
|
||||
|
||||
def get_chart_data(data, filters):
|
||||
period_list = get_period_list(filters.fiscal_year, filters.fiscal_year,
|
||||
filters.from_date, filters.to_date, filters.filter_based_on, 'Monthly')
|
||||
|
||||
fuel_data, service_data = [], []
|
||||
|
||||
def get_chart_data(data,period_list):
|
||||
fuel_exp_data,service_exp_data,fueldata,servicedata = [],[],[],[]
|
||||
service_exp_data = []
|
||||
fueldata = []
|
||||
for period in period_list:
|
||||
total_fuel_exp=0
|
||||
total_ser_exp=0
|
||||
for row in data:
|
||||
if row["Date"] <= period.to_date and row["Date"] >= period.from_date:
|
||||
total_fuel_exp+=flt(row["Fuel Expense"])
|
||||
total_ser_exp+=flt(row["Service Expense"])
|
||||
fueldata.append([period.key,total_fuel_exp])
|
||||
servicedata.append([period.key,total_ser_exp])
|
||||
total_fuel_exp = 0
|
||||
total_service_exp = 0
|
||||
|
||||
for row in data:
|
||||
if row.date <= period.to_date and row.date >= period.from_date:
|
||||
total_fuel_exp += flt(row.fuel_expense)
|
||||
total_service_exp += flt(row.service_expense)
|
||||
|
||||
fuel_data.append([period.key, total_fuel_exp])
|
||||
service_data.append([period.key, total_service_exp])
|
||||
|
||||
labels = [period.label for period in period_list]
|
||||
fuel_exp_data= [row[1] for row in fuel_data]
|
||||
service_exp_data= [row[1] for row in service_data]
|
||||
|
||||
labels = [period.key for period in period_list]
|
||||
fuel_exp_data= [row[1] for row in fueldata]
|
||||
service_exp_data= [row[1] for row in servicedata]
|
||||
datasets = []
|
||||
if fuel_exp_data:
|
||||
datasets.append({
|
||||
'name': 'Fuel Expenses',
|
||||
'name': _('Fuel Expenses'),
|
||||
'values': fuel_exp_data
|
||||
})
|
||||
|
||||
if service_exp_data:
|
||||
datasets.append({
|
||||
'name': 'Service Expenses',
|
||||
'name': _('Service Expenses'),
|
||||
'values': service_exp_data
|
||||
})
|
||||
|
||||
chart = {
|
||||
"data": {
|
||||
'data': {
|
||||
'labels': labels,
|
||||
'datasets': datasets
|
||||
}
|
||||
},
|
||||
'type': 'line',
|
||||
'fieldtype': 'Currency'
|
||||
}
|
||||
chart["type"] = "line"
|
||||
|
||||
return chart
|
||||
|
@ -269,6 +269,7 @@ def get_total_exemption_amount(declarations):
|
||||
total_exemption_amount = sum([flt(d.total_exemption_amount) for d in exemptions.values()])
|
||||
return total_exemption_amount
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_leave_period(from_date, to_date, company):
|
||||
leave_period = frappe.db.sql("""
|
||||
select name, from_date, to_date
|
||||
|
@ -264,7 +264,7 @@ def make_loan_write_off(loan, company=None, posting_date=None, amount=0, as_dict
|
||||
pending_amount = amounts['pending_principal_amount']
|
||||
|
||||
if amount and (amount > pending_amount):
|
||||
frappe.throw('Write Off amount cannot be greater than pending loan amount')
|
||||
frappe.throw(_('Write Off amount cannot be greater than pending loan amount'))
|
||||
|
||||
if not amount:
|
||||
amount = pending_amount
|
||||
|
@ -12,7 +12,7 @@
|
||||
"idx": 0,
|
||||
"is_default": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Loan Management",
|
||||
"label": "Loans",
|
||||
"links": [
|
||||
{
|
||||
"hidden": 0,
|
||||
@ -220,10 +220,10 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2021-02-18 17:31:53.586508",
|
||||
"modified": "2021-05-25 17:31:53.586508",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Management",
|
||||
"name": "Loans",
|
||||
"owner": "Administrator",
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
|
@ -2,40 +2,36 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.maintenance");
|
||||
|
||||
frappe.ui.form.on('Maintenance Schedule', {
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frm.set_query('contact_person', erpnext.queries.contact_query);
|
||||
frm.set_query('customer_address', erpnext.queries.address_query);
|
||||
frm.set_query('customer', erpnext.queries.customer);
|
||||
|
||||
frm.add_fetch('item_code', 'item_name', 'item_name');
|
||||
frm.add_fetch('item_code', 'description', 'description');
|
||||
},
|
||||
onload: function(frm) {
|
||||
onload: function (frm) {
|
||||
if (!frm.doc.status) {
|
||||
frm.set_value({status:'Draft'});
|
||||
frm.set_value({ status: 'Draft' });
|
||||
}
|
||||
if (frm.doc.__islocal) {
|
||||
frm.set_value({transaction_date: frappe.datetime.get_today()});
|
||||
frm.set_value({ transaction_date: frappe.datetime.get_today() });
|
||||
}
|
||||
},
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
setTimeout(() => {
|
||||
frm.toggle_display('generate_schedule', !(frm.is_new()));
|
||||
frm.toggle_display('schedule', !(frm.is_new()));
|
||||
},10);
|
||||
}, 10);
|
||||
},
|
||||
customer: function(frm) {
|
||||
customer: function (frm) {
|
||||
erpnext.utils.get_party_details(frm)
|
||||
},
|
||||
customer_address: function(frm) {
|
||||
customer_address: function (frm) {
|
||||
erpnext.utils.get_address_display(frm, 'customer_address', 'address_display');
|
||||
},
|
||||
contact_person: function(frm) {
|
||||
contact_person: function (frm) {
|
||||
erpnext.utils.get_contact_details(frm);
|
||||
},
|
||||
generate_schedule: function(frm) {
|
||||
generate_schedule: function (frm) {
|
||||
if (frm.is_new()) {
|
||||
frappe.msgprint(__('Please save first'));
|
||||
} else {
|
||||
@ -46,14 +42,14 @@ frappe.ui.form.on('Maintenance Schedule', {
|
||||
|
||||
// TODO commonify this code
|
||||
erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
|
||||
refresh: function() {
|
||||
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
|
||||
refresh: function () {
|
||||
frappe.dynamic_link = { doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer' };
|
||||
|
||||
var me = this;
|
||||
|
||||
if (this.frm.doc.docstatus === 0) {
|
||||
this.frm.add_custom_button(__('Sales Order'),
|
||||
function() {
|
||||
function () {
|
||||
erpnext.utils.map_current_doc({
|
||||
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
|
||||
source_doctype: "Sales Order",
|
||||
@ -68,52 +64,107 @@ erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
}, __("Get Items From"));
|
||||
} else if (this.frm.doc.docstatus === 1) {
|
||||
this.frm.add_custom_button(__('Create Maintenance Visit'), function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit",
|
||||
source_name: me.frm.doc.name,
|
||||
frm: me.frm
|
||||
let schedules = me.frm.doc.schedules;
|
||||
let flag = schedules.some(schedule => schedule.completion_status === "Pending");
|
||||
if (flag) {
|
||||
this.frm.add_custom_button(__('Maintenance Visit'), function () {
|
||||
let options = "";
|
||||
|
||||
me.frm.call('get_pending_data', {data_type: "items"}).then(r => {
|
||||
options = r.message;
|
||||
|
||||
let schedule_id = "";
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __("Enter Visit Details"),
|
||||
fields: [{
|
||||
fieldtype: "Select",
|
||||
fieldname: "item_name",
|
||||
label: __("Item Name"),
|
||||
options: options,
|
||||
reqd: 1,
|
||||
onchange: function () {
|
||||
let field = d.get_field("scheduled_date");
|
||||
me.frm.call('get_pending_data',
|
||||
{
|
||||
item_name: this.value,
|
||||
data_type: "date"
|
||||
}).then(r => {
|
||||
field.df.options = r.message;
|
||||
field.refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: __('Scheduled Date'),
|
||||
fieldname: 'scheduled_date',
|
||||
fieldtype: 'Select',
|
||||
options: "",
|
||||
reqd: 1,
|
||||
onchange: function () {
|
||||
let field = d.get_field('item_name');
|
||||
me.frm.call(
|
||||
'get_pending_data',
|
||||
{
|
||||
item_name: field.value,
|
||||
s_date: this.value,
|
||||
data_type: "id"
|
||||
}).then(r => {
|
||||
schedule_id = r.message;
|
||||
});
|
||||
}
|
||||
},
|
||||
],
|
||||
primary_action_label: 'Create Visit',
|
||||
primary_action(values) {
|
||||
frappe.call({
|
||||
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit",
|
||||
args: {
|
||||
item_name: values.item_name,
|
||||
s_id: schedule_id,
|
||||
source_name: me.frm.doc.name,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
d.hide();
|
||||
}
|
||||
});
|
||||
d.show();
|
||||
});
|
||||
}, __('Create'));
|
||||
}, __('Create'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
start_date: function(doc, cdt, cdn) {
|
||||
start_date: function (doc, cdt, cdn) {
|
||||
this.set_no_of_visits(doc, cdt, cdn);
|
||||
},
|
||||
|
||||
end_date: function(doc, cdt, cdn) {
|
||||
end_date: function (doc, cdt, cdn) {
|
||||
this.set_no_of_visits(doc, cdt, cdn);
|
||||
},
|
||||
|
||||
periodicity: function(doc, cdt, cdn) {
|
||||
periodicity: function (doc, cdt, cdn) {
|
||||
this.set_no_of_visits(doc, cdt, cdn);
|
||||
|
||||
},
|
||||
no_of_visits: function (doc, cdt, cdn) {
|
||||
this.set_no_of_visits(doc, cdt, cdn);
|
||||
},
|
||||
|
||||
set_no_of_visits: function(doc, cdt, cdn) {
|
||||
set_no_of_visits: function (doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
|
||||
if (item.start_date && item.end_date && item.periodicity) {
|
||||
if(item.start_date > item.end_date) {
|
||||
frappe.msgprint(__("Row {0}:Start Date must be before End Date", [item.idx]));
|
||||
return;
|
||||
}
|
||||
|
||||
var date_diff = frappe.datetime.get_diff(item.end_date, item.start_date) + 1;
|
||||
|
||||
var days_in_period = {
|
||||
"Weekly": 7,
|
||||
"Monthly": 30,
|
||||
"Quarterly": 91,
|
||||
"Half Yearly": 182,
|
||||
"Yearly": 365
|
||||
}
|
||||
|
||||
var no_of_visits = cint(date_diff / days_in_period[item.periodicity]);
|
||||
frappe.model.set_value(item.doctype, item.name, "no_of_visits", no_of_visits);
|
||||
let me = this;
|
||||
if (item.start_date && item.periodicity) {
|
||||
me.frm.call('validate_end_date_visits');
|
||||
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
|
||||
$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({ frm: cur_frm }));
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,12 +4,13 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import add_days, getdate, cint, cstr
|
||||
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
|
||||
|
||||
class MaintenanceSchedule(TransactionBase):
|
||||
@frappe.whitelist()
|
||||
@ -32,8 +33,40 @@ class MaintenanceSchedule(TransactionBase):
|
||||
child.idx = count
|
||||
count = count + 1
|
||||
child.sales_person = d.sales_person
|
||||
child.completion_status = "Pending"
|
||||
child.item_reference = d.name
|
||||
|
||||
@frappe.whitelist()
|
||||
def validate_end_date_visits(self):
|
||||
days_in_period = {
|
||||
"Weekly": 7,
|
||||
"Monthly": 30,
|
||||
"Quarterly": 91,
|
||||
"Half Yearly": 182,
|
||||
"Yearly": 365
|
||||
}
|
||||
for item in self.items:
|
||||
if item.periodicity and item.start_date:
|
||||
if not item.end_date:
|
||||
if item.no_of_visits:
|
||||
item.end_date = add_days(item.start_date, item.no_of_visits * days_in_period[item.periodicity])
|
||||
else:
|
||||
item.end_date = add_days(item.start_date, days_in_period[item.periodicity])
|
||||
|
||||
diff = date_diff(item.end_date, item.start_date) + 1
|
||||
no_of_visits = cint(diff / days_in_period[item.periodicity])
|
||||
|
||||
if not item.no_of_visits or item.no_of_visits == 0:
|
||||
item.end_date = add_days(item.start_date, days_in_period[item.periodicity])
|
||||
diff = date_diff(item.end_date, item.start_date) + 1
|
||||
item.no_of_visits = cint(diff / days_in_period[item.periodicity])
|
||||
|
||||
elif item.no_of_visits > no_of_visits:
|
||||
item.end_date = add_days(item.start_date, item.no_of_visits * days_in_period[item.periodicity])
|
||||
|
||||
elif item.no_of_visits < no_of_visits:
|
||||
item.end_date = add_days(item.start_date, item.no_of_visits * days_in_period[item.periodicity])
|
||||
|
||||
self.save()
|
||||
|
||||
def on_submit(self):
|
||||
if not self.get('schedules'):
|
||||
@ -58,9 +91,10 @@ class MaintenanceSchedule(TransactionBase):
|
||||
|
||||
if no_email_sp:
|
||||
frappe.msgprint(
|
||||
frappe._("Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}").format(
|
||||
_("Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}").format(
|
||||
self.owner, "<br>" + "<br>".join(no_email_sp)
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
scheduled_date = frappe.db.sql("""select scheduled_date from
|
||||
`tabMaintenance Schedule Detail` where sales_person=%s and item_code=%s and
|
||||
@ -106,7 +140,7 @@ class MaintenanceSchedule(TransactionBase):
|
||||
if employee:
|
||||
holiday_list = get_holiday_list_for_employee(employee)
|
||||
else:
|
||||
holiday_list = frappe.get_cached_value('Company', self.company, "default_holiday_list")
|
||||
holiday_list = frappe.get_cached_value('Company', self.company, "default_holiday_list")
|
||||
|
||||
holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday` where parent=%s''', holiday_list)
|
||||
|
||||
@ -135,8 +169,7 @@ class MaintenanceSchedule(TransactionBase):
|
||||
}
|
||||
|
||||
if date_diff < days_in_period[d.periodicity]:
|
||||
throw(_("Row {0}: To set {1} periodicity, difference between from and to date \
|
||||
must be greater than or equal to {2}")
|
||||
throw(_("Row {0}: To set {1} periodicity, difference between from and to date must be greater than or equal to {2}")
|
||||
.format(d.idx, d.periodicity, days_in_period[d.periodicity]))
|
||||
|
||||
def validate_maintenance_detail(self):
|
||||
@ -166,13 +199,15 @@ class MaintenanceSchedule(TransactionBase):
|
||||
throw(_("Maintenance Schedule {0} exists against {1}").format(chk[0][0], d.sales_order))
|
||||
|
||||
def validate(self):
|
||||
self.validate_end_date_visits()
|
||||
self.validate_maintenance_detail()
|
||||
self.validate_dates_with_periodicity()
|
||||
self.validate_sales_order()
|
||||
self.generate_schedule()
|
||||
|
||||
def on_update(self):
|
||||
frappe.db.set(self, 'status', 'Draft')
|
||||
|
||||
|
||||
def update_amc_date(self, serial_nos, amc_expiry_date=None):
|
||||
for serial_no in serial_nos:
|
||||
serial_no_doc = frappe.get_doc("Serial No", serial_no)
|
||||
@ -202,8 +237,8 @@ class MaintenanceSchedule(TransactionBase):
|
||||
|
||||
if not sr_details.warehouse and sr_details.delivery_date and \
|
||||
getdate(sr_details.delivery_date) >= getdate(amc_start_date):
|
||||
throw(_("Maintenance start date can not be before delivery date for Serial No {0}")
|
||||
.format(serial_no))
|
||||
throw(_("Maintenance start date can not be before delivery date for Serial No {0}")
|
||||
.format(serial_no))
|
||||
|
||||
def validate_schedule(self):
|
||||
item_lst1 =[]
|
||||
@ -245,13 +280,50 @@ class MaintenanceSchedule(TransactionBase):
|
||||
def on_trash(self):
|
||||
delete_events(self.doctype, self.name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_pending_data(self, data_type, s_date=None, item_name=None):
|
||||
if data_type == "date":
|
||||
dates = ""
|
||||
for schedule in self.schedules:
|
||||
if schedule.item_name == item_name and schedule.completion_status == "Pending":
|
||||
dates = dates + "\n" + formatdate(schedule.scheduled_date, "dd-MM-yyyy")
|
||||
return dates
|
||||
elif data_type == "items":
|
||||
items = ""
|
||||
for item in self.items:
|
||||
for schedule in self.schedules:
|
||||
if item.item_name == schedule.item_name and schedule.completion_status == "Pending":
|
||||
items = items + "\n" + item.item_name
|
||||
break
|
||||
return items
|
||||
elif data_type == "id":
|
||||
for schedule in self.schedules:
|
||||
if schedule.item_name == item_name and s_date == formatdate(schedule.scheduled_date, "dd-mm-yyyy"):
|
||||
return schedule.name
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_maintenance_visit(source_name, target_doc=None):
|
||||
def update_serial_nos(s_id):
|
||||
serial_nos = frappe.db.get_value('Maintenance Schedule Detail', s_id, 'serial_no')
|
||||
if serial_nos:
|
||||
serial_nos = get_serial_nos(serial_nos)
|
||||
return serial_nos
|
||||
else:
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=None):
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
def update_status(source, target, parent):
|
||||
def update_status_and_detail(source, target, parent):
|
||||
target.maintenance_type = "Scheduled"
|
||||
|
||||
target.maintenance_schedule = source.name
|
||||
target.maintenance_schedule_detail = s_id
|
||||
|
||||
def update_sales(source, target, parent):
|
||||
sales_person = frappe.db.get_value('Maintenance Schedule Detail', s_id, 'sales_person')
|
||||
target.service_person = sales_person
|
||||
target.serial_no = ''
|
||||
|
||||
doclist = get_mapped_doc("Maintenance Schedule", source_name, {
|
||||
"Maintenance Schedule": {
|
||||
"doctype": "Maintenance Visit",
|
||||
@ -261,15 +333,12 @@ def make_maintenance_visit(source_name, target_doc=None):
|
||||
"validation": {
|
||||
"docstatus": ["=", 1]
|
||||
},
|
||||
"postprocess": update_status
|
||||
"postprocess": update_status_and_detail
|
||||
},
|
||||
"Maintenance Schedule Item": {
|
||||
"doctype": "Maintenance Visit Purpose",
|
||||
"field_map": {
|
||||
"parent": "prevdoc_docname",
|
||||
"parenttype": "prevdoc_doctype",
|
||||
"sales_person": "service_person"
|
||||
}
|
||||
"condition": lambda doc: doc.item_name == item_name,
|
||||
"postprocess": update_sales
|
||||
}
|
||||
}, target_doc)
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
from frappe.utils.data import get_datetime, add_days
|
||||
from frappe.utils.data import add_days, today, formatdate
|
||||
from erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule import make_maintenance_visit
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
@ -21,7 +22,57 @@ class TestMaintenanceSchedule(unittest.TestCase):
|
||||
ms.cancel()
|
||||
events_after_cancel = get_events(ms)
|
||||
self.assertTrue(len(events_after_cancel) == 0)
|
||||
|
||||
def test_make_schedule(self):
|
||||
ms = make_maintenance_schedule()
|
||||
ms.save()
|
||||
i = ms.items[0]
|
||||
expected_dates = []
|
||||
expected_end_date = add_days(i.start_date, i.no_of_visits * 7)
|
||||
self.assertEqual(i.end_date, expected_end_date)
|
||||
|
||||
i.no_of_visits = 2
|
||||
ms.save()
|
||||
expected_end_date = add_days(i.start_date, i.no_of_visits * 7)
|
||||
self.assertEqual(i.end_date, expected_end_date)
|
||||
|
||||
items = ms.get_pending_data(data_type = "items")
|
||||
items = items.split('\n')
|
||||
items.pop(0)
|
||||
expected_items = ['_Test Item']
|
||||
self.assertTrue(items, expected_items)
|
||||
|
||||
# "dates" contains all generated schedule dates
|
||||
dates = ms.get_pending_data(data_type = "date", item_name = i.item_name)
|
||||
dates = dates.split('\n')
|
||||
dates.pop(0)
|
||||
expected_dates.append(formatdate(add_days(i.start_date, 7), "dd-MM-yyyy"))
|
||||
expected_dates.append(formatdate(add_days(i.start_date, 14), "dd-MM-yyyy"))
|
||||
|
||||
# test for generated schedule dates
|
||||
self.assertEqual(dates, expected_dates)
|
||||
|
||||
ms.submit()
|
||||
s_id = ms.get_pending_data(data_type = "id", item_name = i.item_name, s_date = expected_dates[1])
|
||||
test = make_maintenance_visit(source_name = ms.name, item_name = "_Test Item", s_id = s_id)
|
||||
visit = frappe.new_doc('Maintenance Visit')
|
||||
visit = test
|
||||
visit.maintenance_schedule = ms.name
|
||||
visit.maintenance_schedule_detail = s_id
|
||||
visit.completion_status = "Partially Completed"
|
||||
visit.set('purposes', [{
|
||||
'item_code': i.item_code,
|
||||
'description': "test",
|
||||
'work_done': "test",
|
||||
'service_person': "Sales Team",
|
||||
}])
|
||||
visit.save()
|
||||
visit.submit()
|
||||
ms = frappe.get_doc('Maintenance Schedule', ms.name)
|
||||
|
||||
#checks if visit status is back updated in schedule
|
||||
self.assertTrue(ms.schedules[1].completion_status, "Partially Completed")
|
||||
|
||||
def get_events(ms):
|
||||
return frappe.get_all("Event Participants", filters={
|
||||
"reference_doctype": ms.doctype,
|
||||
@ -33,12 +84,11 @@ def make_maintenance_schedule():
|
||||
ms = frappe.new_doc("Maintenance Schedule")
|
||||
ms.company = "_Test Company"
|
||||
ms.customer = "_Test Customer"
|
||||
ms.transaction_date = get_datetime()
|
||||
ms.transaction_date = today()
|
||||
|
||||
ms.append("items", {
|
||||
"item_code": "_Test Item",
|
||||
"start_date": get_datetime(),
|
||||
"end_date": add_days(get_datetime(), 32),
|
||||
"start_date": today(),
|
||||
"periodicity": "Weekly",
|
||||
"no_of_visits": 4,
|
||||
"sales_person": "Sales Team",
|
||||
|
@ -1,222 +1,137 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "hash",
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:28:05",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-02-22 01:28:05",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item_code",
|
||||
"item_name",
|
||||
"column_break_3",
|
||||
"scheduled_date",
|
||||
"actual_date",
|
||||
"section_break_6",
|
||||
"sales_person",
|
||||
"column_break_8",
|
||||
"completion_status",
|
||||
"section_break_10",
|
||||
"serial_no",
|
||||
"item_reference"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"label": "Item Name",
|
||||
"oldfieldname": "item_name",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "scheduled_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": "Scheduled Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "scheduled_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"fieldname": "scheduled_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Scheduled Date",
|
||||
"oldfieldname": "scheduled_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "actual_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Actual Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "actual_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "actual_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Actual Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "actual_date",
|
||||
"oldfieldtype": "Date",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_person",
|
||||
"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": "Sales Person",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "incharge_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Sales Person",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"allow_on_submit": 1,
|
||||
"columns": 2,
|
||||
"fieldname": "sales_person",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Sales Person",
|
||||
"oldfieldname": "incharge_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Sales Person",
|
||||
"read_only_depends_on": "eval:doc.completion_status != \"Pending\""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small 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": "Serial No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "serial_no",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "160px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Serial No",
|
||||
"oldfieldname": "serial_no",
|
||||
"oldfieldtype": "Small Text",
|
||||
"print_width": "160px",
|
||||
"read_only": 1,
|
||||
"width": "160px"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "completion_status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Completion Status",
|
||||
"options": "Pending\nPartially Completed\nFully Completed",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "item_reference",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Item Reference",
|
||||
"options": "Maintenance Schedule Item",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-02-17 17:05:44.644663",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Maintenance",
|
||||
"name": "Maintenance Schedule Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-05-27 16:07:25.905015",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Maintenance",
|
||||
"name": "Maintenance Schedule Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,431 +1,160 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "hash",
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:28:05",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-02-22 01:28:05",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item_code",
|
||||
"item_name",
|
||||
"description",
|
||||
"column_break_4",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"periodicity",
|
||||
"schedule_details",
|
||||
"no_of_visits",
|
||||
"column_break_10",
|
||||
"sales_person",
|
||||
"reference",
|
||||
"serial_no",
|
||||
"sales_order"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"columns": 1,
|
||||
"fetch_from": "item_code.item_name",
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item_name",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item Name",
|
||||
"oldfieldname": "item_name",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "item_code.description",
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "300px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Data",
|
||||
"print_width": "300px",
|
||||
"read_only": 1,
|
||||
"width": "300px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "schedule_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"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": "schedule_details",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "start_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": "Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Start Date",
|
||||
"oldfieldname": "start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "end_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": "End Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "end_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "End Date",
|
||||
"oldfieldname": "end_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "periodicity",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Periodicity",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "periodicity",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nWeekly\nMonthly\nQuarterly\nHalf Yearly\nYearly\nRandom",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 1,
|
||||
"fieldname": "periodicity",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Periodicity",
|
||||
"oldfieldname": "periodicity",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nWeekly\nMonthly\nQuarterly\nHalf Yearly\nYearly\nRandom"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "no_of_visits",
|
||||
"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": "No of Visits",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "no_of_visits",
|
||||
"oldfieldtype": "Int",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 1,
|
||||
"fieldname": "no_of_visits",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "No of Visits",
|
||||
"oldfieldname": "no_of_visits",
|
||||
"oldfieldtype": "Int",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_person",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sales Person",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "incharge_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Sales Person",
|
||||
"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": "sales_person",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Person",
|
||||
"oldfieldname": "incharge_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Sales Person"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference",
|
||||
"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": "Reference",
|
||||
"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": "reference",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Reference"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Serial No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "serial_no",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Serial No",
|
||||
"oldfieldname": "serial_no",
|
||||
"oldfieldtype": "Small Text"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sales Order",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Sales Order",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Order",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Sales Order",
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-16 22:43:14.260729",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Maintenance",
|
||||
"name": "Maintenance Schedule Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-15 16:09:47.311994",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Maintenance",
|
||||
"name": "Maintenance Schedule Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -2,39 +2,62 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.maintenance");
|
||||
|
||||
var serial_nos = [];
|
||||
frappe.ui.form.on('Maintenance Visit', {
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
//filters for serial_no based on item_code
|
||||
frm.set_query('serial_no', 'purposes', function(frm, cdt, cdn) {
|
||||
frm.set_query('serial_no', 'purposes', function (frm, cdt, cdn) {
|
||||
let item = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'item_code': item.item_code
|
||||
}
|
||||
};
|
||||
if (serial_nos) {
|
||||
return {
|
||||
filters: {
|
||||
'item_code': item.item_code,
|
||||
'name': ["in", serial_nos]
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
filters: {
|
||||
'item_code': item.item_code
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frm.set_query('contact_person', erpnext.queries.contact_query);
|
||||
frm.set_query('customer_address', erpnext.queries.address_query);
|
||||
frm.set_query('customer', erpnext.queries.customer);
|
||||
},
|
||||
onload: function(frm) {
|
||||
onload: function (frm, cdt, cdn) {
|
||||
let item = locals[cdt][cdn];
|
||||
if (frm.maintenance_type == 'Scheduled') {
|
||||
let schedule_id = item.purposes[0].prevdoc_detail_docname;
|
||||
frappe.call({
|
||||
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.update_serial_nos",
|
||||
args: {
|
||||
s_id: schedule_id
|
||||
},
|
||||
callback: function (r) {
|
||||
serial_nos = r.message;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!frm.doc.status) {
|
||||
frm.set_value({status:'Draft'});
|
||||
frm.set_value({ status: 'Draft' });
|
||||
}
|
||||
if (frm.doc.__islocal) {
|
||||
frm.set_value({mntc_date: frappe.datetime.get_today()});
|
||||
frm.set_value({ mntc_date: frappe.datetime.get_today() });
|
||||
}
|
||||
},
|
||||
customer: function(frm) {
|
||||
customer: function (frm) {
|
||||
erpnext.utils.get_party_details(frm);
|
||||
},
|
||||
customer_address: function(frm) {
|
||||
customer_address: function (frm) {
|
||||
erpnext.utils.get_address_display(frm, 'customer_address', 'address_display');
|
||||
},
|
||||
contact_person: function(frm) {
|
||||
contact_person: function (frm) {
|
||||
erpnext.utils.get_contact_details(frm);
|
||||
}
|
||||
|
||||
@ -42,14 +65,14 @@ frappe.ui.form.on('Maintenance Visit', {
|
||||
|
||||
// TODO commonify this code
|
||||
erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
|
||||
refresh: function() {
|
||||
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
|
||||
refresh: function () {
|
||||
frappe.dynamic_link = { doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer' };
|
||||
|
||||
var me = this;
|
||||
|
||||
if (this.frm.doc.docstatus===0) {
|
||||
if (this.frm.doc.docstatus === 0) {
|
||||
this.frm.add_custom_button(__('Maintenance Schedule'),
|
||||
function() {
|
||||
function () {
|
||||
erpnext.utils.map_current_doc({
|
||||
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit",
|
||||
source_doctype: "Maintenance Schedule",
|
||||
@ -64,7 +87,7 @@ erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
|
||||
})
|
||||
}, __("Get Items From"));
|
||||
this.frm.add_custom_button(__('Warranty Claim'),
|
||||
function() {
|
||||
function () {
|
||||
erpnext.utils.map_current_doc({
|
||||
method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit",
|
||||
source_doctype: "Warranty Claim",
|
||||
@ -80,7 +103,7 @@ erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
|
||||
})
|
||||
}, __("Get Items From"));
|
||||
this.frm.add_custom_button(__('Sales Order'),
|
||||
function() {
|
||||
function () {
|
||||
erpnext.utils.map_current_doc({
|
||||
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
|
||||
source_doctype: "Sales Order",
|
||||
@ -99,4 +122,4 @@ erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
|
||||
},
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({frm: cur_frm}));
|
||||
$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({ frm: cur_frm }));
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import get_datetime
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
|
||||
@ -16,44 +17,62 @@ class MaintenanceVisit(TransactionBase):
|
||||
if d.serial_no and not frappe.db.exists("Serial No", d.serial_no):
|
||||
frappe.throw(_("Serial No {0} does not exist").format(d.serial_no))
|
||||
|
||||
def validate_maintenance_date(self):
|
||||
if self.maintenance_type == "Scheduled" and self.maintenance_schedule_detail:
|
||||
item_ref = frappe.db.get_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'item_reference')
|
||||
if item_ref:
|
||||
start_date, end_date = frappe.db.get_value('Maintenance Schedule Item', item_ref, ['start_date', 'end_date'])
|
||||
if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime(self.mntc_date) > get_datetime(end_date):
|
||||
frappe.throw(_("Date must be between {0} and {1}").format(start_date, end_date))
|
||||
|
||||
def validate(self):
|
||||
self.validate_serial_no()
|
||||
self.validate_maintenance_date()
|
||||
|
||||
def update_completion_status(self):
|
||||
if self.maintenance_schedule_detail:
|
||||
frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'completion_status', self.completion_status)
|
||||
|
||||
def update_actual_date(self):
|
||||
if self.maintenance_schedule_detail:
|
||||
frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'actual_date', self.mntc_date)
|
||||
|
||||
def update_customer_issue(self, flag):
|
||||
for d in self.get('purposes'):
|
||||
if d.prevdoc_docname and d.prevdoc_doctype == 'Warranty Claim' :
|
||||
if flag==1:
|
||||
mntc_date = self.mntc_date
|
||||
service_person = d.service_person
|
||||
work_done = d.work_done
|
||||
status = "Open"
|
||||
if self.completion_status == 'Fully Completed':
|
||||
status = 'Closed'
|
||||
elif self.completion_status == 'Partially Completed':
|
||||
status = 'Work In Progress'
|
||||
else:
|
||||
nm = frappe.db.sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.name))
|
||||
|
||||
if nm:
|
||||
status = 'Work In Progress'
|
||||
mntc_date = nm and nm[0][1] or ''
|
||||
service_person = nm and nm[0][2] or ''
|
||||
work_done = nm and nm[0][3] or ''
|
||||
if not self.maintenance_schedule:
|
||||
for d in self.get('purposes'):
|
||||
if d.prevdoc_docname and d.prevdoc_doctype == 'Warranty Claim' :
|
||||
if flag==1:
|
||||
mntc_date = self.mntc_date
|
||||
service_person = d.service_person
|
||||
work_done = d.work_done
|
||||
status = "Open"
|
||||
if self.completion_status == 'Fully Completed':
|
||||
status = 'Closed'
|
||||
elif self.completion_status == 'Partially Completed':
|
||||
status = 'Work In Progress'
|
||||
else:
|
||||
status = 'Open'
|
||||
mntc_date = None
|
||||
service_person = None
|
||||
work_done = None
|
||||
nm = frappe.db.sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.name))
|
||||
|
||||
wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname)
|
||||
wc_doc.update({
|
||||
'resolution_date': mntc_date,
|
||||
'resolved_by': service_person,
|
||||
'resolution_details': work_done,
|
||||
'status': status
|
||||
})
|
||||
if nm:
|
||||
status = 'Work In Progress'
|
||||
mntc_date = nm and nm[0][1] or ''
|
||||
service_person = nm and nm[0][2] or ''
|
||||
work_done = nm and nm[0][3] or ''
|
||||
else:
|
||||
status = 'Open'
|
||||
mntc_date = None
|
||||
service_person = None
|
||||
work_done = None
|
||||
|
||||
wc_doc.db_update()
|
||||
wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname)
|
||||
wc_doc.update({
|
||||
'resolution_date': mntc_date,
|
||||
'resolved_by': service_person,
|
||||
'resolution_details': work_done,
|
||||
'status': status
|
||||
})
|
||||
|
||||
wc_doc.db_update()
|
||||
|
||||
def check_if_last_visit(self):
|
||||
"""check if last maintenance visit against same sales order/ Warranty Claim"""
|
||||
@ -77,6 +96,8 @@ class MaintenanceVisit(TransactionBase):
|
||||
def on_submit(self):
|
||||
self.update_customer_issue(1)
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
self.update_completion_status()
|
||||
self.update_actual_date()
|
||||
|
||||
def on_cancel(self):
|
||||
self.check_if_last_visit()
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-02-22 01:28:06",
|
||||
"doctype": "DocType",
|
||||
@ -8,14 +9,15 @@
|
||||
"field_order": [
|
||||
"item_code",
|
||||
"item_name",
|
||||
"column_break_3",
|
||||
"service_person",
|
||||
"serial_no",
|
||||
"section_break_6",
|
||||
"description",
|
||||
"work_details",
|
||||
"service_person",
|
||||
"work_done",
|
||||
"prevdoc_doctype",
|
||||
"prevdoc_docname",
|
||||
"prevdoc_detail_docname"
|
||||
"prevdoc_docname"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -62,6 +64,8 @@
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "prevdoc_detail_docname.sales_person",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "service_person",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@ -83,49 +87,30 @@
|
||||
{
|
||||
"fieldname": "prevdoc_doctype",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Document Type",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_doctype",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "DocType",
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"report_hide": 1,
|
||||
"width": "150px"
|
||||
"options": "DocType"
|
||||
},
|
||||
{
|
||||
"fieldname": "prevdoc_docname",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 1,
|
||||
"label": "Against Document No",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "prevdoc_doctype",
|
||||
"print_hide": 1,
|
||||
"print_width": "160px",
|
||||
"read_only": 1,
|
||||
"report_hide": 1,
|
||||
"width": "160px"
|
||||
"options": "prevdoc_doctype"
|
||||
},
|
||||
{
|
||||
"fieldname": "prevdoc_detail_docname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Against Document Detail No",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_detail_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"print_hide": 1,
|
||||
"print_width": "160px",
|
||||
"read_only": 1,
|
||||
"report_hide": 1,
|
||||
"width": "160px"
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2020-09-18 17:26:09.703215",
|
||||
"links": [],
|
||||
"modified": "2021-05-27 17:47:21.474282",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Maintenance",
|
||||
"name": "Maintenance Visit Purpose",
|
||||
|
@ -433,7 +433,8 @@ def make_material_request(source_name, target_doc=None):
|
||||
def make_stock_entry(source_name, target_doc=None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.t_warehouse = source_parent.wip_warehouse
|
||||
target.conversion_factor = 1
|
||||
if not target.conversion_factor:
|
||||
target.conversion_factor = 1
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.purpose = "Material Transfer for Manufacture"
|
||||
|
@ -211,16 +211,27 @@ frappe.ui.form.on('Production Plan', {
|
||||
});
|
||||
},
|
||||
|
||||
get_items: function(frm) {
|
||||
get_items: function (frm) {
|
||||
frm.clear_table('prod_plan_references');
|
||||
|
||||
frappe.call({
|
||||
method: "get_items",
|
||||
freeze: true,
|
||||
doc: frm.doc,
|
||||
callback: function() {
|
||||
callback: function () {
|
||||
refresh_field('po_items');
|
||||
}
|
||||
});
|
||||
},
|
||||
combine_items: function (frm) {
|
||||
frm.clear_table('prod_plan_references');
|
||||
|
||||
frappe.call({
|
||||
method: "get_items",
|
||||
freeze: true,
|
||||
doc: frm.doc,
|
||||
});
|
||||
},
|
||||
|
||||
get_items_for_mr: function(frm) {
|
||||
if (!frm.doc.for_warehouse) {
|
||||
|
@ -28,7 +28,10 @@
|
||||
"material_requests",
|
||||
"select_items_to_manufacture_section",
|
||||
"get_items",
|
||||
"combine_items",
|
||||
"po_items",
|
||||
"section_break_25",
|
||||
"prod_plan_references",
|
||||
"material_request_planning",
|
||||
"include_non_stock_items",
|
||||
"include_subcontracted_items",
|
||||
@ -316,13 +319,31 @@
|
||||
"fieldname": "include_safety_stock",
|
||||
"fieldtype": "Check",
|
||||
"label": "Include Safety Stock in Required Qty Calculation"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.get_items_from == 'Sales Order'",
|
||||
"fieldname": "combine_items",
|
||||
"fieldtype": "Check",
|
||||
"label": "Consolidate Items"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_25",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "prod_plan_references",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 1,
|
||||
"label": "Production Plan Item Reference",
|
||||
"options": "Production Plan Item Reference"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-calendar",
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-08 11:17:25.470147",
|
||||
"modified": "2021-05-24 16:59:03.643211",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Plan",
|
||||
|
@ -96,8 +96,10 @@ class ProductionPlan(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_items(self):
|
||||
self.set('po_items', [])
|
||||
if self.get_items_from == "Sales Order":
|
||||
self.get_so_items()
|
||||
self.get_so_items()
|
||||
|
||||
elif self.get_items_from == "Material Request":
|
||||
self.get_mr_items()
|
||||
|
||||
@ -165,9 +167,31 @@ class ProductionPlan(Document):
|
||||
self.calculate_total_planned_qty()
|
||||
|
||||
def add_items(self, items):
|
||||
self.set('po_items', [])
|
||||
refs = {}
|
||||
for data in items:
|
||||
item_details = get_item_details(data.item_code)
|
||||
if self.combine_items:
|
||||
if item_details.bom_no in refs:
|
||||
refs[item_details.bom_no]['so_details'].append({
|
||||
'sales_order': data.parent,
|
||||
'sales_order_item': data.name,
|
||||
'qty': data.pending_qty
|
||||
})
|
||||
refs[item_details.bom_no]['qty'] += data.pending_qty
|
||||
continue
|
||||
|
||||
else:
|
||||
refs[item_details.bom_no] = {
|
||||
'qty': data.pending_qty,
|
||||
'po_item_ref': data.name,
|
||||
'so_details': []
|
||||
}
|
||||
refs[item_details.bom_no]['so_details'].append({
|
||||
'sales_order': data.parent,
|
||||
'sales_order_item': data.name,
|
||||
'qty': data.pending_qty
|
||||
})
|
||||
|
||||
pi = self.append('po_items', {
|
||||
'include_exploded_items': 1,
|
||||
'warehouse': data.warehouse,
|
||||
@ -185,11 +209,28 @@ class ProductionPlan(Document):
|
||||
pi.sales_order = data.parent
|
||||
pi.sales_order_item = data.name
|
||||
pi.description = data.description
|
||||
|
||||
|
||||
elif self.get_items_from == "Material Request":
|
||||
pi.material_request = data.parent
|
||||
pi.material_request_item = data.name
|
||||
pi.description = data.description
|
||||
|
||||
if refs:
|
||||
for po_item in self.po_items:
|
||||
po_item.planned_qty = refs[po_item.bom_no]['qty']
|
||||
po_item.pending_qty = refs[po_item.bom_no]['qty']
|
||||
po_item.sales_order = ''
|
||||
self.add_pp_ref(refs)
|
||||
|
||||
def add_pp_ref(self, refs):
|
||||
for bom_no in refs:
|
||||
for so_detail in refs[bom_no]['so_details']:
|
||||
self.append('prod_plan_references', {
|
||||
'item_reference': refs[bom_no]['po_item_ref'],
|
||||
'sales_order': so_detail['sales_order'],
|
||||
'sales_order_item': so_detail['sales_order_item'],
|
||||
'qty': so_detail['qty']
|
||||
})
|
||||
|
||||
def calculate_total_planned_qty(self):
|
||||
self.total_planned_qty = 0
|
||||
|
@ -100,7 +100,7 @@ class TestProductionPlan(unittest.TestCase):
|
||||
|
||||
def test_production_plan_sales_orders(self):
|
||||
item = 'Test Production Item 1'
|
||||
so = make_sales_order(item_code=item, qty=5)
|
||||
so = make_sales_order(item_code=item, qty=1)
|
||||
sales_order = so.name
|
||||
sales_order_item = so.items[0].name
|
||||
|
||||
@ -124,8 +124,8 @@ class TestProductionPlan(unittest.TestCase):
|
||||
|
||||
wo_doc = frappe.get_doc('Work Order', work_order)
|
||||
wo_doc.update({
|
||||
'wip_warehouse': '_Test Warehouse 1 - _TC',
|
||||
'fg_warehouse': '_Test Warehouse - _TC'
|
||||
'wip_warehouse': 'Work In Progress - _TC',
|
||||
'fg_warehouse': 'Finished Goods - _TC'
|
||||
})
|
||||
wo_doc.submit()
|
||||
|
||||
@ -145,6 +145,58 @@ class TestProductionPlan(unittest.TestCase):
|
||||
|
||||
self.assertEqual(sales_orders, [])
|
||||
|
||||
def test_production_plan_combine_items(self):
|
||||
item = 'Test Production Item 1'
|
||||
so = make_sales_order(item_code=item, qty=1)
|
||||
|
||||
pln = frappe.new_doc('Production Plan')
|
||||
pln.company = so.company
|
||||
pln.get_items_from = 'Sales Order'
|
||||
pln.append('sales_orders', {
|
||||
'sales_order': so.name,
|
||||
'sales_order_date': so.transaction_date,
|
||||
'customer': so.customer,
|
||||
'grand_total': so.grand_total
|
||||
})
|
||||
so = make_sales_order(item_code=item, qty=2)
|
||||
pln.append('sales_orders', {
|
||||
'sales_order': so.name,
|
||||
'sales_order_date': so.transaction_date,
|
||||
'customer': so.customer,
|
||||
'grand_total': so.grand_total
|
||||
})
|
||||
pln.combine_items = 1
|
||||
pln.get_items()
|
||||
pln.submit()
|
||||
|
||||
self.assertTrue(pln.po_items[0].planned_qty, 3)
|
||||
|
||||
pln.make_work_order()
|
||||
work_order = frappe.db.get_value('Work Order', {
|
||||
'production_plan_item': pln.po_items[0].name,
|
||||
'production_plan': pln.name
|
||||
}, 'name')
|
||||
|
||||
wo_doc = frappe.get_doc('Work Order', work_order)
|
||||
wo_doc.update({
|
||||
'wip_warehouse': 'Work In Progress - _TC',
|
||||
})
|
||||
|
||||
wo_doc.submit()
|
||||
so_items = []
|
||||
for plan_reference in pln.prod_plan_references:
|
||||
so_items.append(plan_reference.sales_order_item)
|
||||
so_wo_qty = frappe.db.get_value('Sales Order Item', plan_reference.sales_order_item, 'work_order_qty')
|
||||
self.assertEqual(so_wo_qty, plan_reference.qty)
|
||||
|
||||
wo_doc.cancel()
|
||||
for so_item in so_items:
|
||||
so_wo_qty = frappe.db.get_value('Sales Order Item', so_item, 'work_order_qty')
|
||||
self.assertEqual(so_wo_qty, 0.0)
|
||||
|
||||
latest_plan = frappe.get_doc('Production Plan', pln.name)
|
||||
latest_plan.cancel()
|
||||
|
||||
def test_pp_to_mr_customer_provided(self):
|
||||
#Material Request from Production Plan for Customer Provided
|
||||
create_item('CUST-0987', is_customer_provided_item = 1, customer = '_Test Customer', is_purchase_item = 0)
|
||||
|
@ -1,792 +1,229 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "hash",
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"include_exploded_items",
|
||||
"item_code",
|
||||
"bom_no",
|
||||
"planned_qty",
|
||||
"column_break_6",
|
||||
"make_work_order_for_sub_assembly_items",
|
||||
"warehouse",
|
||||
"planned_start_date",
|
||||
"section_break_9",
|
||||
"pending_qty",
|
||||
"ordered_qty",
|
||||
"produced_qty",
|
||||
"column_break_17",
|
||||
"description",
|
||||
"stock_uom",
|
||||
"reference_section",
|
||||
"sales_order",
|
||||
"sales_order_item",
|
||||
"column_break_19",
|
||||
"material_request",
|
||||
"material_request_item",
|
||||
"product_bundle_item",
|
||||
"item_reference"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "include_exploded_items",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Include Exploded Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"columns": 2,
|
||||
"default": "0",
|
||||
"fieldname": "include_exploded_items",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Include Exploded Items"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "150px",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"print_width": "150px",
|
||||
"reqd": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "bom_no",
|
||||
"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": "BOM No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "100px",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"print_width": "100px",
|
||||
"reqd": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "planned_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Planned Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "planned_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "100px",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "planned_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Planned Qty",
|
||||
"oldfieldname": "planned_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"print_width": "100px",
|
||||
"reqd": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "If enabled, system will create the work order for the exploded items against which BOM is available.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "make_work_order_for_sub_assembly_items",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Make Work Order for Sub Assembly Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"description": "If enabled, system will create the work order for the exploded items against which BOM is available.",
|
||||
"fieldname": "make_work_order_for_sub_assembly_items",
|
||||
"fieldtype": "Check",
|
||||
"label": "Make Work Order for Sub Assembly Items"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "For Warehouse",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "For Warehouse",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "planned_start_date",
|
||||
"fieldtype": "Datetime",
|
||||
"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": "Planned Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "Today",
|
||||
"fieldname": "planned_start_date",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 1,
|
||||
"label": "Planned Start Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Quantity and Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Quantity and Description"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "pending_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Pending Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "prevdoc_reqd_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "100px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"default": "0",
|
||||
"fieldname": "pending_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Pending Qty",
|
||||
"oldfieldname": "prevdoc_reqd_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"print_width": "100px",
|
||||
"read_only": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "ordered_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Ordered Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "ordered_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Ordered Qty",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Produced Qty",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Produced Qty",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_17",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_17",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "200px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "200px",
|
||||
"read_only": 1,
|
||||
"width": "200px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "80px",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "UOM",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"print_width": "80px",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "80px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "reference_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": "Reference",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "reference_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Reference"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sales Order",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "source_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Sales Order",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Order",
|
||||
"oldfieldname": "source_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Sales Order",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_order_item",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sales Order Item",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "sales_order_item",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Sales Order Item",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "material_request",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Material Request",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Material Request",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "material_request",
|
||||
"fieldtype": "Link",
|
||||
"label": "Material Request",
|
||||
"options": "Material Request",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "material_request_item",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "material_request_item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "material_request_item",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "material_request_item"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "product_bundle_item",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Product Bundle Item",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "product_bundle_item",
|
||||
"fieldtype": "Link",
|
||||
"label": "Product Bundle Item",
|
||||
"no_copy": 1,
|
||||
"options": "Item",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "item_reference",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Item Reference"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-04-08 23:09:57.199423",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Plan Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-28 19:14:57.772123",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Plan Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC"
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2021-04-22 10:32:58.896330",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item_reference",
|
||||
"sales_order",
|
||||
"sales_order_item",
|
||||
"qty"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Sales Order Reference",
|
||||
"options": "Sales Order"
|
||||
},
|
||||
{
|
||||
"fieldname": "sales_order_item",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Sales Order Item"
|
||||
},
|
||||
{
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "qty"
|
||||
},
|
||||
{
|
||||
"fieldname": "item_reference",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Reference"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-05-07 17:03:49.707487",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Plan Item Reference",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- 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 ProductionPlanItemReference(Document):
|
||||
pass
|
@ -240,8 +240,12 @@ class WorkOrder(Document):
|
||||
frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
|
||||
if not self.fg_warehouse:
|
||||
frappe.throw(_("For Warehouse is required before Submit"))
|
||||
|
||||
if self.production_plan and frappe.db.exists('Production Plan Item Reference',{'parent':self.production_plan}):
|
||||
self.update_work_order_qty_in_combined_so()
|
||||
else:
|
||||
self.update_work_order_qty_in_so()
|
||||
|
||||
self.update_work_order_qty_in_so()
|
||||
self.update_reserved_qty_for_production()
|
||||
self.update_completed_qty_in_material_request()
|
||||
self.update_planned_qty()
|
||||
@ -250,9 +254,13 @@ class WorkOrder(Document):
|
||||
|
||||
def on_cancel(self):
|
||||
self.validate_cancel()
|
||||
|
||||
frappe.db.set(self,'status', 'Cancelled')
|
||||
self.update_work_order_qty_in_so()
|
||||
|
||||
if self.production_plan and frappe.db.exists('Production Plan Item Reference',{'parent':self.production_plan}):
|
||||
self.update_work_order_qty_in_combined_so()
|
||||
else:
|
||||
self.update_work_order_qty_in_so()
|
||||
|
||||
self.delete_job_card()
|
||||
self.update_completed_qty_in_material_request()
|
||||
self.update_planned_qty()
|
||||
@ -357,7 +365,28 @@ class WorkOrder(Document):
|
||||
work_order_qty = qty[0][0] if qty and qty[0][0] else 0
|
||||
frappe.db.set_value('Sales Order Item',
|
||||
self.sales_order_item, 'work_order_qty', flt(work_order_qty/total_bundle_qty, 2))
|
||||
|
||||
def update_work_order_qty_in_combined_so(self):
|
||||
total_bundle_qty = 1
|
||||
if self.product_bundle_item:
|
||||
total_bundle_qty = frappe.db.sql(""" select sum(qty) from
|
||||
`tabProduct Bundle Item` where parent = %s""", (frappe.db.escape(self.product_bundle_item)))[0][0]
|
||||
|
||||
if not total_bundle_qty:
|
||||
# product bundle is 0 (product bundle allows 0 qty for items)
|
||||
total_bundle_qty = 1
|
||||
|
||||
prod_plan = frappe.get_doc('Production Plan', self.production_plan)
|
||||
item_reference = frappe.get_value('Production Plan Item', self.production_plan_item, 'sales_order_item')
|
||||
|
||||
for plan_reference in prod_plan.prod_plan_references:
|
||||
work_order_qty = 0.0
|
||||
if plan_reference.item_reference == item_reference:
|
||||
if self.docstatus == 1:
|
||||
work_order_qty = flt(plan_reference.qty) / total_bundle_qty
|
||||
frappe.db.set_value('Sales Order Item',
|
||||
plan_reference.sales_order_item, 'work_order_qty', work_order_qty)
|
||||
|
||||
def update_completed_qty_in_material_request(self):
|
||||
if self.material_request:
|
||||
frappe.get_doc("Material Request", self.material_request).update_completed_qty([self.material_request_item])
|
||||
|
@ -28,7 +28,7 @@ class Member(Document):
|
||||
def setup_subscription(self):
|
||||
non_profit_settings = frappe.get_doc('Non Profit Settings')
|
||||
if not non_profit_settings.enable_razorpay_for_memberships:
|
||||
frappe.throw('Please check Enable Razorpay for Memberships in {0} to setup subscription').format(
|
||||
frappe.throw(_('Please check Enable Razorpay for Memberships in {0} to setup subscription')).format(
|
||||
get_link_to_form('Non Profit Settings', 'Non Profit Settings'))
|
||||
|
||||
controller = get_payment_gateway_controller("Razorpay")
|
||||
|
@ -1,494 +1,19 @@
|
||||
execute:import unidecode # new requirement
|
||||
erpnext.patches.v8_0.move_perpetual_inventory_setting
|
||||
erpnext.patches.v8_9.set_print_zero_amount_taxes
|
||||
erpnext.patches.v12_0.update_is_cancelled_field
|
||||
erpnext.patches.v11_0.rename_production_order_to_work_order
|
||||
erpnext.patches.v11_0.refactor_naming_series
|
||||
erpnext.patches.v11_0.refactor_autoname_naming
|
||||
erpnext.patches.v10_0.rename_schools_to_education
|
||||
erpnext.patches.v4_0.validate_v3_patch
|
||||
erpnext.patches.v4_0.fix_employee_user_id
|
||||
erpnext.patches.v4_0.remove_employee_role_if_no_employee
|
||||
erpnext.patches.v4_0.update_user_properties
|
||||
erpnext.patches.v4_0.apply_user_permissions
|
||||
erpnext.patches.v4_0.move_warehouse_user_to_restrictions
|
||||
erpnext.patches.v4_0.global_defaults_to_system_settings
|
||||
erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
|
||||
execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
|
||||
execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24
|
||||
execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
|
||||
execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29
|
||||
execute:frappe.reload_doc('selling', 'doctype', 'quotation') # 2014-01-29
|
||||
execute:frappe.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-29
|
||||
erpnext.patches.v4_0.reload_sales_print_format
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') # 2014-01-29
|
||||
execute:frappe.reload_doc('buying', 'doctype', 'purchase_order') # 2014-01-29
|
||||
execute:frappe.reload_doc('buying', 'doctype', 'supplier_quotation') # 2014-01-29
|
||||
execute:frappe.reload_doc('stock', 'doctype', 'purchase_receipt') # 2014-01-29
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'pos_setting') # 2014-01-29
|
||||
execute:frappe.reload_doc('selling', 'doctype', 'customer') # 2014-01-29
|
||||
execute:frappe.reload_doc('buying', 'doctype', 'supplier') # 2014-01-29
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'asset_category')
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'pricing_rule')
|
||||
erpnext.patches.v4_0.map_charge_to_taxes_and_charges
|
||||
execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31
|
||||
execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03
|
||||
execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'")
|
||||
erpnext.patches.v5_2.change_item_selects_to_checks
|
||||
execute:frappe.reload_doctype('Item')
|
||||
erpnext.patches.v4_0.fields_to_be_renamed
|
||||
erpnext.patches.v4_0.rename_sitemap_to_route
|
||||
erpnext.patches.v7_0.re_route #2016-06-27
|
||||
erpnext.patches.v4_0.fix_contact_address
|
||||
erpnext.patches.v4_0.customer_discount_to_pricing_rule
|
||||
execute:frappe.db.sql("""delete from `tabWebsite Item Group` where ifnull(item_group, '')=''""")
|
||||
erpnext.patches.v4_0.remove_module_home_pages
|
||||
erpnext.patches.v4_0.split_email_settings
|
||||
erpnext.patches.v4_0.import_country_codes
|
||||
erpnext.patches.v4_0.countrywise_coa
|
||||
execute:frappe.delete_doc("DocType", "MIS Control")
|
||||
execute:frappe.delete_doc("Page", "Financial Statements")
|
||||
execute:frappe.delete_doc("DocType", "Stock Ledger")
|
||||
execute:frappe.delete_doc("DocType", "Grade")
|
||||
execute:frappe.db.sql("delete from `tabWebsite Item Group` where ifnull(item_group, '')=''")
|
||||
execute:frappe.delete_doc("Print Format", "SalesInvoice")
|
||||
execute:import frappe.defaults;frappe.defaults.clear_default("price_list_currency")
|
||||
erpnext.patches.v4_0.update_account_root_type
|
||||
execute:frappe.delete_doc("Report", "Purchase In Transit")
|
||||
erpnext.patches.v4_0.new_address_template
|
||||
execute:frappe.delete_doc("DocType", "SMS Control")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Bulk SMS") #2015-08-18
|
||||
erpnext.patches.v4_0.fix_case_of_hr_module_def
|
||||
erpnext.patches.v4_0.fix_address_template
|
||||
|
||||
# WATCHOUT: This patch reload's documents
|
||||
erpnext.patches.v4_0.reset_permissions_for_masters
|
||||
erpnext.patches.v6_20x.rename_project_name_to_project #2016-03-14
|
||||
|
||||
erpnext.patches.v4_0.update_tax_amount_after_discount
|
||||
execute:frappe.permissions.reset_perms("GL Entry") #2014-06-09
|
||||
execute:frappe.permissions.reset_perms("Stock Ledger Entry") #2014-06-09
|
||||
erpnext.patches.v4_0.create_custom_fields_for_india_specific_fields
|
||||
erpnext.patches.v4_0.save_default_letterhead
|
||||
erpnext.patches.v4_0.update_custom_print_formats_for_renamed_fields
|
||||
erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats
|
||||
erpnext.patches.v4_0.create_price_list_if_missing
|
||||
execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16
|
||||
erpnext.patches.v4_0.update_users_report_view_settings
|
||||
erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling
|
||||
erpnext.patches.v4_1.set_outgoing_email_footer
|
||||
erpnext.patches.v4_1.fix_sales_order_delivered_status
|
||||
erpnext.patches.v4_1.fix_delivery_and_billing_status
|
||||
execute:frappe.db.sql("update `tabAccount` set root_type='Liability' where root_type='Income' and report_type='Balance Sheet'")
|
||||
execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool") # 29-07-2014
|
||||
execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool Detail") # 29-07-2014
|
||||
execute:frappe.delete_doc("Page", "trial-balance") #2014-07-22
|
||||
erpnext.patches.v4_2.delete_old_print_formats #2014-07-29
|
||||
erpnext.patches.v4_2.toggle_rounded_total #2014-07-30
|
||||
erpnext.patches.v4_2.fix_account_master_type
|
||||
erpnext.patches.v4_2.update_project_milestones
|
||||
erpnext.patches.v4_2.add_currency_turkish_lira #2014-08-08
|
||||
execute:frappe.delete_doc("DocType", "Landed Cost Wizard")
|
||||
erpnext.patches.v4_2.default_website_style
|
||||
erpnext.patches.v4_2.set_company_country
|
||||
erpnext.patches.v4_2.update_sales_order_invoice_field_name
|
||||
erpnext.patches.v4_2.seprate_manufacture_and_repack
|
||||
execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
|
||||
execute:frappe.delete_doc("DocType", "Purchase Request")
|
||||
execute:frappe.delete_doc("DocType", "Purchase Request Item")
|
||||
erpnext.patches.v4_2.recalculate_bom_cost
|
||||
erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
|
||||
erpnext.patches.v4_2.update_requested_and_ordered_qty #2021-03-31
|
||||
execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True)
|
||||
erpnext.patches.v4_4.make_email_accounts
|
||||
execute:frappe.delete_doc("DocType", "Contact Control")
|
||||
erpnext.patches.v4_2.discount_amount
|
||||
erpnext.patches.v4_2.reset_bom_costs
|
||||
erpnext.patches.v5_0.update_frozen_accounts_permission_role
|
||||
erpnext.patches.v5_0.update_dn_against_doc_fields
|
||||
execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'")
|
||||
execute:frappe.reload_doc('stock', 'doctype', 'item')
|
||||
erpnext.patches.v5_0.set_default_company_in_bom
|
||||
execute:frappe.reload_doc('crm', 'doctype', 'lead')
|
||||
execute:frappe.reload_doc('crm', 'doctype', 'opportunity')
|
||||
erpnext.patches.v5_0.rename_taxes_and_charges_master
|
||||
erpnext.patches.v5_1.sales_bom_rename
|
||||
erpnext.patches.v5_0.rename_table_fieldnames
|
||||
execute:frappe.db.sql("update `tabJournal Entry` set voucher_type='Journal Entry' where ifnull(voucher_type, '')=''")
|
||||
erpnext.patches.v5_0.is_group
|
||||
erpnext.patches.v4_2.party_model
|
||||
erpnext.patches.v5_0.party_model_patch_fix
|
||||
erpnext.patches.v4_1.fix_jv_remarks
|
||||
erpnext.patches.v4_2.update_landed_cost_voucher
|
||||
erpnext.patches.v4_2.set_item_has_batch
|
||||
erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle
|
||||
erpnext.patches.v5_0.recalculate_total_amount_in_jv
|
||||
erpnext.patches.v5_0.update_companywise_payment_account
|
||||
erpnext.patches.v5_0.remove_birthday_events
|
||||
erpnext.patches.v5_0.update_item_name_in_bom
|
||||
erpnext.patches.v5_0.rename_customer_issue
|
||||
erpnext.patches.v5_0.rename_total_fields
|
||||
erpnext.patches.v5_0.new_crm_module
|
||||
erpnext.patches.v5_0.rename_customer_issue
|
||||
erpnext.patches.v5_0.update_material_transfer_for_manufacture
|
||||
execute:frappe.reload_doc('crm', 'doctype', 'opportunity_item')
|
||||
erpnext.patches.v5_0.update_item_description_and_image
|
||||
erpnext.patches.v5_0.update_material_transferred_for_manufacturing
|
||||
erpnext.patches.v5_0.stock_entry_update_value
|
||||
erpnext.patches.v5_0.convert_stock_reconciliation
|
||||
erpnext.patches.v5_0.update_projects
|
||||
erpnext.patches.v5_0.item_patches
|
||||
erpnext.patches.v5_0.update_journal_entry_title
|
||||
erpnext.patches.v5_0.taxes_and_totals_in_party_currency
|
||||
erpnext.patches.v5_0.replace_renamed_fields_in_custom_scripts_and_print_formats
|
||||
erpnext.patches.v5_0.update_from_bom
|
||||
erpnext.patches.v5_0.update_account_types
|
||||
erpnext.patches.v5_0.update_sms_sender
|
||||
erpnext.patches.v5_0.set_appraisal_remarks
|
||||
erpnext.patches.v5_0.update_time_log_title
|
||||
erpnext.patches.v7_0.create_warehouse_nestedset
|
||||
erpnext.patches.v7_0.merge_account_type_stock_and_warehouse_to_stock
|
||||
erpnext.patches.v7_0.set_is_group_for_warehouse
|
||||
erpnext.patches.v7_2.stock_uom_in_selling
|
||||
erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
|
||||
erpnext.patches.v5_0.newsletter
|
||||
execute:frappe.delete_doc("DocType", "Chart of Accounts")
|
||||
execute:frappe.delete_doc("DocType", "Style Settings")
|
||||
erpnext.patches.v5_0.update_opportunity
|
||||
erpnext.patches.v5_0.opportunity_not_submittable
|
||||
execute:frappe.permissions.reset_perms("Purchase Taxes and Charges Template") #2014-06-09
|
||||
execute:frappe.permissions.reset_perms("Expense Claim Type") #2014-06-19
|
||||
erpnext.patches.v5_0.execute_on_doctype_update
|
||||
erpnext.patches.v4_2.fix_recurring_orders
|
||||
erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices
|
||||
erpnext.patches.v5_0.project_costing
|
||||
erpnext.patches.v5_0.update_temporary_account
|
||||
erpnext.patches.v5_0.update_advance_paid
|
||||
erpnext.patches.v5_0.link_warehouse_with_account
|
||||
execute:frappe.delete_doc("Page", "stock-ledger")
|
||||
execute:frappe.delete_doc("Page","stock-level")
|
||||
erpnext.patches.v5_0.reclculate_planned_operating_cost_in_production_order
|
||||
erpnext.patches.v5_0.repost_requested_qty
|
||||
erpnext.patches.v5_0.fix_taxes_and_totals_in_party_currency
|
||||
erpnext.patches.v5_0.update_tax_amount_after_discount_in_purchase_cycle
|
||||
erpnext.patches.v5_0.rename_pos_setting
|
||||
erpnext.patches.v5_0.update_operation_description
|
||||
erpnext.patches.v5_0.set_footer_address
|
||||
execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
|
||||
execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
|
||||
erpnext.patches.v5_0.update_item_and_description_again
|
||||
erpnext.patches.v6_0.multi_currency
|
||||
erpnext.patches.v7_0.create_budget_record
|
||||
erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
|
||||
erpnext.patches.v5_0.portal_fixes
|
||||
erpnext.patches.v5_0.reset_values_in_tools # 02-05-2016
|
||||
execute:frappe.delete_doc("Page", "users")
|
||||
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
|
||||
erpnext.patches.v5_0.index_on_account_and_gl_entry
|
||||
execute:frappe.db.sql("""delete from `tabProject Task`""")
|
||||
erpnext.patches.v5_0.update_item_desc_in_invoice
|
||||
erpnext.patches.v5_1.fix_against_account
|
||||
execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
|
||||
erpnext.patches.v5_1.rename_roles
|
||||
erpnext.patches.v5_1.default_bom
|
||||
execute:frappe.delete_doc("DocType", "Party Type")
|
||||
execute:frappe.delete_doc("Module Def", "Contacts")
|
||||
erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015
|
||||
execute:frappe.reload_doctype("Leave Type")
|
||||
execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0")
|
||||
erpnext.patches.v5_4.set_root_and_report_type
|
||||
erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation
|
||||
erpnext.patches.v5_4.fix_invoice_outstanding
|
||||
execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' where voucher_type = 'Stock Reconciliation' and ifnull(qty_after_transaction, 0) = 0")
|
||||
erpnext.patches.v5_4.fix_missing_item_images
|
||||
erpnext.patches.v5_4.stock_entry_additional_costs
|
||||
erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14
|
||||
erpnext.patches.v5_7.update_item_description_based_on_item_master
|
||||
erpnext.patches.v5_7.item_template_attributes
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Manage Variants")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item")
|
||||
erpnext.patches.v4_2.repost_reserved_qty #2021-03-31
|
||||
erpnext.patches.v5_4.update_purchase_cost_against_project
|
||||
erpnext.patches.v5_8.update_order_reference_in_return_entries
|
||||
erpnext.patches.v5_8.add_credit_note_print_heading
|
||||
execute:frappe.delete_doc_if_exists("Print Format", "Credit Note - Negative Invoice")
|
||||
|
||||
# V6.0
|
||||
erpnext.patches.v6_0.set_default_title # 2015-09-03
|
||||
erpnext.patches.v6_0.default_activity_rate
|
||||
execute:frappe.db.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
|
||||
execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""")
|
||||
erpnext.patches.v6_0.fix_outstanding_amount
|
||||
erpnext.patches.v6_0.fix_planned_qty
|
||||
erpnext.patches.v6_2.remove_newsletter_duplicates
|
||||
erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
|
||||
erpnext.patches.v6_3.convert_applicable_territory
|
||||
erpnext.patches.v6_4.round_status_updater_percentages
|
||||
erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
|
||||
erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
|
||||
erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
|
||||
erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
|
||||
erpnext.patches.v6_4.fix_duplicate_bins
|
||||
erpnext.patches.v6_4.fix_sales_order_maintenance_status
|
||||
erpnext.patches.v6_4.email_digest_update
|
||||
|
||||
# delete shopping cart doctypes
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Applicable Territory")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Price List")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Taxes and Charges Master")
|
||||
|
||||
erpnext.patches.v6_4.set_user_in_contact
|
||||
erpnext.patches.v6_4.make_image_thumbnail #2015-10-20
|
||||
erpnext.patches.v6_5.show_in_website_for_template_item
|
||||
erpnext.patches.v6_4.fix_expense_included_in_valuation
|
||||
execute:frappe.delete_doc_if_exists("Report", "Item-wise Last Purchase Rate")
|
||||
erpnext.patches.v6_6.fix_website_image
|
||||
erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility")
|
||||
erpnext.patches.v6_8.make_webform_standard #2015-11-23
|
||||
erpnext.patches.v6_8.move_drop_ship_to_po_items
|
||||
erpnext.patches.v6_10.fix_ordered_received_billed
|
||||
erpnext.patches.v6_10.fix_jv_total_amount #2015-11-30
|
||||
erpnext.patches.v6_10.email_digest_default_quote
|
||||
erpnext.patches.v6_10.fix_billed_amount_in_drop_ship_po
|
||||
erpnext.patches.v6_10.fix_delivery_status_of_drop_ship_item #2015-12-08
|
||||
erpnext.patches.v5_8.tax_rule #2015-12-08
|
||||
erpnext.patches.v6_12.set_overdue_tasks
|
||||
erpnext.patches.v6_16.update_billing_status_in_dn_and_pr
|
||||
erpnext.patches.v6_16.create_manufacturer_records
|
||||
execute:frappe.db.sql("update `tabPricing Rule` set title=name where title='' or title is null") #2016-01-27
|
||||
erpnext.patches.v6_20.set_party_account_currency_in_orders
|
||||
erpnext.patches.v6_19.comment_feed_communication
|
||||
erpnext.patches.v6_21.fix_reorder_level
|
||||
erpnext.patches.v6_21.rename_material_request_fields
|
||||
erpnext.patches.v6_23.update_stopped_status_to_closed
|
||||
erpnext.patches.v6_24.set_recurring_id
|
||||
erpnext.patches.v6_20x.set_compact_print
|
||||
execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
|
||||
erpnext.patches.v6_20x.remove_fiscal_year_from_holiday_list
|
||||
erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po
|
||||
erpnext.patches.v6_27.fix_recurring_order_status
|
||||
erpnext.patches.v6_20x.update_product_bundle_description
|
||||
erpnext.patches.v7_0.update_party_status #2016-09-22
|
||||
erpnext.patches.v7_0.remove_features_setup
|
||||
erpnext.patches.v7_0.update_home_page
|
||||
execute:frappe.delete_doc_if_exists("Page", "financial-analytics")
|
||||
erpnext.patches.v7_0.update_project_in_gl_entry
|
||||
execute:frappe.db.sql('update tabQuotation set status="Cancelled" where docstatus=2')
|
||||
execute:frappe.rename_doc("DocType", "Payments", "Sales Invoice Payment", force=True)
|
||||
erpnext.patches.v7_0.update_mins_to_first_response
|
||||
erpnext.patches.v6_20x.repost_valuation_rate_for_negative_inventory
|
||||
erpnext.patches.v7_0.migrate_mode_of_payments_v6_to_v7
|
||||
erpnext.patches.v7_0.system_settings_setup_complete
|
||||
erpnext.patches.v7_0.set_naming_series_for_timesheet #2016-07-27
|
||||
execute:frappe.reload_doc('projects', 'doctype', 'project')
|
||||
execute:frappe.reload_doc('projects', 'doctype', 'project_user')
|
||||
erpnext.patches.v7_0.convert_timelogbatch_to_timesheet
|
||||
erpnext.patches.v7_0.convert_timelog_to_timesheet
|
||||
erpnext.patches.v7_0.move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet
|
||||
erpnext.patches.v7_0.remove_doctypes_and_reports #2016-10-29
|
||||
erpnext.patches.v7_0.update_maintenance_module_in_doctype
|
||||
erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
|
||||
erpnext.patches.v7_0.rename_advance_table_fields
|
||||
erpnext.patches.v7_0.rename_salary_components
|
||||
erpnext.patches.v7_0.rename_prevdoc_fields
|
||||
erpnext.patches.v7_0.rename_time_sheet_doctype
|
||||
execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long Time")
|
||||
erpnext.patches.v7_0.make_is_group_fieldtype_as_check
|
||||
execute:frappe.reload_doc('projects', 'doctype', 'timesheet') #2016-09-12
|
||||
erpnext.patches.v7_1.rename_field_timesheet
|
||||
execute:frappe.delete_doc_if_exists("Report", "Employee Holiday Attendance")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Payment Tool")
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Payment Tool Detail")
|
||||
erpnext.patches.v7_0.setup_account_table_for_expense_claim_type_if_exists
|
||||
erpnext.patches.v7_0.migrate_schools_to_erpnext
|
||||
erpnext.patches.v7_1.update_lead_source
|
||||
erpnext.patches.v6_20x.remove_customer_supplier_roles
|
||||
erpnext.patches.v7_0.remove_administrator_role_in_doctypes
|
||||
erpnext.patches.v7_0.rename_fee_amount_to_fee_component
|
||||
erpnext.patches.v7_0.calculate_total_costing_amount
|
||||
erpnext.patches.v7_0.fix_nonwarehouse_ledger_gl_entries_for_transactions
|
||||
erpnext.patches.v7_0.remove_old_earning_deduction_doctypes
|
||||
erpnext.patches.v7_0.make_guardian
|
||||
erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
|
||||
erpnext.patches.v7_0.set_material_request_type_in_item
|
||||
erpnext.patches.v7_0.rename_examination_to_assessment
|
||||
erpnext.patches.v7_0.set_portal_settings
|
||||
erpnext.patches.v7_0.update_change_amount_account
|
||||
erpnext.patches.v7_0.fix_duplicate_icons
|
||||
erpnext.patches.v7_0.repost_gle_for_pos_sales_return
|
||||
erpnext.patches.v7_1.update_total_billing_hours
|
||||
erpnext.patches.v7_1.update_component_type
|
||||
erpnext.patches.v7_0.repost_gle_for_pos_sales_return
|
||||
erpnext.patches.v7_0.update_missing_employee_in_timesheet
|
||||
erpnext.patches.v7_0.update_status_for_timesheet
|
||||
erpnext.patches.v7_0.set_party_name_in_payment_entry
|
||||
erpnext.patches.v7_1.set_student_guardian
|
||||
erpnext.patches.v7_0.update_conversion_factor_in_supplier_quotation_item
|
||||
erpnext.patches.v7_1.move_sales_invoice_from_parent_to_child_timesheet
|
||||
execute:frappe.db.sql("update `tabTimesheet` ts, `tabEmployee` emp set ts.employee_name = emp.employee_name where emp.name = ts.employee and ts.employee_name is null and ts.employee is not null")
|
||||
erpnext.patches.v7_1.fix_link_for_customer_from_lead
|
||||
execute:frappe.db.sql("delete from `tabTimesheet Detail` where NOT EXISTS (select name from `tabTimesheet` where name = `tabTimesheet Detail`.parent)")
|
||||
erpnext.patches.v7_0.update_mode_of_payment_type
|
||||
|
||||
execute:frappe.reload_doctype('Employee') #2016-10-18
|
||||
execute:frappe.db.sql("update `tabEmployee` set prefered_contact_email = IFNULL(prefered_contact_email,'') ")
|
||||
execute:frappe.reload_doc("Payroll", "doctype", "salary_slip")
|
||||
execute:frappe.db.sql("update `tabSalary Slip` set posting_date=creation")
|
||||
execute:frappe.reload_doc("stock", "doctype", "stock_settings")
|
||||
erpnext.patches.v8_0.create_domain_docs #16-05-2017
|
||||
erpnext.patches.v7_1.update_portal_roles
|
||||
erpnext.patches.v7_1.set_total_amount_currency_in_je
|
||||
finally:erpnext.patches.v7_0.update_timesheet_communications
|
||||
erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
|
||||
erpnext.patches.v7_1.add_field_for_task_dependent
|
||||
erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
|
||||
erpnext.patches.v7_1.set_prefered_contact_email
|
||||
execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings')
|
||||
execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0)
|
||||
execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')")
|
||||
erpnext.patches.v7_1.save_stock_settings
|
||||
erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01
|
||||
erpnext.patches.v7_1.add_account_user_role_for_timesheet
|
||||
erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table
|
||||
erpnext.patches.v7_1.update_invoice_status
|
||||
erpnext.patches.v7_0.po_status_issue_for_pr_return
|
||||
erpnext.patches.v7_1.update_missing_salary_component_type
|
||||
erpnext.patches.v7_1.rename_quality_inspection_field
|
||||
erpnext.patches.v7_0.update_autoname_field
|
||||
erpnext.patches.v7_1.update_bom_base_currency
|
||||
erpnext.patches.v7_0.update_status_of_po_so
|
||||
erpnext.patches.v7_1.set_budget_against_as_cost_center
|
||||
erpnext.patches.v7_1.set_currency_exchange_date
|
||||
erpnext.patches.v7_1.set_sales_person_status
|
||||
erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items
|
||||
erpnext.patches.v7_2.update_website_for_variant
|
||||
erpnext.patches.v7_2.update_assessment_modules
|
||||
erpnext.patches.v7_2.update_doctype_status
|
||||
erpnext.patches.v7_2.update_salary_slips
|
||||
erpnext.patches.v7_2.delete_fleet_management_module_def
|
||||
erpnext.patches.v7_2.contact_address_links
|
||||
erpnext.patches.v7_2.mark_students_active
|
||||
erpnext.patches.v7_2.set_null_value_to_fields
|
||||
erpnext.patches.v7_2.update_guardian_name_in_student_master
|
||||
erpnext.patches.v7_2.update_abbr_in_salary_slips
|
||||
erpnext.patches.v7_2.rename_evaluation_criteria
|
||||
erpnext.patches.v7_2.update_party_type
|
||||
erpnext.patches.v7_2.setup_auto_close_settings
|
||||
erpnext.patches.v7_2.empty_supplied_items_for_non_subcontracted
|
||||
erpnext.patches.v7_2.arrear_leave_encashment_as_salary_component
|
||||
erpnext.patches.v7_2.rename_att_date_attendance
|
||||
erpnext.patches.v7_2.update_attendance_docstatus
|
||||
erpnext.patches.v7_2.make_all_assessment_group
|
||||
erpnext.patches.v8_0.repost_reserved_qty_for_multiple_sales_uom
|
||||
erpnext.patches.v8_0.addresses_linked_to_lead
|
||||
execute:frappe.delete_doc('DocType', 'Purchase Common')
|
||||
erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice
|
||||
erpnext.patches.v8_0.update_supplier_address_in_stock_entry
|
||||
erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate
|
||||
erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices
|
||||
erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically
|
||||
erpnext.patches.v8_0.set_project_copied_from
|
||||
erpnext.patches.v8_0.update_status_as_paid_for_completed_expense_claim
|
||||
erpnext.patches.v7_2.stock_uom_in_selling
|
||||
erpnext.patches.v8_0.revert_manufacturers_table_from_item
|
||||
erpnext.patches.v8_0.disable_instructor_role
|
||||
erpnext.patches.v8_0.merge_student_batch_and_student_group
|
||||
erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
|
||||
erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
|
||||
erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
|
||||
erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
|
||||
erpnext.patches.v8_0.delete_schools_depricated_doctypes
|
||||
erpnext.patches.v8_0.update_customer_pos_id
|
||||
erpnext.patches.v8_0.rename_items_in_status_field_of_material_request
|
||||
erpnext.patches.v8_0.delete_bin_indexes
|
||||
erpnext.patches.v8_0.move_account_head_from_account_to_warehouse_for_inventory
|
||||
erpnext.patches.v8_0.change_in_words_varchar_length
|
||||
erpnext.patches.v8_0.update_stock_qty_value_in_bom_item
|
||||
erpnext.patches.v8_0.update_sales_cost_in_project
|
||||
erpnext.patches.v8_0.save_system_settings
|
||||
erpnext.patches.v8_1.delete_deprecated_reports
|
||||
erpnext.patches.v9_0.remove_subscription_module
|
||||
erpnext.patches.v8_7.make_subscription_from_recurring_data
|
||||
erpnext.patches.v8_1.setup_gst_india #2017-06-27
|
||||
execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
|
||||
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account #16-08-2018
|
||||
erpnext.patches.v8_1.gst_fixes #2017-07-06
|
||||
erpnext.patches.v8_0.update_production_orders
|
||||
erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no
|
||||
erpnext.patches.v8_1.allow_invoice_copy_to_edit_after_submit
|
||||
erpnext.patches.v8_1.add_hsn_sac_codes
|
||||
erpnext.patches.v8_1.update_gst_state #17-07-2017
|
||||
erpnext.patches.v8_1.removed_report_support_hours
|
||||
erpnext.patches.v8_1.add_indexes_in_transaction_doctypes
|
||||
erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
|
||||
erpnext.patches.v8_1.update_expense_claim_status
|
||||
erpnext.patches.v8_3.update_company_total_sales #2017-08-16
|
||||
erpnext.patches.v8_4.make_scorecard_records
|
||||
erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28
|
||||
erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
|
||||
erpnext.patches.v8_5.remove_quotations_route_in_sidebar
|
||||
erpnext.patches.v8_5.update_existing_data_in_project_type
|
||||
erpnext.patches.v8_5.set_default_mode_of_payment
|
||||
erpnext.patches.v8_5.update_customer_group_in_POS_profile
|
||||
erpnext.patches.v8_6.update_timesheet_company_from_PO
|
||||
erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager
|
||||
erpnext.patches.v8_5.remove_project_type_property_setter
|
||||
erpnext.patches.v8_7.sync_india_custom_fields
|
||||
erpnext.patches.v8_7.fix_purchase_receipt_status
|
||||
erpnext.patches.v8_6.rename_bom_update_tool
|
||||
erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2017 #15-12-2017
|
||||
erpnext.patches.v8_9.rename_company_sales_target_field
|
||||
erpnext.patches.v8_8.set_bom_rate_as_per_uom
|
||||
erpnext.patches.v8_8.add_new_fields_in_accounts_settings
|
||||
erpnext.patches.v8_9.set_default_customer_group
|
||||
erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
|
||||
erpnext.patches.v8_9.set_default_fields_in_variant_settings
|
||||
erpnext.patches.v8_9.update_billing_gstin_for_indian_account
|
||||
erpnext.patches.v8_9.set_member_party_type
|
||||
erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
|
||||
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
||||
erpnext.patches.v9_0.student_admission_childtable_migrate
|
||||
erpnext.patches.v9_0.add_healthcare_domain
|
||||
erpnext.patches.v9_0.set_variant_item_description
|
||||
erpnext.patches.v9_0.set_uoms_in_variant_field
|
||||
erpnext.patches.v9_0.copy_old_fees_field_data
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
||||
erpnext.patches.v9_0.set_pos_profile_name
|
||||
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
|
||||
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
||||
erpnext.patches.v8_10.change_default_customer_credit_days
|
||||
erpnext.patches.v9_0.update_employee_loan_details
|
||||
erpnext.patches.v9_2.delete_healthcare_domain_default_items
|
||||
erpnext.patches.v9_1.create_issue_opportunity_type
|
||||
erpnext.patches.v9_2.rename_translated_domains_in_en
|
||||
erpnext.patches.v9_0.set_shipping_type_for_existing_shipping_rules
|
||||
erpnext.patches.v9_0.update_multi_uom_fields_in_material_request
|
||||
erpnext.patches.v9_2.repost_reserved_qty_for_production
|
||||
erpnext.patches.v9_2.remove_company_from_patient
|
||||
erpnext.patches.v9_2.set_item_name_in_production_order
|
||||
erpnext.patches.v10_0.update_lft_rgt_for_employee
|
||||
erpnext.patches.v9_2.rename_net_weight_in_item_master
|
||||
erpnext.patches.v9_2.delete_process_payroll
|
||||
erpnext.patches.v10_0.add_agriculture_domain
|
||||
erpnext.patches.v10_0.add_non_profit_domain
|
||||
erpnext.patches.v10_0.setup_vat_for_uae_and_saudi_arabia #2017-12-28
|
||||
erpnext.patches.v10_0.set_primary_contact_for_customer
|
||||
erpnext.patches.v10_0.copy_projects_renamed_fields
|
||||
erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
|
||||
erpnext.patches.v10_0.update_asset_calculate_depreciation
|
||||
erpnext.patches.v10_0.add_guardian_role_for_parent_portal
|
||||
erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank
|
||||
erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
|
||||
erpnext.patches.v10_0.fichier_des_ecritures_comptables_for_france
|
||||
erpnext.patches.v10_0.update_assessment_plan
|
||||
erpnext.patches.v10_0.update_assessment_result
|
||||
erpnext.patches.v10_0.set_default_payment_terms_based_on_company
|
||||
erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
|
||||
erpnext.patches.v10_0.rename_price_to_rate_in_pricing_rule
|
||||
erpnext.patches.v10_0.set_currency_in_pricing_rule
|
||||
erpnext.patches.v10_0.set_b2c_limit
|
||||
erpnext.patches.v10_0.update_translatable_fields
|
||||
erpnext.patches.v10_0.rename_offer_letter_to_job_offer
|
||||
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
|
||||
@ -496,16 +21,6 @@ erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_
|
||||
erpnext.patches.v10_0.add_default_cash_flow_mappers
|
||||
erpnext.patches.v11_0.rename_duplicate_item_code_values
|
||||
erpnext.patches.v11_0.make_quality_inspection_template
|
||||
erpnext.patches.v10_0.update_status_for_multiple_source_in_po
|
||||
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
|
||||
erpnext.patches.v10_0.update_territory_and_customer_group
|
||||
erpnext.patches.v10_0.update_warehouse_address_details
|
||||
erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
|
||||
erpnext.patches.v10_0.update_hub_connector_domain
|
||||
erpnext.patches.v10_0.set_student_party_type
|
||||
erpnext.patches.v10_0.update_project_in_sle
|
||||
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
|
||||
erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items
|
||||
erpnext.patches.v11_0.merge_land_unit_with_location
|
||||
erpnext.patches.v11_0.add_index_on_nestedset_doctypes
|
||||
erpnext.patches.v11_0.remove_modules_setup_page
|
||||
@ -514,7 +29,6 @@ erpnext.patches.v11_0.update_department_lft_rgt
|
||||
erpnext.patches.v11_0.add_default_email_template_for_leave
|
||||
erpnext.patches.v11_0.set_default_email_template_in_hr #08-06-2018
|
||||
erpnext.patches.v11_0.uom_conversion_data #30-06-2018
|
||||
erpnext.patches.v10_0.taxes_issue_with_pos
|
||||
erpnext.patches.v11_0.update_account_type_in_party_type
|
||||
erpnext.patches.v11_0.rename_healthcare_doctype_and_fields
|
||||
erpnext.patches.v11_0.rename_supplier_type_to_supplier_group
|
||||
@ -522,8 +36,6 @@ erpnext.patches.v10_1.transfer_subscription_to_auto_repeat
|
||||
erpnext.patches.v11_0.update_brand_in_item_price
|
||||
erpnext.patches.v11_0.create_default_success_action
|
||||
erpnext.patches.v11_0.add_healthcare_service_unit_tree_root
|
||||
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
|
||||
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
|
||||
erpnext.patches.v11_0.rename_field_max_days_allowed
|
||||
erpnext.patches.v11_0.create_salary_structure_assignments
|
||||
erpnext.patches.v11_0.rename_health_insurance
|
||||
@ -536,7 +48,6 @@ erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-
|
||||
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
|
||||
erpnext.patches.v11_0.rename_overproduction_percent_field
|
||||
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
|
||||
erpnext.patches.v10_0.update_status_in_purchase_receipt
|
||||
erpnext.patches.v11_0.inter_state_field_for_gst
|
||||
erpnext.patches.v11_0.rename_members_with_naming_series #04-06-2018
|
||||
erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state
|
||||
@ -550,13 +61,10 @@ erpnext.patches.v11_0.skip_user_permission_check_for_department
|
||||
erpnext.patches.v11_0.set_department_for_doctypes
|
||||
erpnext.patches.v11_0.update_allow_transfer_for_manufacture
|
||||
erpnext.patches.v11_0.add_item_group_defaults
|
||||
erpnext.patches.v10_0.update_address_template_for_india
|
||||
erpnext.patches.v11_0.add_expense_claim_default_account
|
||||
execute:frappe.delete_doc("Page", "hub")
|
||||
erpnext.patches.v11_0.reset_publish_in_hub_for_all_items
|
||||
erpnext.patches.v11_0.update_hub_url # 2018-08-31 # 2018-09-03
|
||||
erpnext.patches.v10_0.set_discount_amount
|
||||
erpnext.patches.v10_0.recalculate_gross_margin_for_project
|
||||
erpnext.patches.v11_0.make_job_card
|
||||
erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
|
||||
erpnext.patches.v10_0.delete_hub_documents # 12-08-2018
|
||||
@ -570,9 +78,6 @@ execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
|
||||
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 #2019-04-26 #2019-05-03
|
||||
erpnext.patches.v11_0.drop_column_max_days_allowed
|
||||
erpnext.patches.v10_0.update_user_image_in_employee
|
||||
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
|
||||
erpnext.patches.v10_0.allow_operators_in_supplier_scorecard
|
||||
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
|
||||
erpnext.patches.v11_0.update_delivery_trip_status
|
||||
erpnext.patches.v11_0.set_missing_gst_hsn_code
|
||||
@ -779,5 +284,7 @@ erpnext.patches.v12_0.add_ewaybill_validity_field
|
||||
erpnext.patches.v13_0.germany_make_custom_fields
|
||||
erpnext.patches.v13_0.germany_fill_debtor_creditor_number
|
||||
erpnext.patches.v13_0.set_pos_closing_as_failed
|
||||
execute:frappe.rename_doc("Workspace", "Loan Management", "Loans", force=True)
|
||||
erpnext.patches.v13_0.update_timesheet_changes
|
||||
erpnext.patches.v13_0.set_training_event_attendance
|
||||
erpnext.patches.v13_0.rename_issue_status_hold_to_on_hold
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
from erpnext.stock.stock_balance import set_stock_balance_as_per_serial_no
|
||||
frappe.db.auto_commit_on_many_writes = 1
|
||||
|
||||
set_stock_balance_as_per_serial_no()
|
||||
|
||||
frappe.db.auto_commit_on_many_writes = 0
|
@ -1,13 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
domain = 'Agriculture'
|
||||
if not frappe.db.exists('Domain', domain):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Domain',
|
||||
'domain': domain
|
||||
}).insert(ignore_permissions=True)
|
@ -1,23 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
# create guardian role
|
||||
if not frappe.get_value('Role', dict(role_name='Guardian')):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Role',
|
||||
'role_name': 'Guardian',
|
||||
'desk_access': 0,
|
||||
'restrict_to_domain': 'Education'
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
# set guardian roles in already created users
|
||||
if frappe.db.exists("Doctype", "Guardian"):
|
||||
for user in frappe.db.sql_list("""select u.name from `tabUser` u , `tabGuardian` g where g.email_address = u.name"""):
|
||||
user = frappe.get_doc('User', user)
|
||||
user.flags.ignore_validate = True
|
||||
user.flags.ignore_mandatory = True
|
||||
user.save()
|
@ -1,20 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
domain = 'Non Profit'
|
||||
if not frappe.db.exists('Domain', domain):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Domain',
|
||||
'domain': domain
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
frappe.get_doc({
|
||||
'doctype': 'Role',
|
||||
'role_name': 'Non Profit Portal User',
|
||||
'desk_access': 0,
|
||||
'restrict_to_domain': domain
|
||||
}).insert(ignore_permissions=True)
|
@ -1,23 +0,0 @@
|
||||
# Copyright (c) 2019, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_criteria')
|
||||
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_scoring_criteria')
|
||||
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard')
|
||||
|
||||
for criteria in frappe.get_all('Supplier Scorecard Criteria', fields=['name', 'formula'], limit_page_length=None):
|
||||
frappe.db.set_value('Supplier Scorecard Criteria', criteria.name,
|
||||
'formula', criteria.formula.replace('<','<').replace('>','>'))
|
||||
|
||||
for criteria in frappe.get_all('Supplier Scorecard Scoring Criteria', fields=['name', 'formula'], limit_page_length=None):
|
||||
if criteria.formula: # not mandatory
|
||||
frappe.db.set_value('Supplier Scorecard Scoring Criteria', criteria.name,
|
||||
'formula', criteria.formula.replace('<','<').replace('>','>'))
|
||||
|
||||
for sc in frappe.get_all('Supplier Scorecard', fields=['name', 'weighting_function'], limit_page_length=None):
|
||||
frappe.db.set_value('Supplier Scorecard', sc.name, 'weighting_function',
|
||||
sc.weighting_function.replace('<','<').replace('>','>'))
|
@ -1,13 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
|
||||
def execute():
|
||||
""" copy data from old fields to new """
|
||||
frappe.reload_doc("projects", "doctype", "project")
|
||||
|
||||
if frappe.db.has_column('Project', 'total_sales_cost'):
|
||||
rename_field('Project', "total_sales_cost", "total_sales_amount")
|
||||
|
||||
if frappe.db.has_column('Project', 'total_billing_amount'):
|
||||
rename_field('Project', "total_billing_amount", "total_billable_amount")
|
@ -1,22 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
print_format_mapper = {
|
||||
'India': ['GST POS Invoice', 'GST Tax Invoice'],
|
||||
'Saudi Arabia': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice'],
|
||||
'United Arab Emirates': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice']
|
||||
}
|
||||
|
||||
frappe.db.sql(""" update `tabPrint Format` set disabled = 1 where name
|
||||
in ('GST POS Invoice', 'GST Tax Invoice', 'Simplified Tax Invoice', 'Detailed Tax Invoice')""")
|
||||
|
||||
for d in frappe.get_all('Company', fields = ["country"],
|
||||
filters={'country': ('in', ['India', 'Saudi Arabia', 'United Arab Emirates'])}):
|
||||
if print_format_mapper.get(d.country):
|
||||
print_formats = print_format_mapper.get(d.country)
|
||||
frappe.db.sql(""" update `tabPrint Format` set disabled = 0
|
||||
where name in (%s)""" % ", ".join(["%s"]*len(print_formats)), tuple(print_formats))
|
@ -1,31 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "bin")
|
||||
frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
|
||||
for d in frappe.db.sql("""
|
||||
select distinct rm_item_code, reserve_warehouse
|
||||
from `tabPurchase Order Item Supplied`
|
||||
where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""):
|
||||
|
||||
try:
|
||||
bin_doc = get_bin(d[0], d[1])
|
||||
bin_doc.update_reserved_qty_for_sub_contracting()
|
||||
except:
|
||||
pass
|
||||
|
||||
for d in frappe.db.sql("""select distinct item_code, source_warehouse
|
||||
from `tabWork Order Item`
|
||||
where docstatus=1 and transferred_qty > required_qty
|
||||
and source_warehouse is not null and source_warehouse != ''""", as_list=1):
|
||||
|
||||
try:
|
||||
bin_doc = get_bin(d[0], d[1])
|
||||
bin_doc.update_reserved_qty_for_production()
|
||||
except:
|
||||
pass
|
@ -1,14 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('projects', 'doctype', 'project')
|
||||
for d in frappe.db.sql(""" select name from `tabProject` where
|
||||
ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1):
|
||||
doc = frappe.get_doc("Project", d.name)
|
||||
doc.calculate_gross_margin()
|
||||
doc.db_set('gross_margin', doc.gross_margin)
|
||||
doc.db_set('per_gross_margin', doc.per_gross_margin)
|
@ -1,32 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
# rename the School module as Education
|
||||
|
||||
# rename the school module
|
||||
if frappe.db.exists('Module Def', 'Schools') and not frappe.db.exists('Module Def', 'Education'):
|
||||
frappe.rename_doc("Module Def", "Schools", "Education")
|
||||
|
||||
# delete the school module
|
||||
if frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Education'):
|
||||
frappe.db.sql("""delete from `tabModule Def` where module_name = 'Schools'""")
|
||||
|
||||
|
||||
# rename "School Settings" to the "Education Settings
|
||||
if frappe.db.exists('DocType', 'School Settings'):
|
||||
frappe.rename_doc("DocType", "School Settings", "Education Settings", force=True)
|
||||
frappe.reload_doc("education", "doctype", "education_settings")
|
||||
|
||||
# delete the discussion web form if exists
|
||||
if frappe.db.exists('Web Form', 'Discussion'):
|
||||
frappe.db.sql("""delete from `tabWeb Form` where name = 'discussion'""")
|
||||
|
||||
# rename the select option field from "School Bus" to "Institute's Bus"
|
||||
frappe.reload_doc("education", "doctype", "Program Enrollment")
|
||||
if "mode_of_transportation" in frappe.db.get_table_columns("Program Enrollment"):
|
||||
frappe.db.sql("""update `tabProgram Enrollment` set mode_of_transportation = "Institute's Bus"
|
||||
where mode_of_transportation = "School Bus" """)
|
@ -1,32 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
|
||||
def execute():
|
||||
for company in frappe.get_all("Company"):
|
||||
if not erpnext.is_perpetual_inventory_enabled(company.name):
|
||||
continue
|
||||
|
||||
acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
|
||||
pr_with_rejected_warehouse = frappe.db.sql("""
|
||||
select pr.name
|
||||
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
|
||||
where pr.name = pr_item.parent
|
||||
and pr.posting_date > %s
|
||||
and pr.docstatus=1
|
||||
and pr.company = %s
|
||||
and pr_item.rejected_qty > 0
|
||||
""", (acc_frozen_upto, company.name), as_dict=1)
|
||||
|
||||
for d in pr_with_rejected_warehouse:
|
||||
doc = frappe.get_doc("Purchase Receipt", d.name)
|
||||
|
||||
doc.docstatus = 2
|
||||
doc.make_gl_entries_on_cancel()
|
||||
|
||||
|
||||
# update gl entries for submit state of PR
|
||||
doc.docstatus = 1
|
||||
doc.make_gl_entries()
|
@ -1,21 +0,0 @@
|
||||
# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# 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
|
||||
|
||||
count=0
|
||||
for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
|
||||
from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""):
|
||||
try:
|
||||
count += 1
|
||||
update_bin_qty(item_code, warehouse, {
|
||||
"indented_qty": get_indented_qty(item_code, warehouse),
|
||||
})
|
||||
if count % 200 == 0:
|
||||
frappe.db.commit()
|
||||
except:
|
||||
frappe.db.rollback()
|
@ -1,56 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
serialised_items = [d.name for d in frappe.get_all("Item", filters={"has_serial_no": 1})]
|
||||
|
||||
if not serialised_items:
|
||||
return
|
||||
|
||||
for dt in ["Stock Entry Detail", "Purchase Receipt Item", "Purchase Invoice Item"]:
|
||||
cond = ""
|
||||
if dt=="Purchase Invoice Item":
|
||||
cond = """ and parent in (select name from `tabPurchase Invoice`
|
||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.parent and update_stock=1)"""
|
||||
|
||||
item_rows = frappe.db.sql("""
|
||||
select name
|
||||
from `tab{0}`
|
||||
where conversion_factor != 1
|
||||
and docstatus = 1
|
||||
and ifnull(serial_no, '') = ''
|
||||
and item_code in ({1})
|
||||
{2}
|
||||
""".format(dt, ', '.join(['%s']*len(serialised_items)), cond), tuple(serialised_items))
|
||||
|
||||
if item_rows:
|
||||
sle_serial_nos = dict(frappe.db.sql("""
|
||||
select voucher_detail_no, serial_no
|
||||
from `tabStock Ledger Entry`
|
||||
where ifnull(serial_no, '') != ''
|
||||
and voucher_detail_no in (%s)
|
||||
""".format(', '.join(['%s']*len(item_rows))),
|
||||
tuple([d[0] for d in item_rows])))
|
||||
|
||||
batch_size = 100
|
||||
for i in range(0, len(item_rows), batch_size):
|
||||
batch_item_rows = item_rows[i:i + batch_size]
|
||||
when_then = []
|
||||
for item_row in batch_item_rows:
|
||||
|
||||
when_then.append('WHEN `name` = "{row_name}" THEN "{value}"'.format(
|
||||
row_name=item_row[0],
|
||||
value=sle_serial_nos.get(item_row[0])))
|
||||
|
||||
frappe.db.sql("""
|
||||
update
|
||||
`tab{doctype}`
|
||||
set
|
||||
serial_no = CASE {when_then_cond} ELSE `serial_no` END
|
||||
""".format(
|
||||
doctype = dt,
|
||||
when_then_cond=" ".join(when_then)
|
||||
))
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user