Merge branch 'develop' of https://github.com/frappe/erpnext into currency-exchange-settings
This commit is contained in:
commit
3fdd47e71f
27
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
27
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -24,20 +24,6 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: Affected versions.
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- v12
|
|
||||||
- v13
|
|
||||||
- v14
|
|
||||||
- develop
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: module
|
id: module
|
||||||
attributes:
|
attributes:
|
||||||
@ -86,7 +72,7 @@ body:
|
|||||||
- manual install
|
- manual install
|
||||||
- FrappeCloud
|
- FrappeCloud
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: false
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: logs
|
id: logs
|
||||||
@ -95,12 +81,7 @@ body:
|
|||||||
description: Please copy and paste any relevant log output. This will be automatically formatted.
|
description: Please copy and paste any relevant log output. This will be automatically formatted.
|
||||||
render: shell
|
render: shell
|
||||||
|
|
||||||
|
- type: markdown
|
||||||
- type: checkboxes
|
|
||||||
id: terms
|
|
||||||
attributes:
|
attributes:
|
||||||
label: Code of Conduct
|
value: |
|
||||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/frappe/erpnext/blob/develop/CODE_OF_CONDUCT.md)
|
By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/frappe/erpnext/blob/develop/CODE_OF_CONDUCT.md)
|
||||||
options:
|
|
||||||
- label: I agree to follow this project's Code of Conduct
|
|
||||||
required: true
|
|
||||||
|
15
.github/helper/install.sh
vendored
15
.github/helper/install.sh
vendored
@ -12,8 +12,15 @@ git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB
|
|||||||
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
|
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
|
||||||
|
|
||||||
mkdir ~/frappe-bench/sites/test_site
|
mkdir ~/frappe-bench/sites/test_site
|
||||||
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/
|
|
||||||
|
|
||||||
|
if [ "$DB" == "mariadb" ];then
|
||||||
|
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config_mariadb.json" ~/frappe-bench/sites/test_site/site_config.json
|
||||||
|
else
|
||||||
|
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config_postgres.json" ~/frappe-bench/sites/test_site/site_config.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$DB" == "mariadb" ];then
|
||||||
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||||
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||||
|
|
||||||
@ -23,6 +30,12 @@ mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_fr
|
|||||||
|
|
||||||
mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
||||||
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
|
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DB" == "postgres" ];then
|
||||||
|
echo "travis" | psql -h 127.0.0.1 -p 5432 -c "CREATE DATABASE test_frappe" -U postgres;
|
||||||
|
echo "travis" | psql -h 127.0.0.1 -p 5432 -c "CREATE USER test_frappe WITH PASSWORD 'test_frappe'" -U postgres;
|
||||||
|
fi
|
||||||
|
|
||||||
wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||||
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||||
|
18
.github/helper/site_config_postgres.json
vendored
Normal file
18
.github/helper/site_config_postgres.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"db_host": "127.0.0.1",
|
||||||
|
"db_port": 5432,
|
||||||
|
"db_name": "test_frappe",
|
||||||
|
"db_password": "test_frappe",
|
||||||
|
"db_type": "postgres",
|
||||||
|
"allow_tests": true,
|
||||||
|
"auto_email_id": "test@example.com",
|
||||||
|
"mail_server": "smtp.example.com",
|
||||||
|
"mail_login": "test@example.com",
|
||||||
|
"mail_password": "test",
|
||||||
|
"admin_password": "admin",
|
||||||
|
"root_login": "postgres",
|
||||||
|
"root_password": "travis",
|
||||||
|
"host_name": "http://test_site:8000",
|
||||||
|
"install_apps": ["erpnext"],
|
||||||
|
"throttle_user_limit": 100
|
||||||
|
}
|
55
.github/labeler.yml
vendored
Normal file
55
.github/labeler.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
accounts:
|
||||||
|
- 'erpnext/accounts/*'
|
||||||
|
- 'erpnext/controllers/accounts_controller.py'
|
||||||
|
- 'erpnext/controllers/taxes_and_totals.py'
|
||||||
|
|
||||||
|
stock:
|
||||||
|
- 'erpnext/stock/*'
|
||||||
|
- 'erpnext/controllers/stock_controller.py'
|
||||||
|
- 'erpnext/controllers/item_variant.py'
|
||||||
|
|
||||||
|
assets:
|
||||||
|
- 'erpnext/assets/*'
|
||||||
|
|
||||||
|
regional:
|
||||||
|
- 'erpnext/regional/*'
|
||||||
|
|
||||||
|
selling:
|
||||||
|
- 'erpnext/selling/*'
|
||||||
|
- 'erpnext/controllers/selling_controller.py'
|
||||||
|
|
||||||
|
buying:
|
||||||
|
- 'erpnext/buying/*'
|
||||||
|
- 'erpnext/controllers/buying_controller.py'
|
||||||
|
|
||||||
|
support:
|
||||||
|
- 'erpnext/support/*'
|
||||||
|
|
||||||
|
POS:
|
||||||
|
- 'pos*'
|
||||||
|
|
||||||
|
ecommerce:
|
||||||
|
- 'erpnext/e_commerce/*'
|
||||||
|
|
||||||
|
maintenance:
|
||||||
|
- 'erpnext/maintenance/*'
|
||||||
|
|
||||||
|
manufacturing:
|
||||||
|
- 'erpnext/manufacturing/*'
|
||||||
|
|
||||||
|
crm:
|
||||||
|
- 'erpnext/crm/*'
|
||||||
|
|
||||||
|
HR:
|
||||||
|
- 'erpnext/hr/*'
|
||||||
|
|
||||||
|
payroll:
|
||||||
|
- 'erpnext/payroll*'
|
||||||
|
|
||||||
|
projects:
|
||||||
|
- 'erpnext/projects/*'
|
||||||
|
|
||||||
|
# Any python files modifed but no test files modified
|
||||||
|
needs-tests:
|
||||||
|
- any: ['erpnext/**/*.py']
|
||||||
|
all: ['!erpnext/**/test*.py']
|
12
.github/workflows/labeller.yml
vendored
Normal file
12
.github/workflows/labeller.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
name: "Pull Request Labeler"
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
triage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/labeler@v3
|
||||||
|
with:
|
||||||
|
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
3
.github/workflows/patch.yml
vendored
3
.github/workflows/patch.yml
vendored
@ -80,6 +80,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||||
|
env:
|
||||||
|
DB: mariadb
|
||||||
|
TYPE: server
|
||||||
|
|
||||||
- name: Run Patch Tests
|
- name: Run Patch Tests
|
||||||
run: |
|
run: |
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
name: Server
|
name: Server (Mariadb)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.js'
|
- '**.js'
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
- '**.html'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches: [ develop ]
|
branches: [ develop ]
|
||||||
@ -13,7 +14,7 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: server-develop-${{ github.event.number }}
|
group: server-mariadb-develop-${{ github.event.number }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -92,6 +93,7 @@ jobs:
|
|||||||
- name: Install
|
- name: Install
|
||||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||||
env:
|
env:
|
||||||
|
DB: mariadb
|
||||||
TYPE: server
|
TYPE: server
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
105
.github/workflows/server-tests-postgres.yml
vendored
Normal file
105
.github/workflows/server-tests-postgres.yml
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
name: Server (Postgres)
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.js'
|
||||||
|
- '**.md'
|
||||||
|
- '**.html'
|
||||||
|
types: [opened, labelled, synchronize, reopened]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: server-postgres-develop-${{ github.event.number }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
if: ${{ contains(github.event.pull_request.labels.*.name, 'postgres') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
container: [1, 2, 3]
|
||||||
|
|
||||||
|
name: Python Unit Tests
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:13.3
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: travis
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Clone
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.7
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- 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
|
||||||
|
env:
|
||||||
|
DB: postgres
|
||||||
|
TYPE: server
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator
|
||||||
|
env:
|
||||||
|
TYPE: server
|
||||||
|
CI_BUILD_ID: ${{ github.run_id }}
|
||||||
|
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
@ -23,13 +23,13 @@ erpnext/stock/ @marination @rohitwaghchaure @ankush
|
|||||||
|
|
||||||
erpnext/crm/ @ruchamahabal @pateljannat
|
erpnext/crm/ @ruchamahabal @pateljannat
|
||||||
erpnext/education/ @ruchamahabal @pateljannat
|
erpnext/education/ @ruchamahabal @pateljannat
|
||||||
erpnext/healthcare/ @ruchamahabal @pateljannat @chillaranand
|
|
||||||
erpnext/hr/ @ruchamahabal @pateljannat
|
erpnext/hr/ @ruchamahabal @pateljannat
|
||||||
erpnext/non_profit/ @ruchamahabal
|
|
||||||
erpnext/payroll @ruchamahabal @pateljannat
|
erpnext/payroll @ruchamahabal @pateljannat
|
||||||
erpnext/projects/ @ruchamahabal @pateljannat
|
erpnext/projects/ @ruchamahabal @pateljannat
|
||||||
|
|
||||||
erpnext/controllers @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination
|
erpnext/controllers/ @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination @ankush
|
||||||
|
erpnext/patches/ @deepeshgarg007 @nextchamp-saqib @marination @ankush
|
||||||
|
erpnext/public/ @nextchamp-saqib @marination
|
||||||
|
|
||||||
.github/ @surajshetty3416 @ankush
|
.github/ @ankush
|
||||||
requirements.txt @gavindsouza
|
requirements.txt @gavindsouza
|
||||||
|
1
dev-requirements.txt
Normal file
1
dev-requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
hypothesis~=6.31.0
|
@ -55,9 +55,9 @@ def set_perpetual_inventory(enable=1, company=None):
|
|||||||
company.enable_perpetual_inventory = enable
|
company.enable_perpetual_inventory = enable
|
||||||
company.save()
|
company.save()
|
||||||
|
|
||||||
def encode_company_abbr(name, company):
|
def encode_company_abbr(name, company=None, abbr=None):
|
||||||
'''Returns name encoded with company abbreviation'''
|
'''Returns name encoded with company abbreviation'''
|
||||||
company_abbr = frappe.get_cached_value('Company', company, "abbr")
|
company_abbr = abbr or frappe.get_cached_value('Company', company, "abbr")
|
||||||
parts = name.rsplit(" - ", 1)
|
parts = name.rsplit(" - ", 1)
|
||||||
|
|
||||||
if parts[-1].lower() != company_abbr.lower():
|
if parts[-1].lower() != company_abbr.lower():
|
||||||
|
@ -43,12 +43,12 @@ frappe.ui.form.on('Account', {
|
|||||||
frm.trigger('add_toolbar_buttons');
|
frm.trigger('add_toolbar_buttons');
|
||||||
}
|
}
|
||||||
if (frm.has_perm('write')) {
|
if (frm.has_perm('write')) {
|
||||||
frm.add_custom_button(__('Update Account Name / Number'), function () {
|
|
||||||
frm.trigger("update_account_number");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__('Merge Account'), function () {
|
frm.add_custom_button(__('Merge Account'), function () {
|
||||||
frm.trigger("merge_account");
|
frm.trigger("merge_account");
|
||||||
});
|
}, __('Actions'));
|
||||||
|
frm.add_custom_button(__('Update Account Name / Number'), function () {
|
||||||
|
frm.trigger("update_account_number");
|
||||||
|
}, __('Actions'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -59,11 +59,12 @@ frappe.ui.form.on('Account', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
add_toolbar_buttons: function(frm) {
|
add_toolbar_buttons: function(frm) {
|
||||||
frm.add_custom_button(__('Chart of Accounts'),
|
frm.add_custom_button(__('Chart of Accounts'), () => {
|
||||||
function () { frappe.set_route("Tree", "Account"); });
|
frappe.set_route("Tree", "Account");
|
||||||
|
}, __('View'));
|
||||||
|
|
||||||
if (frm.doc.is_group == 1) {
|
if (frm.doc.is_group == 1) {
|
||||||
frm.add_custom_button(__('Group to Non-Group'), function () {
|
frm.add_custom_button(__('Convert to Non-Group'), function () {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: 'convert_group_to_ledger',
|
method: 'convert_group_to_ledger',
|
||||||
@ -71,10 +72,11 @@ frappe.ui.form.on('Account', {
|
|||||||
frm.refresh();
|
frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, __('Actions'));
|
||||||
|
|
||||||
} else if (cint(frm.doc.is_group) == 0
|
} else if (cint(frm.doc.is_group) == 0
|
||||||
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||||
frm.add_custom_button(__('Ledger'), function () {
|
frm.add_custom_button(__('General Ledger'), function () {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
"account": frm.doc.name,
|
"account": frm.doc.name,
|
||||||
"from_date": frappe.sys_defaults.year_start_date,
|
"from_date": frappe.sys_defaults.year_start_date,
|
||||||
@ -82,9 +84,9 @@ frappe.ui.form.on('Account', {
|
|||||||
"company": frm.doc.company
|
"company": frm.doc.company
|
||||||
};
|
};
|
||||||
frappe.set_route("query-report", "General Ledger");
|
frappe.set_route("query-report", "General Ledger");
|
||||||
});
|
}, __('View'));
|
||||||
|
|
||||||
frm.add_custom_button(__('Non-Group to Group'), function () {
|
frm.add_custom_button(__('Convert to Group'), function () {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: 'convert_ledger_to_group',
|
method: 'convert_ledger_to_group',
|
||||||
@ -92,7 +94,7 @@ frappe.ui.form.on('Account', {
|
|||||||
frm.refresh();
|
frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, __('Actions'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
QUnit.module('accounts');
|
|
||||||
|
|
||||||
QUnit.test("test account", function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => frappe.set_route('Tree', 'Account'),
|
|
||||||
() => frappe.timeout(3),
|
|
||||||
() => frappe.click_button('Expand All'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_link('Debtors'),
|
|
||||||
() => frappe.click_button('Edit'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.root_type=='Asset');
|
|
||||||
assert.ok(cur_frm.doc.report_type=='Balance Sheet');
|
|
||||||
assert.ok(cur_frm.doc.account_type=='Receivable');
|
|
||||||
},
|
|
||||||
() => frappe.click_button('Ledger'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
// check if general ledger report shown
|
|
||||||
assert.deepEqual(frappe.get_route(), ['query-report', 'General Ledger']);
|
|
||||||
window.history.back();
|
|
||||||
return frappe.timeout(1);
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,69 +0,0 @@
|
|||||||
QUnit.module('accounts');
|
|
||||||
|
|
||||||
QUnit.test("test account with number", function(assert) {
|
|
||||||
assert.expect(7);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => frappe.set_route('Tree', 'Account'),
|
|
||||||
() => frappe.click_link('Income'),
|
|
||||||
() => frappe.click_button('Add Child'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
cur_dialog.fields_dict.account_name.$input.val("Test Income");
|
|
||||||
cur_dialog.fields_dict.account_number.$input.val("4010");
|
|
||||||
},
|
|
||||||
() => frappe.click_button('Create New'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
assert.ok($('a:contains("4010 - Test Income"):visible').length!=0, "Account created with number");
|
|
||||||
},
|
|
||||||
() => frappe.click_link('4010 - Test Income'),
|
|
||||||
() => frappe.click_button('Edit'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => frappe.click_button('Update Account Number'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
cur_dialog.fields_dict.account_number.$input.val("4020");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => cur_dialog.primary_action(),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => cur_frm.refresh_fields(),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
var abbr = frappe.get_abbr(frappe.defaults.get_default("Company"));
|
|
||||||
var new_account = "4020 - Test Income - " + abbr;
|
|
||||||
assert.ok(cur_frm.doc.name==new_account, "Account renamed");
|
|
||||||
assert.ok(cur_frm.doc.account_name=="Test Income", "account name remained same");
|
|
||||||
assert.ok(cur_frm.doc.account_number=="4020", "Account number updated to 4020");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Menu'),
|
|
||||||
() => frappe.click_link('Rename'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
cur_dialog.fields_dict.new_name.$input.val("4030 - Test Income");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => frappe.click_button("Rename"),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.account_name=="Test Income", "account name remained same");
|
|
||||||
assert.ok(cur_frm.doc.account_number=="4030", "Account number updated to 4030");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => frappe.click_button('Chart of Accounts'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => frappe.click_button('Menu'),
|
|
||||||
() => frappe.click_link('Refresh'),
|
|
||||||
() => frappe.click_button('Expand All'),
|
|
||||||
() => frappe.click_link('4030 - Test Income'),
|
|
||||||
() => frappe.click_button('Delete'),
|
|
||||||
() => frappe.click_button('Yes'),
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
assert.ok($('a:contains("4030 - Test Account"):visible').length==0, "Account deleted");
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,46 +0,0 @@
|
|||||||
QUnit.module('accounts');
|
|
||||||
QUnit.test("test account", assert => {
|
|
||||||
assert.expect(3);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => frappe.set_route('Tree', 'Account'),
|
|
||||||
() => frappe.click_button('Expand All'),
|
|
||||||
() => frappe.click_link('Duties and Taxes - '+ frappe.get_abbr(frappe.defaults.get_default("Company"))),
|
|
||||||
() => {
|
|
||||||
if($('a:contains("CGST"):visible').length == 0){
|
|
||||||
return frappe.map_tax.make('CGST', 9);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
if($('a:contains("SGST"):visible').length == 0){
|
|
||||||
return frappe.map_tax.make('SGST', 9);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
if($('a:contains("IGST"):visible').length == 0){
|
|
||||||
return frappe.map_tax.make('IGST', 18);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
assert.ok($('a:contains("CGST"):visible').length!=0, "CGST Checked");
|
|
||||||
assert.ok($('a:contains("SGST"):visible').length!=0, "SGST Checked");
|
|
||||||
assert.ok($('a:contains("IGST"):visible').length!=0, "IGST Checked");
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
frappe.map_tax = {
|
|
||||||
make:function(text,rate){
|
|
||||||
return frappe.run_serially([
|
|
||||||
() => frappe.click_button('Add Child'),
|
|
||||||
() => frappe.timeout(0.2),
|
|
||||||
() => cur_dialog.set_value('account_name',text),
|
|
||||||
() => cur_dialog.set_value('account_type','Tax'),
|
|
||||||
() => cur_dialog.set_value('tax_rate',rate),
|
|
||||||
() => cur_dialog.set_value('account_currency','INR'),
|
|
||||||
() => frappe.click_button('Create New'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,35 +0,0 @@
|
|||||||
QUnit.module('accounts');
|
|
||||||
|
|
||||||
QUnit.test("test: Accounts Settings doesn't allow negatives", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
assert.expect(2);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
() => frappe.set_route('Form', 'Accounts Settings', 'Accounts Settings'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => unchecked_if_checked(cur_frm, 'Allow Stale Exchange Rates', frappe.click_check),
|
|
||||||
() => cur_frm.set_value('stale_days', 0),
|
|
||||||
() => frappe.click_button('Save'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_dialog);
|
|
||||||
},
|
|
||||||
() => frappe.click_button('Close'),
|
|
||||||
() => cur_frm.set_value('stale_days', -1),
|
|
||||||
() => frappe.click_button('Save'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_dialog);
|
|
||||||
},
|
|
||||||
() => frappe.click_button('Close'),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
const unchecked_if_checked = function(frm, field_name, fn){
|
|
||||||
if (frm.doc.allow_stale) {
|
|
||||||
return fn(field_name);
|
|
||||||
}
|
|
||||||
};
|
|
@ -7,7 +7,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
frm.set_query("bank_account", function () {
|
frm.set_query("bank_account", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: ["in", frm.doc.company],
|
company: frm.doc.company,
|
||||||
'is_company_account': 1
|
'is_company_account': 1
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -218,6 +218,8 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
|
|||||||
# updated clear date of all the vouchers based on the bank transaction
|
# updated clear date of all the vouchers based on the bank transaction
|
||||||
vouchers = json.loads(vouchers)
|
vouchers = json.loads(vouchers)
|
||||||
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||||
|
company_account = frappe.db.get_value('Bank Account', transaction.bank_account, 'account')
|
||||||
|
|
||||||
if transaction.unallocated_amount == 0:
|
if transaction.unallocated_amount == 0:
|
||||||
frappe.throw(_("This bank transaction is already fully reconciled"))
|
frappe.throw(_("This bank transaction is already fully reconciled"))
|
||||||
total_amount = 0
|
total_amount = 0
|
||||||
@ -226,7 +228,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
|
|||||||
total_amount += get_paid_amount(frappe._dict({
|
total_amount += get_paid_amount(frappe._dict({
|
||||||
'payment_document': voucher['payment_doctype'],
|
'payment_document': voucher['payment_doctype'],
|
||||||
'payment_entry': voucher['payment_name'],
|
'payment_entry': voucher['payment_name'],
|
||||||
}), transaction.currency)
|
}), transaction.currency, company_account)
|
||||||
|
|
||||||
if total_amount > transaction.unallocated_amount:
|
if total_amount > transaction.unallocated_amount:
|
||||||
frappe.throw(_("The Sum Total of Amounts of All Selected Vouchers Should be Less than the Unallocated Amount of the Bank Transaction"))
|
frappe.throw(_("The Sum Total of Amounts of All Selected Vouchers Should be Less than the Unallocated Amount of the Bank Transaction"))
|
||||||
@ -261,7 +263,7 @@ def get_linked_payments(bank_transaction_name, document_types = None):
|
|||||||
return matching
|
return matching
|
||||||
|
|
||||||
def check_matching(bank_account, company, transaction, document_types):
|
def check_matching(bank_account, company, transaction, document_types):
|
||||||
# combine all types of vocuhers
|
# combine all types of vouchers
|
||||||
subquery = get_queries(bank_account, company, transaction, document_types)
|
subquery = get_queries(bank_account, company, transaction, document_types)
|
||||||
filters = {
|
filters = {
|
||||||
"amount": transaction.unallocated_amount,
|
"amount": transaction.unallocated_amount,
|
||||||
@ -343,12 +345,10 @@ def get_pe_matching_query(amount_condition, account_from_to, transaction):
|
|||||||
def get_je_matching_query(amount_condition, transaction):
|
def get_je_matching_query(amount_condition, transaction):
|
||||||
# get matching journal entry query
|
# get matching journal entry query
|
||||||
|
|
||||||
|
# We have mapping at the bank level
|
||||||
|
# So one bank could have both types of bank accounts like asset and liability
|
||||||
|
# So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type
|
||||||
company_account = frappe.get_value("Bank Account", transaction.bank_account, "account")
|
company_account = frappe.get_value("Bank Account", transaction.bank_account, "account")
|
||||||
root_type = frappe.get_value("Account", company_account, "root_type")
|
|
||||||
|
|
||||||
if root_type == "Liability":
|
|
||||||
cr_or_dr = "debit" if transaction.withdrawal > 0 else "credit"
|
|
||||||
else:
|
|
||||||
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
|
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
|
||||||
|
|
||||||
return f"""
|
return f"""
|
||||||
|
@ -239,7 +239,8 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
"withdrawal",
|
"withdrawal",
|
||||||
"description",
|
"description",
|
||||||
"reference_number",
|
"reference_number",
|
||||||
"bank_account"
|
"bank_account",
|
||||||
|
"currency"
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -102,7 +102,7 @@ def get_total_allocated_amount(payment_entry):
|
|||||||
AND
|
AND
|
||||||
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
|
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
|
||||||
|
|
||||||
def get_paid_amount(payment_entry, currency):
|
def get_paid_amount(payment_entry, currency, bank_account):
|
||||||
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
|
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
|
||||||
|
|
||||||
paid_amount_field = "paid_amount"
|
paid_amount_field = "paid_amount"
|
||||||
@ -115,7 +115,7 @@ def get_paid_amount(payment_entry, currency):
|
|||||||
payment_entry.payment_entry, paid_amount_field)
|
payment_entry.payment_entry, paid_amount_field)
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Journal Entry":
|
elif payment_entry.payment_document == "Journal Entry":
|
||||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
|
return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, "sum(credit_in_account_currency)")
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Expense Claim":
|
elif payment_entry.payment_document == "Expense Claim":
|
||||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
|
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
|
||||||
|
@ -31,7 +31,7 @@ frappe.ui.form.on("Journal Entry", {
|
|||||||
if(frm.doc.docstatus==1) {
|
if(frm.doc.docstatus==1) {
|
||||||
frm.add_custom_button(__('Reverse Journal Entry'), function() {
|
frm.add_custom_button(__('Reverse Journal Entry'), function() {
|
||||||
return erpnext.journal_entry.reverse_journal_entry(frm);
|
return erpnext.journal_entry.reverse_journal_entry(frm);
|
||||||
}, __('Make'));
|
}, __('Actions'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"voucher_type",
|
"voucher_type",
|
||||||
"naming_series",
|
"naming_series",
|
||||||
"finance_book",
|
"finance_book",
|
||||||
|
"reversal_of",
|
||||||
"tax_withholding_category",
|
"tax_withholding_category",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"from_template",
|
"from_template",
|
||||||
@ -515,13 +516,21 @@
|
|||||||
"fieldname": "apply_tds",
|
"fieldname": "apply_tds",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Apply Tax Withholding Amount "
|
"label": "Apply Tax Withholding Amount "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.docstatus",
|
||||||
|
"fieldname": "reversal_of",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Reversal Of",
|
||||||
|
"options": "Journal Entry",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 176,
|
"idx": 176,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-09 15:31:14.484029",
|
"modified": "2022-01-04 13:39:36.485954",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Journal Entry",
|
"name": "Journal Entry",
|
||||||
|
@ -1157,9 +1157,8 @@ def make_inter_company_journal_entry(name, voucher_type, company):
|
|||||||
def make_reverse_journal_entry(source_name, target_doc=None):
|
def make_reverse_journal_entry(source_name, target_doc=None):
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
|
||||||
def update_accounts(source, target, source_parent):
|
def post_process(source, target):
|
||||||
target.reference_type = "Journal Entry"
|
target.reversal_of = source.name
|
||||||
target.reference_name = source_parent.name
|
|
||||||
|
|
||||||
doclist = get_mapped_doc("Journal Entry", source_name, {
|
doclist = get_mapped_doc("Journal Entry", source_name, {
|
||||||
"Journal Entry": {
|
"Journal Entry": {
|
||||||
@ -1177,9 +1176,8 @@ def make_reverse_journal_entry(source_name, target_doc=None):
|
|||||||
"debit": "credit",
|
"debit": "credit",
|
||||||
"credit_in_account_currency": "debit_in_account_currency",
|
"credit_in_account_currency": "debit_in_account_currency",
|
||||||
"credit": "debit",
|
"credit": "debit",
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"postprocess": update_accounts,
|
}, target_doc, post_process)
|
||||||
},
|
|
||||||
}, target_doc)
|
|
||||||
|
|
||||||
return doclist
|
return doclist
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
QUnit.module('Journal Entry');
|
|
||||||
|
|
||||||
QUnit.test("test journal entry", function(assert) {
|
|
||||||
assert.expect(2);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Journal Entry', [
|
|
||||||
{posting_date:frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
|
|
||||||
{accounts: [
|
|
||||||
[
|
|
||||||
{'account':'Debtors - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
|
|
||||||
{'party_type':'Customer'},
|
|
||||||
{'party':'Test Customer 1'},
|
|
||||||
{'credit_in_account_currency':1000},
|
|
||||||
{'is_advance':'Yes'},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{'account':'HDFC - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
|
|
||||||
{'debit_in_account_currency':1000},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{cheque_no:1234},
|
|
||||||
{cheque_date: frappe.datetime.add_days(frappe.datetime.nowdate(), -1)},
|
|
||||||
{user_remark: 'Test'},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.total_debit==1000, "total debit correct");
|
|
||||||
assert.ok(cur_frm.doc.total_credit==1000, "total credit correct");
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
128
erpnext/accounts/doctype/ledger_merge/ledger_merge.js
Normal file
128
erpnext/accounts/doctype/ledger_merge/ledger_merge.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Ledger Merge', {
|
||||||
|
setup: function(frm) {
|
||||||
|
frappe.realtime.on('ledger_merge_refresh', ({ ledger_merge }) => {
|
||||||
|
if (ledger_merge !== frm.doc.name) return;
|
||||||
|
frappe.model.clear_doc(frm.doc.doctype, frm.doc.name);
|
||||||
|
frappe.model.with_doc(frm.doc.doctype, frm.doc.name).then(() => {
|
||||||
|
frm.refresh();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.realtime.on('ledger_merge_progress', data => {
|
||||||
|
if (data.ledger_merge !== frm.doc.name) return;
|
||||||
|
let message = __('Merging {0} of {1}', [data.current, data.total]);
|
||||||
|
let percent = Math.floor((data.current * 100) / data.total);
|
||||||
|
frm.dashboard.show_progress(__('Merge Progress'), percent, message);
|
||||||
|
frm.page.set_indicator(__('In Progress'), 'orange');
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("account", function(doc) {
|
||||||
|
if (!doc.company) frappe.throw(__('Please set Company'));
|
||||||
|
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
root_type: doc.root_type,
|
||||||
|
company: doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query('account', 'merge_accounts', function(doc) {
|
||||||
|
if (!doc.company) frappe.throw(__('Please set Company'));
|
||||||
|
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
|
||||||
|
if (!doc.account) frappe.throw(__('Please set Account'));
|
||||||
|
let acc = [doc.account];
|
||||||
|
frm.doc.merge_accounts.forEach((row) => {
|
||||||
|
acc.push(row.account);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
is_group: doc.is_group,
|
||||||
|
root_type: doc.root_type,
|
||||||
|
name: ["not in", acc],
|
||||||
|
company: doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function(frm) {
|
||||||
|
frm.page.hide_icon_group();
|
||||||
|
frm.trigger('set_merge_status');
|
||||||
|
frm.trigger('update_primary_action');
|
||||||
|
},
|
||||||
|
|
||||||
|
after_save: function(frm) {
|
||||||
|
setTimeout(() => {
|
||||||
|
frm.trigger('update_primary_action');
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
update_primary_action: function(frm) {
|
||||||
|
if (frm.is_dirty()) {
|
||||||
|
frm.enable_save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frm.disable_save();
|
||||||
|
if (frm.doc.status !== 'Success') {
|
||||||
|
if (!frm.is_new()) {
|
||||||
|
let label = frm.doc.status === 'Pending' ? __('Start Merge') : __('Retry');
|
||||||
|
frm.page.set_primary_action(label, () => frm.events.start_merge(frm));
|
||||||
|
} else {
|
||||||
|
frm.page.set_primary_action(__('Save'), () => frm.save());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
start_merge: function(frm) {
|
||||||
|
frm.call({
|
||||||
|
method: 'form_start_merge',
|
||||||
|
args: { docname: frm.doc.name },
|
||||||
|
btn: frm.page.btn_primary
|
||||||
|
}).then(r => {
|
||||||
|
if (r.message === true) {
|
||||||
|
frm.disable_save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
set_merge_status: function(frm) {
|
||||||
|
if (frm.doc.status == "Pending") return;
|
||||||
|
let successful_records = 0;
|
||||||
|
frm.doc.merge_accounts.forEach((row) => {
|
||||||
|
if (row.merged) successful_records += 1;
|
||||||
|
});
|
||||||
|
let message_args = [successful_records, frm.doc.merge_accounts.length];
|
||||||
|
frm.dashboard.set_headline(__('Successfully merged {0} out of {1}.', message_args));
|
||||||
|
},
|
||||||
|
|
||||||
|
root_type: function(frm) {
|
||||||
|
frm.set_value('account', '');
|
||||||
|
frm.set_value('merge_accounts', []);
|
||||||
|
},
|
||||||
|
|
||||||
|
company: function(frm) {
|
||||||
|
frm.set_value('account', '');
|
||||||
|
frm.set_value('merge_accounts', []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on('Ledger Merge Accounts', {
|
||||||
|
merge_accounts_add: function(frm) {
|
||||||
|
frm.trigger('update_primary_action');
|
||||||
|
},
|
||||||
|
|
||||||
|
merge_accounts_remove: function(frm) {
|
||||||
|
frm.trigger('update_primary_action');
|
||||||
|
},
|
||||||
|
|
||||||
|
account: function(frm, cdt, cdn) {
|
||||||
|
let row = frappe.get_doc(cdt, cdn);
|
||||||
|
row.account_name = row.account;
|
||||||
|
frm.refresh_field('merge_accounts');
|
||||||
|
frm.trigger('update_primary_action');
|
||||||
|
}
|
||||||
|
});
|
130
erpnext/accounts/doctype/ledger_merge/ledger_merge.json
Normal file
130
erpnext/accounts/doctype/ledger_merge/ledger_merge.json
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"autoname": "format:{account_name} merger on {creation}",
|
||||||
|
"creation": "2021-12-09 15:38:04.556584",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"section_break_1",
|
||||||
|
"root_type",
|
||||||
|
"account",
|
||||||
|
"account_name",
|
||||||
|
"column_break_3",
|
||||||
|
"company",
|
||||||
|
"status",
|
||||||
|
"is_group",
|
||||||
|
"section_break_5",
|
||||||
|
"merge_accounts"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"depends_on": "root_type",
|
||||||
|
"fieldname": "account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account",
|
||||||
|
"options": "Account",
|
||||||
|
"reqd": 1,
|
||||||
|
"set_only_once": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_1",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "merge_accounts",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Accounts to Merge",
|
||||||
|
"options": "Ledger Merge Accounts",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "account",
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Company",
|
||||||
|
"options": "Company",
|
||||||
|
"reqd": 1,
|
||||||
|
"set_only_once": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Status",
|
||||||
|
"options": "Pending\nSuccess\nPartial Success\nError",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "root_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Root Type",
|
||||||
|
"options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
|
||||||
|
"reqd": 1,
|
||||||
|
"set_only_once": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "account",
|
||||||
|
"fetch_from": "account.account_name",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
|
"fieldname": "account_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Account Name",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "account",
|
||||||
|
"fetch_from": "account.is_group",
|
||||||
|
"fieldname": "is_group",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Group",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_toolbar": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-12-12 21:34:55.155146",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Ledger Merge",
|
||||||
|
"naming_rule": "Expression",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
76
erpnext/accounts/doctype/ledger_merge/ledger_merge.py
Normal file
76
erpnext/accounts/doctype/ledger_merge/ledger_merge.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.account.account import merge_account
|
||||||
|
|
||||||
|
|
||||||
|
class LedgerMerge(Document):
|
||||||
|
def start_merge(self):
|
||||||
|
from frappe.core.page.background_jobs.background_jobs import get_info
|
||||||
|
from frappe.utils.background_jobs import enqueue
|
||||||
|
from frappe.utils.scheduler import is_scheduler_inactive
|
||||||
|
|
||||||
|
if is_scheduler_inactive() and not frappe.flags.in_test:
|
||||||
|
frappe.throw(
|
||||||
|
_("Scheduler is inactive. Cannot merge accounts."), title=_("Scheduler Inactive")
|
||||||
|
)
|
||||||
|
|
||||||
|
enqueued_jobs = [d.get("job_name") for d in get_info()]
|
||||||
|
|
||||||
|
if self.name not in enqueued_jobs:
|
||||||
|
enqueue(
|
||||||
|
start_merge,
|
||||||
|
queue="default",
|
||||||
|
timeout=6000,
|
||||||
|
event="ledger_merge",
|
||||||
|
job_name=self.name,
|
||||||
|
docname=self.name,
|
||||||
|
now=frappe.conf.developer_mode or frappe.flags.in_test,
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def form_start_merge(docname):
|
||||||
|
return frappe.get_doc("Ledger Merge", docname).start_merge()
|
||||||
|
|
||||||
|
def start_merge(docname):
|
||||||
|
ledger_merge = frappe.get_doc("Ledger Merge", docname)
|
||||||
|
successful_merges = 0
|
||||||
|
total = len(ledger_merge.merge_accounts)
|
||||||
|
for row in ledger_merge.merge_accounts:
|
||||||
|
if not row.merged:
|
||||||
|
try:
|
||||||
|
merge_account(
|
||||||
|
row.account,
|
||||||
|
ledger_merge.account,
|
||||||
|
ledger_merge.is_group,
|
||||||
|
ledger_merge.root_type,
|
||||||
|
ledger_merge.company
|
||||||
|
)
|
||||||
|
row.db_set('merged', 1)
|
||||||
|
frappe.db.commit()
|
||||||
|
successful_merges += 1
|
||||||
|
frappe.publish_realtime("ledger_merge_progress", {
|
||||||
|
"ledger_merge": ledger_merge.name,
|
||||||
|
"current": successful_merges,
|
||||||
|
"total": total
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
frappe.db.rollback()
|
||||||
|
frappe.log_error(title=ledger_merge.name)
|
||||||
|
finally:
|
||||||
|
if successful_merges == total:
|
||||||
|
ledger_merge.db_set('status', 'Success')
|
||||||
|
elif successful_merges > 0:
|
||||||
|
ledger_merge.db_set('status', 'Partial Success')
|
||||||
|
else:
|
||||||
|
ledger_merge.db_set('status', 'Error')
|
||||||
|
|
||||||
|
frappe.publish_realtime("ledger_merge_refresh", {"ledger_merge": ledger_merge.name})
|
118
erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py
Normal file
118
erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.ledger_merge.ledger_merge import start_merge
|
||||||
|
|
||||||
|
|
||||||
|
class TestLedgerMerge(unittest.TestCase):
|
||||||
|
def test_merge_success(self):
|
||||||
|
if not frappe.db.exists("Account", "Indirect Expenses - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Indirect Expenses"
|
||||||
|
acc.is_group = 1
|
||||||
|
acc.parent_account = "Expenses - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
if not frappe.db.exists("Account", "Indirect Test Expenses - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Indirect Test Expenses"
|
||||||
|
acc.is_group = 1
|
||||||
|
acc.parent_account = "Expenses - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
if not frappe.db.exists("Account", "Administrative Test Expenses - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Administrative Test Expenses"
|
||||||
|
acc.parent_account = "Indirect Test Expenses - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
|
||||||
|
doc = frappe.get_doc({
|
||||||
|
"doctype": "Ledger Merge",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"root_type": frappe.db.get_value("Account", "Indirect Test Expenses - _TC", "root_type"),
|
||||||
|
"account": "Indirect Expenses - _TC",
|
||||||
|
"merge_accounts": [
|
||||||
|
{
|
||||||
|
"account": "Indirect Test Expenses - _TC",
|
||||||
|
"account_name": "Indirect Expenses"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
parent = frappe.db.get_value("Account", "Administrative Test Expenses - _TC", "parent_account")
|
||||||
|
self.assertEqual(parent, "Indirect Test Expenses - _TC")
|
||||||
|
|
||||||
|
start_merge(doc.name)
|
||||||
|
|
||||||
|
parent = frappe.db.get_value("Account", "Administrative Test Expenses - _TC", "parent_account")
|
||||||
|
self.assertEqual(parent, "Indirect Expenses - _TC")
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.exists("Account", "Indirect Test Expenses - _TC"))
|
||||||
|
|
||||||
|
def test_partial_merge_success(self):
|
||||||
|
if not frappe.db.exists("Account", "Indirect Income - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Indirect Income"
|
||||||
|
acc.is_group = 1
|
||||||
|
acc.parent_account = "Income - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
if not frappe.db.exists("Account", "Indirect Test Income - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Indirect Test Income"
|
||||||
|
acc.is_group = 1
|
||||||
|
acc.parent_account = "Income - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
if not frappe.db.exists("Account", "Administrative Test Income - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Administrative Test Income"
|
||||||
|
acc.parent_account = "Indirect Test Income - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
|
||||||
|
doc = frappe.get_doc({
|
||||||
|
"doctype": "Ledger Merge",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"root_type": frappe.db.get_value("Account", "Indirect Income - _TC", "root_type"),
|
||||||
|
"account": "Indirect Income - _TC",
|
||||||
|
"merge_accounts": [
|
||||||
|
{
|
||||||
|
"account": "Indirect Test Income - _TC",
|
||||||
|
"account_name": "Indirect Test Income"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account": "Administrative Test Income - _TC",
|
||||||
|
"account_name": "Administrative Test Income"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
parent = frappe.db.get_value("Account", "Administrative Test Income - _TC", "parent_account")
|
||||||
|
self.assertEqual(parent, "Indirect Test Income - _TC")
|
||||||
|
|
||||||
|
start_merge(doc.name)
|
||||||
|
|
||||||
|
parent = frappe.db.get_value("Account", "Administrative Test Income - _TC", "parent_account")
|
||||||
|
self.assertEqual(parent, "Indirect Income - _TC")
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.exists("Account", "Indirect Test Income - _TC"))
|
||||||
|
self.assertTrue(frappe.db.exists("Account", "Administrative Test Income - _TC"))
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
for entry in frappe.db.get_all("Ledger Merge"):
|
||||||
|
frappe.delete_doc("Ledger Merge", entry.name)
|
||||||
|
|
||||||
|
test_accounts = [
|
||||||
|
"Indirect Test Expenses - _TC",
|
||||||
|
"Administrative Test Expenses - _TC",
|
||||||
|
"Indirect Test Income - _TC",
|
||||||
|
"Administrative Test Income - _TC"
|
||||||
|
]
|
||||||
|
for account in test_accounts:
|
||||||
|
frappe.delete_doc_if_exists("Account", account)
|
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2021-12-09 15:44:58.033398",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"account",
|
||||||
|
"account_name",
|
||||||
|
"merged"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"columns": 4,
|
||||||
|
"fieldname": "account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Account",
|
||||||
|
"options": "Account",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "merged",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Merged",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 4,
|
||||||
|
"fieldname": "account_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Account Name",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-12-10 15:27:24.477139",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Ledger Merge Accounts",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class LedgerMergeAccounts(Document):
|
||||||
|
pass
|
@ -75,7 +75,7 @@
|
|||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"modified": "2019-07-25 14:57:33.187689",
|
"modified": "2022-01-04 15:25:06.053187",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Opening Invoice Creation Tool",
|
"name": "Opening Invoice Creation Tool",
|
||||||
|
@ -148,7 +148,7 @@ def make_company():
|
|||||||
company.company_name = "_Test Opening Invoice Company"
|
company.company_name = "_Test Opening Invoice Company"
|
||||||
company.abbr = "_TOIC"
|
company.abbr = "_TOIC"
|
||||||
company.default_currency = "INR"
|
company.default_currency = "INR"
|
||||||
company.country = "India"
|
company.country = "Pakistan"
|
||||||
company.insert()
|
company.insert()
|
||||||
return company
|
return company
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _, bold
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
@ -12,6 +12,17 @@ class PartyLink(Document):
|
|||||||
frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."),
|
frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."),
|
||||||
title=_("Invalid Primary Role"))
|
title=_("Invalid Primary Role"))
|
||||||
|
|
||||||
|
existing_party_link = frappe.get_all('Party Link', {
|
||||||
|
'primary_party': self.primary_party,
|
||||||
|
'secondary_party': self.secondary_party
|
||||||
|
}, pluck="primary_role")
|
||||||
|
if existing_party_link:
|
||||||
|
frappe.throw(_('{} {} is already linked with {} {}')
|
||||||
|
.format(
|
||||||
|
self.primary_role, bold(self.primary_party),
|
||||||
|
self.secondary_role, bold(self.secondary_party)
|
||||||
|
))
|
||||||
|
|
||||||
existing_party_link = frappe.get_all('Party Link', {
|
existing_party_link = frappe.get_all('Party Link', {
|
||||||
'primary_party': self.secondary_party
|
'primary_party': self.secondary_party
|
||||||
}, pluck="primary_role")
|
}, pluck="primary_role")
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
QUnit.module('Payment Entry');
|
|
||||||
|
|
||||||
QUnit.test("test payment entry", function(assert) {
|
|
||||||
assert.expect(6);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
{'qty': 1},
|
|
||||||
{'rate': 101},
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Make'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_link('Payment'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.equal(frappe.get_route()[1], 'Payment Entry',
|
|
||||||
'made payment entry');
|
|
||||||
assert.equal(cur_frm.doc.party, 'Test Customer 1',
|
|
||||||
'customer set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.paid_amount, 101,
|
|
||||||
'paid amount set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.references[0].allocated_amount, 101,
|
|
||||||
'amount allocated against sales invoice');
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => cur_frm.set_value('paid_amount', 100),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
frappe.model.set_value("Payment Entry Reference", cur_frm.doc.references[0].name,
|
|
||||||
"allocated_amount", 101);
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Write Off Difference Amount'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.difference_amount, 0, 'difference amount is zero');
|
|
||||||
assert.equal(cur_frm.doc.deductions[0].amount, 1, 'Write off amount = 1');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,60 +0,0 @@
|
|||||||
QUnit.module('Payment Entry');
|
|
||||||
|
|
||||||
QUnit.test("test payment entry", function(assert) {
|
|
||||||
assert.expect(7 );
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Purchase Invoice', [
|
|
||||||
{supplier: 'Test Supplier'},
|
|
||||||
{bill_no: 'in1234'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 2},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
{'rate':1000},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{supplier_address: 'Test1-Billing'},
|
|
||||||
{contact_person: 'Contact 3-Test Supplier'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is just a Test'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Make'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => frappe.click_link('Payment'),
|
|
||||||
() => frappe.timeout(3),
|
|
||||||
() => cur_frm.set_value('mode_of_payment','Cash'),
|
|
||||||
() => frappe.timeout(3),
|
|
||||||
() => {
|
|
||||||
assert.equal(frappe.get_route()[1], 'Payment Entry',
|
|
||||||
'made payment entry');
|
|
||||||
assert.equal(cur_frm.doc.party, 'Test Supplier',
|
|
||||||
'supplier set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.paid_amount, 2000,
|
|
||||||
'paid amount set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.references[0].allocated_amount, 2000,
|
|
||||||
'amount allocated against purchase invoice');
|
|
||||||
assert.equal(cur_frm.doc.references[0].bill_no, 'in1234',
|
|
||||||
'invoice number allocated against purchase invoice');
|
|
||||||
assert.equal(cur_frm.get_field('total_allocated_amount').value, 2000,
|
|
||||||
'correct amount allocated in Write Off');
|
|
||||||
assert.equal(cur_frm.get_field('unallocated_amount').value, 0,
|
|
||||||
'correct amount unallocated in Write Off');
|
|
||||||
},
|
|
||||||
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
QUnit.module('Accounts');
|
|
||||||
|
|
||||||
QUnit.test("test payment entry", function(assert) {
|
|
||||||
assert.expect(1);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Payment Entry', [
|
|
||||||
{payment_type:'Receive'},
|
|
||||||
{mode_of_payment:'Cash'},
|
|
||||||
{party_type:'Customer'},
|
|
||||||
{party:'Test Customer 3'},
|
|
||||||
{paid_amount:675},
|
|
||||||
{reference_no:123},
|
|
||||||
{reference_date: frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.total_allocated_amount==675, "Allocated AmountCorrect");
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,67 +0,0 @@
|
|||||||
QUnit.module('Payment Entry');
|
|
||||||
|
|
||||||
QUnit.test("test payment entry", function(assert) {
|
|
||||||
assert.expect(8);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{company: 'For Testing'},
|
|
||||||
{currency: 'INR'},
|
|
||||||
{selling_price_list: '_Test Price List'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 1},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(1.5),
|
|
||||||
() => frappe.click_button('Close'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.click_button('Make'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_link('Payment'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => cur_frm.set_value("paid_to", "_Test Cash - FT"),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => {
|
|
||||||
assert.equal(frappe.get_route()[1], 'Payment Entry', 'made payment entry');
|
|
||||||
assert.equal(cur_frm.doc.party, 'Test Customer 1', 'customer set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.paid_from, 'Debtors - FT', 'customer account set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.paid_amount, 100, 'paid amount set in payment entry');
|
|
||||||
assert.equal(cur_frm.doc.references[0].allocated_amount, 100,
|
|
||||||
'amount allocated against sales invoice');
|
|
||||||
},
|
|
||||||
() => cur_frm.set_value('paid_amount', 95),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => {
|
|
||||||
frappe.model.set_value("Payment Entry Reference",
|
|
||||||
cur_frm.doc.references[0].name, "allocated_amount", 100);
|
|
||||||
},
|
|
||||||
() => frappe.timeout(.5),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.difference_amount, 5, 'difference amount is 5');
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
frappe.db.set_value("Company", "For Testing", "write_off_account", "_Test Write Off - FT");
|
|
||||||
frappe.timeout(1);
|
|
||||||
frappe.db.set_value("Company", "For Testing",
|
|
||||||
"exchange_gain_loss_account", "_Test Exchange Gain/Loss - FT");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Write Off Difference Amount'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.difference_amount, 0, 'difference amount is zero');
|
|
||||||
assert.equal(cur_frm.doc.deductions[0].amount, 5, 'Write off amount = 5');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -15,6 +15,7 @@ from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
|
|||||||
update_multi_mode_option,
|
update_multi_mode_option,
|
||||||
)
|
)
|
||||||
from erpnext.accounts.party import get_due_date, get_party_account
|
from erpnext.accounts.party import get_due_date, get_party_account
|
||||||
|
from erpnext.stock.doctype.batch.batch import get_batch_qty, get_pos_reserved_batch_qty
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos
|
||||||
|
|
||||||
|
|
||||||
@ -124,9 +125,26 @@ class POSInvoice(SalesInvoice):
|
|||||||
frappe.throw(_("Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no.")
|
frappe.throw(_("Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no.")
|
||||||
.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
|
.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
|
||||||
elif invalid_serial_nos:
|
elif invalid_serial_nos:
|
||||||
frappe.throw(_("Row #{}: Serial Nos. {} has already been transacted into another POS Invoice. Please select valid serial no.")
|
frappe.throw(_("Row #{}: Serial Nos. {} have already been transacted into another POS Invoice. Please select valid serial no.")
|
||||||
.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
|
.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
|
||||||
|
|
||||||
|
def validate_pos_reserved_batch_qty(self, item):
|
||||||
|
filters = {"item_code": item.item_code, "warehouse": item.warehouse, "batch_no":item.batch_no}
|
||||||
|
|
||||||
|
available_batch_qty = get_batch_qty(item.batch_no, item.warehouse, item.item_code)
|
||||||
|
reserved_batch_qty = get_pos_reserved_batch_qty(filters)
|
||||||
|
|
||||||
|
bold_item_name = frappe.bold(item.item_name)
|
||||||
|
bold_extra_batch_qty_needed = frappe.bold(abs(available_batch_qty - reserved_batch_qty - item.qty))
|
||||||
|
bold_invalid_batch_no = frappe.bold(item.batch_no)
|
||||||
|
|
||||||
|
if (available_batch_qty - reserved_batch_qty) == 0:
|
||||||
|
frappe.throw(_("Row #{}: Batch No. {} of item {} has no stock available. Please select valid batch no.")
|
||||||
|
.format(item.idx, bold_invalid_batch_no, bold_item_name), title=_("Item Unavailable"))
|
||||||
|
elif (available_batch_qty - reserved_batch_qty - item.qty) < 0:
|
||||||
|
frappe.throw(_("Row #{}: Batch No. {} of item {} has less than required stock available, {} more required")
|
||||||
|
.format(item.idx, bold_invalid_batch_no, bold_item_name, bold_extra_batch_qty_needed), title=_("Item Unavailable"))
|
||||||
|
|
||||||
def validate_delivered_serial_nos(self, item):
|
def validate_delivered_serial_nos(self, item):
|
||||||
serial_nos = get_serial_nos(item.serial_no)
|
serial_nos = get_serial_nos(item.serial_no)
|
||||||
delivered_serial_nos = frappe.db.get_list('Serial No', {
|
delivered_serial_nos = frappe.db.get_list('Serial No', {
|
||||||
@ -149,6 +167,8 @@ class POSInvoice(SalesInvoice):
|
|||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
self.validate_pos_reserved_serial_nos(d)
|
self.validate_pos_reserved_serial_nos(d)
|
||||||
self.validate_delivered_serial_nos(d)
|
self.validate_delivered_serial_nos(d)
|
||||||
|
elif d.batch_no:
|
||||||
|
self.validate_pos_reserved_batch_qty(d)
|
||||||
else:
|
else:
|
||||||
if allow_negative_stock:
|
if allow_negative_stock:
|
||||||
return
|
return
|
||||||
|
@ -521,6 +521,41 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
|
||||||
self.assertEqual(rounded_total, 400)
|
self.assertEqual(rounded_total, 400)
|
||||||
|
|
||||||
|
def test_pos_batch_item_qty_validation(self):
|
||||||
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||||
|
create_batch_item_with_batch,
|
||||||
|
)
|
||||||
|
create_batch_item_with_batch('_BATCH ITEM', 'TestBatch 01')
|
||||||
|
item = frappe.get_doc('Item', '_BATCH ITEM')
|
||||||
|
batch = frappe.get_doc('Batch', 'TestBatch 01')
|
||||||
|
batch.submit()
|
||||||
|
item.batch_no = 'TestBatch 01'
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
se = make_stock_entry(target="_Test Warehouse - _TC", item_code="_BATCH ITEM", qty=2, basic_rate=100, batch_no='TestBatch 01')
|
||||||
|
|
||||||
|
pos_inv1 = create_pos_invoice(item=item.name, rate=300, qty=1, do_not_submit=1)
|
||||||
|
pos_inv1.items[0].batch_no = 'TestBatch 01'
|
||||||
|
pos_inv1.save()
|
||||||
|
pos_inv1.submit()
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(item=item.name, rate=300, qty=2, do_not_submit=1)
|
||||||
|
pos_inv2.items[0].batch_no = 'TestBatch 01'
|
||||||
|
pos_inv2.save()
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, pos_inv2.submit)
|
||||||
|
|
||||||
|
#teardown
|
||||||
|
pos_inv1.reload()
|
||||||
|
pos_inv1.cancel()
|
||||||
|
pos_inv1.delete()
|
||||||
|
pos_inv2.reload()
|
||||||
|
pos_inv2.delete()
|
||||||
|
se.cancel()
|
||||||
|
batch.reload()
|
||||||
|
batch.cancel()
|
||||||
|
batch.delete()
|
||||||
|
|
||||||
def create_pos_invoice(**args):
|
def create_pos_invoice(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
pos_profile = None
|
pos_profile = None
|
||||||
@ -557,7 +592,8 @@ def create_pos_invoice(**args):
|
|||||||
"income_account": args.income_account or "Sales - _TC",
|
"income_account": args.income_account or "Sales - _TC",
|
||||||
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
|
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
|
||||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||||
"serial_no": args.serial_no
|
"serial_no": args.serial_no,
|
||||||
|
"batch_no": args.batch_no
|
||||||
})
|
})
|
||||||
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
@ -570,3 +606,8 @@ def create_pos_invoice(**args):
|
|||||||
pos_inv.payment_schedule = []
|
pos_inv.payment_schedule = []
|
||||||
|
|
||||||
return pos_inv
|
return pos_inv
|
||||||
|
|
||||||
|
def make_batch_item(item_name):
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
if not frappe.db.exists(item_name):
|
||||||
|
return make_item(item_name, dict(has_batch_no = 1, create_new_batch = 1, is_stock_item=1))
|
@ -166,7 +166,7 @@ class TestPricingRule(unittest.TestCase):
|
|||||||
"item_group": "Products",
|
"item_group": "Products",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"item_group": "Seed",
|
"item_group": "_Test Item Group",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"selling": 1,
|
"selling": 1,
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
QUnit.module('Pricing Rule');
|
|
||||||
|
|
||||||
QUnit.test("test pricing rule", function(assert) {
|
|
||||||
assert.expect(2);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Pricing Rule", [
|
|
||||||
{title: 'Test Pricing Rule'},
|
|
||||||
{item_code:'Test Product 2'},
|
|
||||||
{selling:1},
|
|
||||||
{applicable_for:'Customer'},
|
|
||||||
{customer:'Test Customer 3'},
|
|
||||||
{currency: frappe.defaults.get_default("currency")}
|
|
||||||
{min_qty:1},
|
|
||||||
{max_qty:20},
|
|
||||||
{valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{discount_percentage:10},
|
|
||||||
{for_price_list:'Standard Selling'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.item_code=='Test Product 2');
|
|
||||||
assert.ok(cur_frm.doc.customer=='Test Customer 3');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,58 +0,0 @@
|
|||||||
QUnit.module('Pricing Rule');
|
|
||||||
|
|
||||||
QUnit.test("test pricing rule with different currency", function(assert) {
|
|
||||||
assert.expect(3);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Pricing Rule", [
|
|
||||||
{title: 'Test Pricing Rule 2'},
|
|
||||||
{apply_on: 'Item Code'},
|
|
||||||
{item_code:'Test Product 4'},
|
|
||||||
{selling:1},
|
|
||||||
{priority: 1},
|
|
||||||
{min_qty:1},
|
|
||||||
{max_qty:20},
|
|
||||||
{valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{margin_type: 'Amount'},
|
|
||||||
{margin_rate_or_amount: 20},
|
|
||||||
{rate_or_discount: 'Rate'},
|
|
||||||
{rate:200},
|
|
||||||
{currency:'USD'}
|
|
||||||
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.item_code=='Test Product 4');
|
|
||||||
},
|
|
||||||
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Order', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{currency: 'INR'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': "Test Product 4"}
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].pricing_rule=='Test Pricing Rule 2', "Pricing rule correct");
|
|
||||||
// margin not applied because different currency in pricing rule
|
|
||||||
assert.ok(cur_frm.doc.items[0].margin_type==null, "Margin correct");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
QUnit.module('Pricing Rule');
|
|
||||||
|
|
||||||
QUnit.test("test pricing rule with same currency", function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Pricing Rule", [
|
|
||||||
{title: 'Test Pricing Rule 1'},
|
|
||||||
{apply_on: 'Item Code'},
|
|
||||||
{item_code:'Test Product 4'},
|
|
||||||
{selling:1},
|
|
||||||
{min_qty:1},
|
|
||||||
{max_qty:20},
|
|
||||||
{valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{rate_or_discount: 'Rate'},
|
|
||||||
{rate:200},
|
|
||||||
{currency:'USD'}
|
|
||||||
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.item_code=='Test Product 4');
|
|
||||||
},
|
|
||||||
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Order', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{currency: 'USD'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': "Test Product 4"}
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].pricing_rule=='Test Pricing Rule 1', "Pricing rule correct");
|
|
||||||
assert.ok(cur_frm.doc.items[0].price_list_rate==200, "Item rate correct");
|
|
||||||
// get_total
|
|
||||||
assert.ok(cur_frm.doc.total== 1000, "Total correct");
|
|
||||||
},
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -505,11 +505,11 @@ class PurchaseInvoice(BuyingController):
|
|||||||
# Checked both rounding_adjustment and rounded_total
|
# Checked both rounding_adjustment and rounded_total
|
||||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||||
|
base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
|
||||||
|
else self.base_grand_total, self.precision("base_grand_total"))
|
||||||
|
|
||||||
if grand_total and not self.is_internal_transfer():
|
if grand_total and not self.is_internal_transfer():
|
||||||
# Did not use base_grand_total to book rounding loss gle
|
# Did not use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
|
||||||
self.precision("grand_total"))
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": self.credit_to,
|
"account": self.credit_to,
|
||||||
@ -517,8 +517,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"party": self.supplier,
|
"party": self.supplier,
|
||||||
"due_date": self.due_date,
|
"due_date": self.due_date,
|
||||||
"against": self.against_expense_account,
|
"against": self.against_expense_account,
|
||||||
"credit": grand_total_in_company_currency,
|
"credit": base_grand_total,
|
||||||
"credit_in_account_currency": grand_total_in_company_currency \
|
"credit_in_account_currency": base_grand_total \
|
||||||
if self.party_account_currency==self.company_currency else grand_total,
|
if self.party_account_currency==self.company_currency else grand_total,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
QUnit.module('Purchase Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test purchase invoice", function(assert) {
|
|
||||||
assert.expect(9);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Purchase Invoice', [
|
|
||||||
{supplier: 'Test Supplier'},
|
|
||||||
{bill_no: 'in123'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
{'rate':100},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{supplier_address: 'Test1-Billing'},
|
|
||||||
{contact_person: 'Contact 3-Test Supplier'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'},
|
|
||||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// get tax account head details
|
|
||||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
|
||||||
|
|
||||||
assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
|
|
||||||
assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(!cur_dialog, 'Message is not shown');
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -986,7 +986,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
pi = make_purchase_invoice(item=item.name, qty=1, rate=100, do_not_save=True)
|
pi = make_purchase_invoice(item=item.name, qty=1, rate=100, do_not_save=True)
|
||||||
pi.set_posting_time = 1
|
pi.set_posting_time = 1
|
||||||
pi.posting_date = '2019-03-15'
|
pi.posting_date = '2019-01-10'
|
||||||
pi.items[0].enable_deferred_expense = 1
|
pi.items[0].enable_deferred_expense = 1
|
||||||
pi.items[0].service_start_date = "2019-01-10"
|
pi.items[0].service_start_date = "2019-01-10"
|
||||||
pi.items[0].service_end_date = "2019-03-15"
|
pi.items[0].service_end_date = "2019-03-15"
|
||||||
@ -1236,7 +1236,7 @@ def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
|||||||
def update_tax_witholding_category(company, account):
|
def update_tax_witholding_category(company, account):
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|
||||||
fiscal_year = get_fiscal_year(fiscal_year='2021')
|
fiscal_year = get_fiscal_year(date=nowdate())
|
||||||
|
|
||||||
if not frappe.db.get_value('Tax Withholding Rate',
|
if not frappe.db.get_value('Tax Withholding Rate',
|
||||||
{'parent': 'TDS - 194 - Dividends - Individual', 'from_date': ('>=', fiscal_year[1]),
|
{'parent': 'TDS - 194 - Dividends - Individual', 'from_date': ('>=', fiscal_year[1]),
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
QUnit.module('Sales Taxes and Charges Template');
|
|
||||||
|
|
||||||
QUnit.test("test sales taxes and charges template", function(assert) {
|
|
||||||
assert.expect(2);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Purchase Taxes and Charges Template', [
|
|
||||||
{title: "TEST In State GST"},
|
|
||||||
{taxes:[
|
|
||||||
[
|
|
||||||
{charge_type:"On Net Total"},
|
|
||||||
{account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{charge_type:"On Net Total"},
|
|
||||||
{account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.title=='TEST In State GST');
|
|
||||||
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -862,11 +862,11 @@ class SalesInvoice(SellingController):
|
|||||||
# Checked both rounding_adjustment and rounded_total
|
# Checked both rounding_adjustment and rounded_total
|
||||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||||
|
base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
|
||||||
|
else self.base_grand_total, self.precision("base_grand_total"))
|
||||||
|
|
||||||
if grand_total and not self.is_internal_transfer():
|
if grand_total and not self.is_internal_transfer():
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
|
||||||
self.precision("grand_total"))
|
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
@ -874,8 +874,8 @@ class SalesInvoice(SellingController):
|
|||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"due_date": self.due_date,
|
"due_date": self.due_date,
|
||||||
"against": self.against_income_account,
|
"against": self.against_income_account,
|
||||||
"debit": grand_total_in_company_currency,
|
"debit": base_grand_total,
|
||||||
"debit_in_account_currency": grand_total_in_company_currency \
|
"debit_in_account_currency": base_grand_total \
|
||||||
if self.party_account_currency==self.company_currency else grand_total,
|
if self.party_account_currency==self.company_currency else grand_total,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
@ -1049,6 +1049,8 @@ class SalesInvoice(SellingController):
|
|||||||
frappe.flags.is_reverse_depr_entry = False
|
frappe.flags.is_reverse_depr_entry = False
|
||||||
asset.flags.ignore_validate_update_after_submit = True
|
asset.flags.ignore_validate_update_after_submit = True
|
||||||
schedule.journal_entry = None
|
schedule.journal_entry = None
|
||||||
|
depreciation_amount = self.get_depreciation_amount_in_je(reverse_journal_entry)
|
||||||
|
asset.finance_books[0].value_after_depreciation += depreciation_amount
|
||||||
asset.save()
|
asset.save()
|
||||||
|
|
||||||
def get_posting_date_of_sales_invoice(self):
|
def get_posting_date_of_sales_invoice(self):
|
||||||
@ -1071,6 +1073,12 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_depreciation_amount_in_je(self, journal_entry):
|
||||||
|
if journal_entry.accounts[0].debit_in_account_currency:
|
||||||
|
return journal_entry.accounts[0].debit_in_account_currency
|
||||||
|
else:
|
||||||
|
return journal_entry.accounts[0].credit_in_account_currency
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enable_discount_accounting(self):
|
def enable_discount_accounting(self):
|
||||||
if not hasattr(self, "_enable_discount_accounting"):
|
if not hasattr(self, "_enable_discount_accounting"):
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
QUnit.module('Sales Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test sales Invoice", function(assert) {
|
|
||||||
assert.expect(9);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{customer_address: 'Test1-Billing'},
|
|
||||||
{shipping_address_name: 'Test1-Shipping'},
|
|
||||||
{contact_person: 'Contact 1-Test Customer 1'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'},
|
|
||||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// get tax account head details
|
|
||||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "Grand Total correct");
|
|
||||||
|
|
||||||
assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
|
|
||||||
assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
|
||||||
},
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.timeout(0.5),
|
|
||||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
|
|
||||||
() => {
|
|
||||||
let date = cur_frm.doc.due_date;
|
|
||||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
|
||||||
frappe.timeout(0.5);
|
|
||||||
assert.ok(!cur_dialog, 'Message is not shown');
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -20,6 +20,7 @@ from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_comp
|
|||||||
from erpnext.accounts.utils import PaymentEntryUnlinkError
|
from erpnext.accounts.utils import PaymentEntryUnlinkError
|
||||||
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
|
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
|
||||||
from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data
|
from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data
|
||||||
|
from erpnext.controllers.accounts_controller import update_invoice_status
|
||||||
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
|
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
|
||||||
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
||||||
from erpnext.regional.india.utils import get_ewb_data
|
from erpnext.regional.india.utils import get_ewb_data
|
||||||
@ -2385,6 +2386,41 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.reload()
|
si.reload()
|
||||||
self.assertEqual(si.status, "Paid")
|
self.assertEqual(si.status, "Paid")
|
||||||
|
|
||||||
|
def test_update_invoice_status(self):
|
||||||
|
today = nowdate()
|
||||||
|
|
||||||
|
# Sales Invoice without Payment Schedule
|
||||||
|
si = create_sales_invoice(posting_date=add_days(today, -5))
|
||||||
|
|
||||||
|
# Sales Invoice with Payment Schedule
|
||||||
|
si_with_payment_schedule = create_sales_invoice(do_not_submit=True)
|
||||||
|
si_with_payment_schedule.extend("payment_schedule", [
|
||||||
|
{
|
||||||
|
"due_date": add_days(today, -5),
|
||||||
|
"invoice_portion": 50,
|
||||||
|
"payment_amount": si_with_payment_schedule.grand_total / 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"due_date": add_days(today, 5),
|
||||||
|
"invoice_portion": 50,
|
||||||
|
"payment_amount": si_with_payment_schedule.grand_total / 2
|
||||||
|
}
|
||||||
|
])
|
||||||
|
si_with_payment_schedule.submit()
|
||||||
|
|
||||||
|
|
||||||
|
for invoice in (si, si_with_payment_schedule):
|
||||||
|
invoice.db_set("status", "Unpaid")
|
||||||
|
update_invoice_status()
|
||||||
|
invoice.reload()
|
||||||
|
self.assertEqual(invoice.status, "Overdue")
|
||||||
|
|
||||||
|
invoice.db_set("status", "Unpaid and Discounted")
|
||||||
|
update_invoice_status()
|
||||||
|
invoice.reload()
|
||||||
|
self.assertEqual(invoice.status, "Overdue and Discounted")
|
||||||
|
|
||||||
|
|
||||||
def test_sales_commission(self):
|
def test_sales_commission(self):
|
||||||
si = frappe.copy_doc(test_records[0])
|
si = frappe.copy_doc(test_records[0])
|
||||||
item = copy.deepcopy(si.get('items')[0])
|
item = copy.deepcopy(si.get('items')[0])
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
QUnit.module('Sales Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test sales Invoice", function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{customer_address: 'Test1-Billing'},
|
|
||||||
{shipping_address_name: 'Test1-Shipping'},
|
|
||||||
{contact_person: 'Contact 1-Test Customer 1'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// get tax account head details
|
|
||||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
QUnit.module('Accounts');
|
|
||||||
|
|
||||||
QUnit.test("test sales invoice with margin", function(assert) {
|
|
||||||
assert.expect(3);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{selling_price_list: 'Test-Selling-USD'},
|
|
||||||
{currency: 'USD'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'item_code': 'Test Product 4'},
|
|
||||||
{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
|
||||||
{'qty': 1},
|
|
||||||
{'margin_type': 'Percentage'},
|
|
||||||
{'margin_rate_or_amount': 20}
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.items[0].rate_with_margin == 240, "Margin rate correct");
|
|
||||||
assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 240, "Base margin rate correct");
|
|
||||||
assert.ok(cur_frm.doc.total == 240, "Amount correct");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
QUnit.module('Sales Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test sales Invoice with payment", function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{customer_address: 'Test1-Billing'},
|
|
||||||
{shipping_address_name: 'Test1-Shipping'},
|
|
||||||
{contact_person: 'Contact 1-Test Customer 1'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'},
|
|
||||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.tests.click_button('Make'),
|
|
||||||
() => frappe.tests.click_link('Payment'),
|
|
||||||
() => frappe.timeout(0.2),
|
|
||||||
() => { cur_frm.set_value('mode_of_payment','Cash');},
|
|
||||||
() => { cur_frm.set_value('paid_to','Cash - '+frappe.get_abbr(frappe.defaults.get_default('Company')));},
|
|
||||||
() => {cur_frm.set_value('reference_no','TEST1234');},
|
|
||||||
() => {cur_frm.set_value('reference_date',frappe.datetime.add_days(frappe.datetime.nowdate(), 0));},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get payment details
|
|
||||||
assert.ok(cur_frm.doc.paid_amount==590, "Paid Amount Correct");
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,51 +0,0 @@
|
|||||||
QUnit.module('Sales Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test sales Invoice with payment request", function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 5},
|
|
||||||
{'item_code': 'Test Product 1'},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{customer_address: 'Test1-Billing'},
|
|
||||||
{shipping_address_name: 'Test1-Shipping'},
|
|
||||||
{contact_person: 'Contact 1-Test Customer 1'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => frappe.tests.click_button('Close'),
|
|
||||||
() => frappe.tests.click_button('Make'),
|
|
||||||
() => frappe.tests.click_link('Payment Request'),
|
|
||||||
() => frappe.timeout(0.2),
|
|
||||||
() => { cur_frm.set_value('print_format','GST Tax Invoice');},
|
|
||||||
() => { cur_frm.set_value('email_to','test@gmail.com');},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get payment details
|
|
||||||
assert.ok(cur_frm.doc.grand_total==590, "grand total Correct");
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,44 +0,0 @@
|
|||||||
QUnit.module('Sales Invoice');
|
|
||||||
|
|
||||||
QUnit.test("test sales Invoice with serialize item", function(assert) {
|
|
||||||
assert.expect(5);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Invoice', [
|
|
||||||
{customer: 'Test Customer 1'},
|
|
||||||
{items: [
|
|
||||||
[
|
|
||||||
{'qty': 2},
|
|
||||||
{'item_code': 'Test Product 4'},
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{update_stock:1},
|
|
||||||
{customer_address: 'Test1-Billing'},
|
|
||||||
{shipping_address_name: 'Test1-Shipping'},
|
|
||||||
{contact_person: 'Contact 1-Test Customer 1'},
|
|
||||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
|
||||||
{tc_name: 'Test Term 1'},
|
|
||||||
{terms: 'This is Test'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.save(),
|
|
||||||
() => {
|
|
||||||
// get_item_details
|
|
||||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
|
|
||||||
// get tax details
|
|
||||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
|
||||||
// get tax account head details
|
|
||||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
|
||||||
// get batch number
|
|
||||||
assert.ok(cur_frm.doc.items[0].batch_no=='TEST-BATCH-001', " Batch Details correct");
|
|
||||||
// grand_total Calculated
|
|
||||||
assert.ok(cur_frm.doc.grand_total==218, "Grad Total correct");
|
|
||||||
|
|
||||||
},
|
|
||||||
() => frappe.tests.click_button('Submit'),
|
|
||||||
() => frappe.tests.click_button('Yes'),
|
|
||||||
() => frappe.timeout(0.3),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
QUnit.module('Sales Taxes and Charges Template');
|
|
||||||
|
|
||||||
QUnit.test("test sales taxes and charges template", function(assert) {
|
|
||||||
assert.expect(2);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make('Sales Taxes and Charges Template', [
|
|
||||||
{title: "TEST In State GST"},
|
|
||||||
{taxes:[
|
|
||||||
[
|
|
||||||
{charge_type:"On Net Total"},
|
|
||||||
{account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{charge_type:"On Net Total"},
|
|
||||||
{account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.title=='TEST In State GST');
|
|
||||||
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
QUnit.module('Shipping Rule');
|
|
||||||
|
|
||||||
QUnit.test("test Shipping Rule", function(assert) {
|
|
||||||
assert.expect(1);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Shipping Rule", [
|
|
||||||
{label: "Next Day Shipping"},
|
|
||||||
{shipping_rule_type: "Selling"},
|
|
||||||
{calculate_based_on: 'Net Total'},
|
|
||||||
{conditions:[
|
|
||||||
[
|
|
||||||
{from_value:1},
|
|
||||||
{to_value:200},
|
|
||||||
{shipping_amount:100}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{from_value:201},
|
|
||||||
{to_value:2000},
|
|
||||||
{shipping_amount:50}
|
|
||||||
],
|
|
||||||
]},
|
|
||||||
{countries:[
|
|
||||||
[
|
|
||||||
{country:'India'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{account:'Accounts Payable - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
|
|
||||||
{cost_center:'Main - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => {assert.ok(cur_frm.doc.name=='Next Day Shipping');},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
QUnit.module('Shipping Rule');
|
|
||||||
|
|
||||||
QUnit.test("test Shipping Rule", function(assert) {
|
|
||||||
assert.expect(1);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Shipping Rule", [
|
|
||||||
{label: "Two Day Shipping"},
|
|
||||||
{shipping_rule_type: "Buying"},
|
|
||||||
{fixed_shipping_amount: 0},
|
|
||||||
{conditions:[
|
|
||||||
[
|
|
||||||
{from_value:1},
|
|
||||||
{to_value:200},
|
|
||||||
{shipping_amount:100}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{from_value:201},
|
|
||||||
{to_value:3000},
|
|
||||||
{shipping_amount:200}
|
|
||||||
],
|
|
||||||
]},
|
|
||||||
{countries:[
|
|
||||||
[
|
|
||||||
{country:'India'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{account:'Accounts Payable - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
|
|
||||||
{cost_center:'Main - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => {assert.ok(cur_frm.doc.name=='Two Day Shipping');},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// rename this file from _test_[name] to test_[name] to activate
|
|
||||||
// and remove above this line
|
|
||||||
|
|
||||||
QUnit.test("test: Subscription", function (assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
let done = assert.async();
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Subscription
|
|
||||||
() => {
|
|
||||||
return frappe.tests.make("Subscription", [
|
|
||||||
{reference_doctype: 'Sales Invoice'},
|
|
||||||
{reference_document: 'SINV-00004'},
|
|
||||||
{start_date: frappe.datetime.month_start()},
|
|
||||||
{end_date: frappe.datetime.month_end()},
|
|
||||||
{frequency: 'Weekly'}
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
() => cur_frm.savesubmit(),
|
|
||||||
() => frappe.timeout(1),
|
|
||||||
() => frappe.click_button('Yes'),
|
|
||||||
() => frappe.timeout(2),
|
|
||||||
() => {
|
|
||||||
assert.ok(cur_frm.doc.frequency.includes("Weekly"), "Set frequency Weekly");
|
|
||||||
assert.ok(cur_frm.doc.reference_doctype.includes("Sales Invoice"), "Set base doctype Sales Invoice");
|
|
||||||
assert.equal(cur_frm.doc.docstatus, 1, "Submitted subscription");
|
|
||||||
assert.equal(cur_frm.doc.next_schedule_date,
|
|
||||||
frappe.datetime.add_days(frappe.datetime.get_today(), 7), "Set schedule date");
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -117,6 +117,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
|||||||
"label": __("Show Future Payments"),
|
"label": __("Show Future Payments"),
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"show_gl_balance",
|
||||||
|
"label": __("Show GL Balance"),
|
||||||
|
"fieldtype": "Check",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
onload: function(report) {
|
onload: function(report) {
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _, scrub
|
from frappe import _, scrub
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, flt
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
from erpnext.accounts.party import get_partywise_advanced_payment_amount
|
from erpnext.accounts.party import get_partywise_advanced_payment_amount
|
||||||
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
|
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
|
||||||
@ -36,7 +37,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
|||||||
party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
|
party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
|
||||||
self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
|
self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
|
||||||
|
|
||||||
for party, party_dict in self.party_total.items():
|
if self.filters.show_gl_balance:
|
||||||
|
gl_balance_map = get_gl_balance(self.filters.report_date)
|
||||||
|
|
||||||
|
for party, party_dict in iteritems(self.party_total):
|
||||||
if party_dict.outstanding == 0:
|
if party_dict.outstanding == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -55,6 +59,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
|||||||
# but in summary report advance shown in separate column
|
# but in summary report advance shown in separate column
|
||||||
row.paid -= row.advance
|
row.paid -= row.advance
|
||||||
|
|
||||||
|
if self.filters.show_gl_balance:
|
||||||
|
row.gl_balance = gl_balance_map.get(party)
|
||||||
|
row.diff = flt(row.outstanding) - flt(row.gl_balance)
|
||||||
|
|
||||||
self.data.append(row)
|
self.data.append(row)
|
||||||
|
|
||||||
def get_party_total(self, args):
|
def get_party_total(self, args):
|
||||||
@ -114,6 +122,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
|||||||
self.add_column(_(credit_debit_label), fieldname='credit_note')
|
self.add_column(_(credit_debit_label), fieldname='credit_note')
|
||||||
self.add_column(_('Outstanding Amount'), fieldname='outstanding')
|
self.add_column(_('Outstanding Amount'), fieldname='outstanding')
|
||||||
|
|
||||||
|
if self.filters.show_gl_balance:
|
||||||
|
self.add_column(_('GL Balance'), fieldname='gl_balance')
|
||||||
|
self.add_column(_('Difference'), fieldname='diff')
|
||||||
|
|
||||||
self.setup_ageing_columns()
|
self.setup_ageing_columns()
|
||||||
|
|
||||||
if self.party_type == "Customer":
|
if self.party_type == "Customer":
|
||||||
@ -140,3 +152,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
|||||||
|
|
||||||
# Add column for total due amount
|
# Add column for total due amount
|
||||||
self.add_column(label="Total Amount Due", fieldname='total_due')
|
self.add_column(label="Total Amount Due", fieldname='total_due')
|
||||||
|
|
||||||
|
def get_gl_balance(report_date):
|
||||||
|
return frappe._dict(frappe.db.get_all("GL Entry", fields=['party', 'sum(debit - credit)'],
|
||||||
|
filters={'posting_date': ("<=", report_date), 'is_cancelled': 0}, group_by='party', as_list=1))
|
||||||
|
@ -370,7 +370,7 @@ def get_account_heads(root_type, companies, filters):
|
|||||||
accounts = get_accounts(root_type, filters)
|
accounts = get_accounts(root_type, filters)
|
||||||
|
|
||||||
if not accounts:
|
if not accounts:
|
||||||
return None, None
|
return None, None, None
|
||||||
|
|
||||||
accounts = update_parent_account_names(accounts)
|
accounts = update_parent_account_names(accounts)
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Agriculture Analysis Criteria', {
|
|
||||||
refresh: function(frm) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,182 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "field:title",
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2017-12-05 16:37:46.599982",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Title",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "standard",
|
|
||||||
"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": "Standard",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "linked_doctype",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Linked Doctype",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nWater Analysis\nSoil Analysis\nPlant Analysis\nFertilizer\nSoil Texture\nWeather",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-11-04 03:27:36.678832",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Agriculture",
|
|
||||||
"name": "Agriculture Analysis Criteria",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 0,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture User",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"title_field": "",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class AgricultureAnalysisCriteria(Document):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestAgricultureAnalysisCriteria(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Agriculture Task', {
|
|
||||||
refresh: function(frm) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,212 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "AG-TASK-.#####",
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2017-10-26 15:51:19.602452",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "task_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Task Name",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "start_day",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Start Day",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "end_day",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "End Day",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Ignore holidays",
|
|
||||||
"fieldname": "holiday_management",
|
|
||||||
"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": "Holiday Management",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Ignore holidays\nPrevious Business Day\nNext Business Day",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Low",
|
|
||||||
"fieldname": "priority",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Priority",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Low\nMedium\nHigh\nUrgent",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-11-04 03:28:08.679157",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Agriculture",
|
|
||||||
"name": "Agriculture Task",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class AgricultureTask(Document):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestAgricultureTask(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.provide("erpnext.crop");
|
|
||||||
|
|
||||||
frappe.ui.form.on('Crop', {
|
|
||||||
refresh: (frm) => {
|
|
||||||
frm.fields_dict.materials_required.grid.set_column_disp('bom_no', false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
frappe.ui.form.on("BOM Item", {
|
|
||||||
item_code: (frm, cdt, cdn) => {
|
|
||||||
erpnext.crop.update_item_rate_uom(frm, cdt, cdn);
|
|
||||||
},
|
|
||||||
qty: (frm, cdt, cdn) => {
|
|
||||||
erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
|
|
||||||
},
|
|
||||||
rate: (frm, cdt, cdn) => {
|
|
||||||
erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
erpnext.crop.update_item_rate_uom = function(frm, cdt, cdn) {
|
|
||||||
let material_list = ['materials_required', 'produce', 'byproducts'];
|
|
||||||
material_list.forEach((material) => {
|
|
||||||
frm.doc[material].forEach((item, index) => {
|
|
||||||
if (item.name == cdn && item.item_code){
|
|
||||||
frappe.call({
|
|
||||||
method:'erpnext.agriculture.doctype.crop.crop.get_item_details',
|
|
||||||
args: {
|
|
||||||
item_code: item.item_code
|
|
||||||
},
|
|
||||||
callback: (r) => {
|
|
||||||
frappe.model.set_value('BOM Item', item.name, 'uom', r.message.uom);
|
|
||||||
frappe.model.set_value('BOM Item', item.name, 'rate', r.message.rate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
erpnext.crop.update_item_qty_amount = function(frm, cdt, cdn) {
|
|
||||||
let material_list = ['materials_required', 'produce', 'byproducts'];
|
|
||||||
material_list.forEach((material) => {
|
|
||||||
frm.doc[material].forEach((item, index) => {
|
|
||||||
if (item.name == cdn){
|
|
||||||
if (!frappe.model.get_value('BOM Item', item.name, 'qty'))
|
|
||||||
frappe.model.set_value('BOM Item', item.name, 'qty', 1);
|
|
||||||
frappe.model.set_value('BOM Item', item.name, 'amount', item.qty * item.rate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class Crop(Document):
|
|
||||||
def validate(self):
|
|
||||||
self.validate_crop_tasks()
|
|
||||||
|
|
||||||
def validate_crop_tasks(self):
|
|
||||||
for task in self.agriculture_task:
|
|
||||||
if task.start_day > task.end_day:
|
|
||||||
frappe.throw(_("Start day is greater than end day in task '{0}'").format(task.task_name))
|
|
||||||
|
|
||||||
# Verify that the crop period is correct
|
|
||||||
max_crop_period = max([task.end_day for task in self.agriculture_task])
|
|
||||||
self.period = max(self.period, max_crop_period)
|
|
||||||
|
|
||||||
# Sort the crop tasks based on start days,
|
|
||||||
# maintaining the order for same-day tasks
|
|
||||||
self.agriculture_task.sort(key=lambda task: task.start_day)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_item_details(item_code):
|
|
||||||
item = frappe.get_doc('Item', item_code)
|
|
||||||
return {"uom": item.stock_uom, "rate": item.valuation_rate}
|
|
@ -1,12 +0,0 @@
|
|||||||
from frappe import _
|
|
||||||
|
|
||||||
|
|
||||||
def get_data():
|
|
||||||
return {
|
|
||||||
'transactions': [
|
|
||||||
{
|
|
||||||
'label': _('Crop Cycle'),
|
|
||||||
'items': ['Crop Cycle']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// rename this file from _test_[name] to test_[name] to activate
|
|
||||||
// and remove above this line
|
|
||||||
|
|
||||||
QUnit.test("test: Crop", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
// number of asserts
|
|
||||||
assert.expect(2);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Item
|
|
||||||
() => frappe.tests.make('Item', [
|
|
||||||
// values to be set
|
|
||||||
{item_code: 'Basil Seeds'},
|
|
||||||
{item_name: 'Basil Seeds'},
|
|
||||||
{item_group: 'Seed'}
|
|
||||||
]),
|
|
||||||
// insert a new Item
|
|
||||||
() => frappe.tests.make('Item', [
|
|
||||||
// values to be set
|
|
||||||
{item_code: 'Twigs'},
|
|
||||||
{item_name: 'Twigs'},
|
|
||||||
{item_group: 'By-product'}
|
|
||||||
]),
|
|
||||||
// insert a new Item
|
|
||||||
() => frappe.tests.make('Item', [
|
|
||||||
// values to be set
|
|
||||||
{item_code: 'Basil Leaves'},
|
|
||||||
{item_name: 'Basil Leaves'},
|
|
||||||
{item_group: 'Produce'}
|
|
||||||
]),
|
|
||||||
// insert a new Crop
|
|
||||||
() => frappe.tests.make('Crop', [
|
|
||||||
// values to be set
|
|
||||||
{title: 'Basil from seed'},
|
|
||||||
{crop_name: 'Basil'},
|
|
||||||
{scientific_name: 'Ocimum basilicum'},
|
|
||||||
{materials_required: [
|
|
||||||
[
|
|
||||||
{item_code: 'Basil Seeds'},
|
|
||||||
{qty: '25'},
|
|
||||||
{uom: 'Nos'},
|
|
||||||
{rate: '1'}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{item_code: 'Urea'},
|
|
||||||
{qty: '5'},
|
|
||||||
{uom: 'Kg'},
|
|
||||||
{rate: '10'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{byproducts: [
|
|
||||||
[
|
|
||||||
{item_code: 'Twigs'},
|
|
||||||
{qty: '25'},
|
|
||||||
{uom: 'Nos'},
|
|
||||||
{rate: '1'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{produce: [
|
|
||||||
[
|
|
||||||
{item_code: 'Basil Leaves'},
|
|
||||||
{qty: '100'},
|
|
||||||
{uom: 'Nos'},
|
|
||||||
{rate: '1'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{agriculture_task: [
|
|
||||||
[
|
|
||||||
{task_name: "Plough the field"},
|
|
||||||
{start_day: 1},
|
|
||||||
{end_day: 1},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "Plant the seeds"},
|
|
||||||
{start_day: 2},
|
|
||||||
{end_day: 3},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "Water the field"},
|
|
||||||
{start_day: 4},
|
|
||||||
{end_day: 4},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "First harvest"},
|
|
||||||
{start_day: 8},
|
|
||||||
{end_day: 8},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "Add the fertilizer"},
|
|
||||||
{start_day: 10},
|
|
||||||
{end_day: 12},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "Final cut"},
|
|
||||||
{start_day: 15},
|
|
||||||
{end_day: 15},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]),
|
|
||||||
// agriculture task list
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.name, 'Basil from seed');
|
|
||||||
assert.equal(cur_frm.doc.period, 15);
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
@ -1,13 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
test_dependencies = ["Fertilizer"]
|
|
||||||
|
|
||||||
class TestCrop(unittest.TestCase):
|
|
||||||
def test_crop_period(self):
|
|
||||||
basil = frappe.get_doc('Crop', 'Basil from seed')
|
|
||||||
self.assertEqual(basil.period, 15)
|
|
@ -1,80 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"doctype": "Item",
|
|
||||||
"item_code": "Basil Seeds",
|
|
||||||
"item_name": "Basil Seeds",
|
|
||||||
"item_group": "Seed"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Item",
|
|
||||||
"item_code": "Twigs",
|
|
||||||
"item_name": "Twigs",
|
|
||||||
"item_group": "By-product"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Item",
|
|
||||||
"item_code": "Basil Leaves",
|
|
||||||
"item_name": "Basil Leaves",
|
|
||||||
"item_group": "Produce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Crop",
|
|
||||||
"title": "Basil from seed",
|
|
||||||
"crop_name": "Basil",
|
|
||||||
"scientific_name": "Ocimum basilicum",
|
|
||||||
"materials_required": [{
|
|
||||||
"item_code": "Basil Seeds",
|
|
||||||
"qty": "25",
|
|
||||||
"uom": "Nos",
|
|
||||||
"rate": "1"
|
|
||||||
}, {
|
|
||||||
"item_code": "Urea",
|
|
||||||
"qty": "5",
|
|
||||||
"uom": "Kg",
|
|
||||||
"rate": "10"
|
|
||||||
}],
|
|
||||||
"byproducts": [{
|
|
||||||
"item_code": "Twigs",
|
|
||||||
"qty": "25",
|
|
||||||
"uom": "Nos",
|
|
||||||
"rate": "1"
|
|
||||||
}],
|
|
||||||
"produce": [{
|
|
||||||
"item_code": "Basil Leaves",
|
|
||||||
"qty": "100",
|
|
||||||
"uom": "Nos",
|
|
||||||
"rate": "1"
|
|
||||||
}],
|
|
||||||
"agriculture_task": [{
|
|
||||||
"task_name": "Plough the field",
|
|
||||||
"start_day": 1,
|
|
||||||
"end_day": 1,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "Plant the seeds",
|
|
||||||
"start_day": 2,
|
|
||||||
"end_day": 3,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "Water the field",
|
|
||||||
"start_day": 4,
|
|
||||||
"end_day": 4,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "First harvest",
|
|
||||||
"start_day": 8,
|
|
||||||
"end_day": 8,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "Add the fertilizer",
|
|
||||||
"start_day": 10,
|
|
||||||
"end_day": 12,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "Final cut",
|
|
||||||
"start_day": 15,
|
|
||||||
"end_day": 15,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Crop Cycle', {
|
|
||||||
refresh: (frm) => {
|
|
||||||
if (!frm.doc.__islocal)
|
|
||||||
frm.add_custom_button(__('Reload Linked Analysis'), () => frm.call("reload_linked_analysis"));
|
|
||||||
|
|
||||||
frappe.realtime.on("List of Linked Docs", (output) => {
|
|
||||||
let analysis_doctypes = ['Soil Texture', 'Plant Analysis', 'Soil Analysis'];
|
|
||||||
let analysis_doctypes_docs = ['soil_texture', 'plant_analysis', 'soil_analysis'];
|
|
||||||
let obj_to_append = {soil_analysis: [], soil_texture: [], plant_analysis: []};
|
|
||||||
output['Location'].forEach( (land_doc) => {
|
|
||||||
analysis_doctypes.forEach( (doctype) => {
|
|
||||||
output[doctype].forEach( (analysis_doc) => {
|
|
||||||
let point_to_be_tested = JSON.parse(analysis_doc.location).features[0].geometry.coordinates;
|
|
||||||
let poly_of_land = JSON.parse(land_doc.location).features[0].geometry.coordinates[0];
|
|
||||||
if (is_in_land_unit(point_to_be_tested, poly_of_land)){
|
|
||||||
obj_to_append[analysis_doctypes_docs[analysis_doctypes.indexOf(doctype)]].push(analysis_doc.name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
frm.call('append_to_child', {
|
|
||||||
obj_to_append: obj_to_append
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function is_in_land_unit(point, vs) {
|
|
||||||
// ray-casting algorithm based on
|
|
||||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
|
||||||
|
|
||||||
var x = point[0], y = point[1];
|
|
||||||
|
|
||||||
var inside = false;
|
|
||||||
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
|
|
||||||
var xi = vs[i][0], yi = vs[i][1];
|
|
||||||
var xj = vs[j][0], yj = vs[j][1];
|
|
||||||
|
|
||||||
var intersect = ((yi > y) != (yj > y))
|
|
||||||
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
|
||||||
if (intersect) inside = !inside;
|
|
||||||
}
|
|
||||||
|
|
||||||
return inside;
|
|
||||||
};
|
|
@ -1,904 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "field:title",
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2017-11-02 03:09:35.449880",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Title",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "crop",
|
|
||||||
"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": "Crop",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Crop",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "column_break_3",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Linked Location",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "A link to all the Locations in which the Crop is growing",
|
|
||||||
"fieldname": "linked_location",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Linked Location",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Linked Location",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_3",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:!doc.__islocal",
|
|
||||||
"fieldname": "project",
|
|
||||||
"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": "Project",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Project",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_12",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "This will be day 1 of the crop cycle",
|
|
||||||
"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,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_from": "project.expected_end_date",
|
|
||||||
"fieldname": "end_date",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "End Date",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_7",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "iso_8601_standard",
|
|
||||||
"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": "ISO 8601 standard",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_5",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "cycle_type",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Cycle Type",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Yearly\nLess than a year",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_12",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "The minimum length between each plant in the field for optimum growth",
|
|
||||||
"fetch_from": "crop.crop_spacing",
|
|
||||||
"fieldname": "crop_spacing",
|
|
||||||
"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": "Crop Spacing",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "crop_spacing_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": "Crop Spacing UOM",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "UOM",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_11",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "The minimum distance between rows of plants for optimum growth",
|
|
||||||
"fetch_from": "crop.row_spacing",
|
|
||||||
"fieldname": "row_spacing",
|
|
||||||
"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": "Row Spacing",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "row_spacing_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": "Row Spacing UOM",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "UOM",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:!doc.__islocal",
|
|
||||||
"description": "List of diseases detected on the field. When selected it'll automatically add a list of tasks to deal with the disease ",
|
|
||||||
"fieldname": "section_break_14",
|
|
||||||
"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": "Detected Diseases",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "detected_disease",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Detected Disease",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Detected Disease",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 1,
|
|
||||||
"collapsible_depends_on": "eval:false",
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_22",
|
|
||||||
"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": "LInked Analysis",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "soil_texture",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Soil Texture",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Linked Soil Texture",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "soil_analysis",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Soil Analysis",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Linked Soil Analysis",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "plant_analysis",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Plant Analysis",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Linked Plant Analysis",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-11-04 03:31:47.602312",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Agriculture",
|
|
||||||
"name": "Crop Cycle",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 0,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture User",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,126 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
import ast
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
|
||||||
from frappe.utils import add_days
|
|
||||||
|
|
||||||
|
|
||||||
class CropCycle(Document):
|
|
||||||
def validate(self):
|
|
||||||
self.set_missing_values()
|
|
||||||
|
|
||||||
def after_insert(self):
|
|
||||||
self.create_crop_cycle_project()
|
|
||||||
self.create_tasks_for_diseases()
|
|
||||||
|
|
||||||
def on_update(self):
|
|
||||||
self.create_tasks_for_diseases()
|
|
||||||
|
|
||||||
def set_missing_values(self):
|
|
||||||
crop = frappe.get_doc('Crop', self.crop)
|
|
||||||
|
|
||||||
if not self.crop_spacing_uom:
|
|
||||||
self.crop_spacing_uom = crop.crop_spacing_uom
|
|
||||||
|
|
||||||
if not self.row_spacing_uom:
|
|
||||||
self.row_spacing_uom = crop.row_spacing_uom
|
|
||||||
|
|
||||||
def create_crop_cycle_project(self):
|
|
||||||
crop = frappe.get_doc('Crop', self.crop)
|
|
||||||
|
|
||||||
self.project = self.create_project(crop.period, crop.agriculture_task)
|
|
||||||
self.create_task(crop.agriculture_task, self.project, self.start_date)
|
|
||||||
|
|
||||||
def create_tasks_for_diseases(self):
|
|
||||||
for disease in self.detected_disease:
|
|
||||||
if not disease.tasks_created:
|
|
||||||
self.import_disease_tasks(disease.disease, disease.start_date)
|
|
||||||
disease.tasks_created = True
|
|
||||||
|
|
||||||
frappe.msgprint(_("Tasks have been created for managing the {0} disease (on row {1})").format(disease.disease, disease.idx))
|
|
||||||
|
|
||||||
def import_disease_tasks(self, disease, start_date):
|
|
||||||
disease_doc = frappe.get_doc('Disease', disease)
|
|
||||||
self.create_task(disease_doc.treatment_task, self.project, start_date)
|
|
||||||
|
|
||||||
def create_project(self, period, crop_tasks):
|
|
||||||
project = frappe.get_doc({
|
|
||||||
"doctype": "Project",
|
|
||||||
"project_name": self.title,
|
|
||||||
"expected_start_date": self.start_date,
|
|
||||||
"expected_end_date": add_days(self.start_date, period - 1)
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
return project.name
|
|
||||||
|
|
||||||
def create_task(self, crop_tasks, project_name, start_date):
|
|
||||||
for crop_task in crop_tasks:
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Task",
|
|
||||||
"subject": crop_task.get("task_name"),
|
|
||||||
"priority": crop_task.get("priority"),
|
|
||||||
"project": project_name,
|
|
||||||
"exp_start_date": add_days(start_date, crop_task.get("start_day") - 1),
|
|
||||||
"exp_end_date": add_days(start_date, crop_task.get("end_day") - 1)
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def reload_linked_analysis(self):
|
|
||||||
linked_doctypes = ['Soil Texture', 'Soil Analysis', 'Plant Analysis']
|
|
||||||
required_fields = ['location', 'name', 'collection_datetime']
|
|
||||||
output = {}
|
|
||||||
|
|
||||||
for doctype in linked_doctypes:
|
|
||||||
output[doctype] = frappe.get_all(doctype, fields=required_fields)
|
|
||||||
|
|
||||||
output['Location'] = []
|
|
||||||
|
|
||||||
for location in self.linked_location:
|
|
||||||
output['Location'].append(frappe.get_doc('Location', location.location))
|
|
||||||
|
|
||||||
frappe.publish_realtime("List of Linked Docs",
|
|
||||||
output, user=frappe.session.user)
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def append_to_child(self, obj_to_append):
|
|
||||||
for doctype in obj_to_append:
|
|
||||||
for doc_name in set(obj_to_append[doctype]):
|
|
||||||
self.append(doctype, {doctype: doc_name})
|
|
||||||
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
|
|
||||||
def get_coordinates(doc):
|
|
||||||
return ast.literal_eval(doc.location).get('features')[0].get('geometry').get('coordinates')
|
|
||||||
|
|
||||||
|
|
||||||
def get_geometry_type(doc):
|
|
||||||
return ast.literal_eval(doc.location).get('features')[0].get('geometry').get('type')
|
|
||||||
|
|
||||||
|
|
||||||
def is_in_location(point, vs):
|
|
||||||
x, y = point
|
|
||||||
inside = False
|
|
||||||
|
|
||||||
j = len(vs) - 1
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while i < len(vs):
|
|
||||||
xi, yi = vs[i]
|
|
||||||
xj, yj = vs[j]
|
|
||||||
|
|
||||||
intersect = ((yi > y) != (yj > y)) and (
|
|
||||||
x < (xj - xi) * (y - yi) / (yj - yi) + xi)
|
|
||||||
|
|
||||||
if intersect:
|
|
||||||
inside = not inside
|
|
||||||
|
|
||||||
i = j
|
|
||||||
j += 1
|
|
||||||
|
|
||||||
return inside
|
|
@ -1,34 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// rename this file from _test_[name] to test_[name] to activate
|
|
||||||
// and remove above this line
|
|
||||||
|
|
||||||
QUnit.test("test: Crop Cycle", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
// number of asserts
|
|
||||||
assert.expect(1);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Crop Cycle
|
|
||||||
() => frappe.tests.make('Crop Cycle', [
|
|
||||||
// values to be set
|
|
||||||
{title: 'Basil from seed 2017'},
|
|
||||||
{detected_disease: [
|
|
||||||
[
|
|
||||||
{start_date: '2017-11-21'},
|
|
||||||
{disease: 'Aphids'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{linked_land_unit: [
|
|
||||||
[
|
|
||||||
{land_unit: 'Basil Farm'}
|
|
||||||
]
|
|
||||||
]},
|
|
||||||
{crop: 'Basil from seed'},
|
|
||||||
{start_date: '2017-11-11'},
|
|
||||||
{cycle_type: 'Less than a year'}
|
|
||||||
]),
|
|
||||||
() => assert.equal(cur_frm.doc.name, 'Basil from seed 2017'),
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
});
|
|
@ -1,72 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe.utils import datetime
|
|
||||||
|
|
||||||
test_dependencies = ["Crop", "Fertilizer", "Location", "Disease"]
|
|
||||||
|
|
||||||
|
|
||||||
class TestCropCycle(unittest.TestCase):
|
|
||||||
def test_crop_cycle_creation(self):
|
|
||||||
cycle = frappe.get_doc('Crop Cycle', 'Basil from seed 2017')
|
|
||||||
self.assertTrue(frappe.db.exists('Crop Cycle', 'Basil from seed 2017'))
|
|
||||||
|
|
||||||
# check if the tasks were created
|
|
||||||
self.assertEqual(check_task_creation(), True)
|
|
||||||
self.assertEqual(check_project_creation(), True)
|
|
||||||
|
|
||||||
|
|
||||||
def check_task_creation():
|
|
||||||
all_task_dict = {
|
|
||||||
"Survey and find the aphid locations": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 21),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 22)
|
|
||||||
},
|
|
||||||
"Apply Pesticides": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 23),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 23)
|
|
||||||
},
|
|
||||||
"Plough the field": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 11),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 11)
|
|
||||||
},
|
|
||||||
"Plant the seeds": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 12),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 13)
|
|
||||||
},
|
|
||||||
"Water the field": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 14),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 14)
|
|
||||||
},
|
|
||||||
"First harvest": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 18),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 18)
|
|
||||||
},
|
|
||||||
"Add the fertilizer": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 20),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 22)
|
|
||||||
},
|
|
||||||
"Final cut": {
|
|
||||||
"exp_start_date": datetime.date(2017, 11, 25),
|
|
||||||
"exp_end_date": datetime.date(2017, 11, 25)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
all_tasks = frappe.get_all('Task')
|
|
||||||
|
|
||||||
for task in all_tasks:
|
|
||||||
sample_task = frappe.get_doc('Task', task.name)
|
|
||||||
|
|
||||||
if sample_task.subject in list(all_task_dict):
|
|
||||||
if sample_task.exp_start_date != all_task_dict[sample_task.subject]['exp_start_date'] or sample_task.exp_end_date != all_task_dict[sample_task.subject]['exp_end_date']:
|
|
||||||
return False
|
|
||||||
all_task_dict.pop(sample_task.subject)
|
|
||||||
|
|
||||||
return True if not all_task_dict else False
|
|
||||||
|
|
||||||
|
|
||||||
def check_project_creation():
|
|
||||||
return True if frappe.db.exists('Project', {'project_name': 'Basil from seed 2017'}) else False
|
|
@ -1,15 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"doctype": "Crop Cycle",
|
|
||||||
"title": "Basil from seed 2017",
|
|
||||||
"linked_location": [{
|
|
||||||
"location": "Basil Farm"
|
|
||||||
}],
|
|
||||||
"crop": "Basil from seed",
|
|
||||||
"start_date": "2017-11-11",
|
|
||||||
"detected_disease": [{
|
|
||||||
"disease": "Aphids",
|
|
||||||
"start_date": "2017-11-21"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2017-11-20 17:31:30.772779",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "disease",
|
|
||||||
"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": "Disease",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Disease",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "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,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "tasks_created",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"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": "Tasks Created",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-11-04 03:27:47.463994",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Agriculture",
|
|
||||||
"name": "Detected Disease",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class DetectedDisease(Document):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Disease', {
|
|
||||||
refresh: function(frm) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,308 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "field:common_name",
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2017-11-20 17:16:54.496355",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "common_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Common Name",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "scientific_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Scientific Name",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_3",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "treatment_task",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Treatment Task",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Agriculture Task",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "treatment_period",
|
|
||||||
"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": "Treatment Period",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_2",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Treatment Task",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "description",
|
|
||||||
"fieldtype": "Long Text",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Description",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-11-04 03:27:25.076490",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Agriculture",
|
|
||||||
"name": "Disease",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 0,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Agriculture User",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class Disease(Document):
|
|
||||||
def validate(self):
|
|
||||||
max_period = 0
|
|
||||||
for task in self.treatment_task:
|
|
||||||
# validate start_day is not > end_day
|
|
||||||
if task.start_day > task.end_day:
|
|
||||||
frappe.throw(_("Start day is greater than end day in task '{0}'").format(task.task_name))
|
|
||||||
# to calculate the period of the Crop Cycle
|
|
||||||
if task.end_day > max_period: max_period = task.end_day
|
|
||||||
self.treatment_period = max_period
|
|
@ -1,38 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// rename this file from _test_[name] to test_[name] to activate
|
|
||||||
// and remove above this line
|
|
||||||
|
|
||||||
QUnit.test("test: Disease", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
// number of asserts
|
|
||||||
assert.expect(1);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Disease
|
|
||||||
() => frappe.tests.make('Disease', [
|
|
||||||
// values to be set
|
|
||||||
{common_name: 'Aphids'},
|
|
||||||
{scientific_name: 'Aphidoidea'},
|
|
||||||
{treatment_task: [
|
|
||||||
[
|
|
||||||
{task_name: "Survey and find the aphid locations"},
|
|
||||||
{start_day: 1},
|
|
||||||
{end_day: 2},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{task_name: "Apply Pesticides"},
|
|
||||||
{start_day: 3},
|
|
||||||
{end_day: 3},
|
|
||||||
{holiday_management: "Ignore holidays"}
|
|
||||||
]
|
|
||||||
]}
|
|
||||||
]),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.treatment_period, 3);
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
@ -1,12 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
|
|
||||||
class TestDisease(unittest.TestCase):
|
|
||||||
def test_treatment_period(self):
|
|
||||||
disease = frappe.get_doc('Disease', 'Aphids')
|
|
||||||
self.assertEqual(disease.treatment_period, 3)
|
|
@ -1,18 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"doctype": "Disease",
|
|
||||||
"common_name": "Aphids",
|
|
||||||
"scientific_name": "Aphidoidea",
|
|
||||||
"treatment_task": [{
|
|
||||||
"task_name": "Survey and find the aphid locations",
|
|
||||||
"start_day": 1,
|
|
||||||
"end_day": 2,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}, {
|
|
||||||
"task_name": "Apply Pesticides",
|
|
||||||
"start_day": 3,
|
|
||||||
"end_day": 3,
|
|
||||||
"holiday_management": "Ignore holidays"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user