Compare commits

..

74 Commits

Author SHA1 Message Date
mbauskar
a8406e1544 Merge branch 'develop' 2017-07-11 13:02:15 +05:30
mbauskar
b2aa867b70 bumped to version 8.3.6 2017-07-11 13:32:14 +06:00
Makarand Bauskar
30f2bcbccc [hotfix] allow only 5 character in company_abbr field in setup wizard (#9779) 2017-07-11 12:36:57 +05:30
Prateeksha Singh
7d885432eb [wiz] add user slide, enforce first entry, static labels (#9744) 2017-07-11 12:36:34 +05:30
Nabin Hait
3b5f774144 Merge pull request #9410 from manassolanki/patch-company
Patch for the PR 8754, fixes #9011
2017-07-11 11:35:29 +05:30
Nabin Hait
3a200bbc44 Update create_address_doc_from_address_field_in_company.py 2017-07-11 11:34:27 +05:30
Nabin Hait
2bedca04ae Merge pull request #9750 from rohitwaghchaure/taxable_amount_issue
[Fix] Taxable amount in tax breakup showing wrong value for duplicate items in the invoice
2017-07-11 11:16:56 +05:30
Manas Solanki
1a0536bff4 changes as per review 2017-07-11 11:16:16 +05:30
Manas Solanki
cdba021802 patch for removing the address field from company and creating address doc, fixes #9011 2017-07-11 11:16:16 +05:30
Shivam Mishra
3fe5ecc611 Added Lead fixture, Added test for Lead, Opportunity (#9607)
* Added fixtures for Address and Contact

* Fixed formatting errors

* Added Test for terms, Added Tax and Terms fixture

* Add tests for tax

* Added Test for Print Format
2017-07-11 10:33:07 +05:30
Rohit Waghchaure
296fbfeaac [Fix] Taxable amount in tax breakup showing wrong value for duplicate items in the invoice 2017-07-10 23:06:49 +05:30
Rushabh Mehta
4a7b4efbec [tests] update travis.yml to run ui-tests (#9748)
* [tests] update travis.yml to run ui-tests

* [tests] update travis.yml to run ui-tests

* [test] fix item_group.py

* [test] fix item_group.py

* [check] daily work summary fails?

* [check] daily work summary fails?

* [check] daily work summary fails?

* [check] daily work summary fails?

* [check] daily work summary fails?

* [check] daily work summary fails?

* [check] no scheduled jobs for tests

* [check] daily work summary fails?

* [check] daily work summary fails?
2017-07-10 23:00:01 +05:30
Nabin Hait
f7d2a59c18 Merge pull request #9538 from sagarvora/fix-bom-issue
[minor] fix bom price resetting on validation
2017-07-10 20:41:16 +05:30
Nabin Hait
0ac8542eaa Merge pull request #9772 from tundebabzy/issue-9595
Wrong Exchange Rate when making payment against Journal Entry (#9595)
2017-07-10 19:12:48 +05:30
Nabin Hait
c8b6d3badb Merge pull request #9713 from manassolanki/stud-dashb
changes in the student dashboard
2017-07-10 19:10:57 +05:30
Nabin Hait
cdf4320b3b Merge pull request #9673 from rohitwaghchaure/serial_no_sales_return_issue
Remove sales invoice from serial number while making sales return entery using delivery note
2017-07-10 19:04:30 +05:30
Nabin Hait
5b2d3222f3 Merge pull request #9710 from rohitwaghchaure/sales_invoice_dn_link_revert
Revert sales invoice dn link issue
2017-07-10 18:47:38 +05:30
Manas Solanki
5d202ca31a change in the student type 2017-07-10 18:40:53 +05:30
Nabin Hait
7088db9e1f Merge pull request #9773 from mbauskar/docs
[docs] corrected the filename from sms_setting2 -> sms_settings2
2017-07-10 18:17:28 +05:30
Nabin Hait
ec344ffa96 Merge pull request #9761 from mbauskar/depends-on
[minor] fixed depends on for stock entry expense_account and purchase receipt item's cost_center field
2017-07-10 18:16:15 +05:30
mbauskar
a52e726b6b [docs] corrected the filename from sms_setting2 -> sms_settings2 2017-07-10 18:11:32 +05:30
Nabin Hait
cf82c3828e Merge pull request #9769 from manassolanki/payment-entry
frappe call if posting date is defined
2017-07-10 17:57:26 +05:30
Nabin Hait
6fcfbaa1f9 Merge pull request #9766 from nabinhait/migration_fixes
minor fixes while upgrading an old instance
2017-07-10 17:45:25 +05:30
Nabin Hait
a6c733d06c Merge pull request #9753 from rohitwaghchaure/budget_cost_center_issue
[Fix] Budget against the field in the validation message
2017-07-10 17:45:02 +05:30
tunde
46ef26df71 treat use case where Journal entry is contained in outstanding_invoices in get_outstanding_reference_documents function 2017-07-10 13:05:29 +01:00
Manas Solanki
99d571a786 frappe call if posting date is defined 2017-07-10 17:33:27 +05:30
Rohit Waghchaure
e3ae600277 [Fix] Budget against the field in the validation message 2017-07-10 17:06:54 +05:30
Nabin Hait
dd7a723214 minor fixes while upgrading an old instance 2017-07-10 16:41:59 +05:30
mbauskar
ccaf36a00f [minor] fixed depends on for stock entry expense_account and purchase receipt item's cost_center field 2017-07-10 16:24:24 +05:30
Manas Solanki
101a021f7b added student type in program enrollment and changes in the student dashboard 2017-07-10 16:21:44 +05:30
Nabin Hait
68ed0488a3 Merge pull request #9757 from mbauskar/breadcrumb-fixes
[hotfix] check if the item group exist or not
2017-07-10 15:32:52 +05:30
mbauskar
75a233b472 [hotfix] check if the item group exist or not 2017-07-10 14:36:42 +05:30
Nabin Hait
5a174d61bc Merge pull request #9754 from creamdory/develop
Added Quotation as Standard Sidebar Menu
2017-07-10 14:13:35 +05:30
creamdory
7a2815299e Added Quotation as Standard Sidebar Menu 2017-07-10 16:09:03 +08:00
Manas Solanki
195d2b577f add few details in the student log (#9670) 2017-07-10 12:29:46 +05:30
Britlog
8c85562ceb Breadcrumbs management (#9544) 2017-07-10 12:14:05 +05:30
Manas Solanki
77aa4762b8 don't request another ajax call if one is pending (#9620) 2017-07-10 12:12:16 +05:30
Nabin Hait
35ecab6a52 Merge branch 'develop' 2017-07-08 13:55:41 +05:30
Nabin Hait
097da8cc89 bumped to version 8.3.5 2017-07-08 14:25:41 +06:00
Nabin Hait
1d52a4df22 Merge pull request #9732 from adityaduggal/gstin_NA
First 2 digit validation would disregard NA values
2017-07-08 13:52:35 +05:30
Nabin Hait
cd61a20fb4 Update utils.py 2017-07-08 13:52:13 +05:30
Nabin Hait
8f7eb358b8 Merge pull request #9730 from nabinhait/prod_fix
Finish prod order when skipped material transfer
2017-07-08 13:50:52 +05:30
Aditya Duggal
0e285265b1 First 2 digit validation would disregard NA values 2017-07-08 13:35:01 +05:30
Nabin Hait
b866fcf14f Finish prod order when skipped material transfer 2017-07-08 12:57:13 +05:30
Manas Solanki
3d190a15ab changes in the student dashboard 2017-07-07 17:29:29 +05:30
mbauskar
ab59e4769b Merge branch 'develop' 2017-07-07 17:12:37 +05:30
mbauskar
7b5ca3e494 bumped to version 8.3.4 2017-07-07 17:42:36 +06:00
Rohit Waghchaure
8f2c8f6e9d Revert sales invoice dn link issue 2017-07-07 17:07:59 +05:30
Nabin Hait
76c5924cbe Merge pull request #9699 from manassolanki/productn
frappe call only when there is item in production order
2017-07-07 15:48:37 +05:30
Nabin Hait
6eb55042d8 Merge pull request #9704 from rohitwaghchaure/serial_no_not_found_issue
Fixed the issue Serial No serial no not found
2017-07-07 15:47:25 +05:30
Rohit Waghchaure
9589527784 Fixed the issue Serial No serial no not found 2017-07-07 15:34:28 +05:30
Nabin Hait
dba3f0048b Merge pull request #9702 from mbauskar/installation-note
[hotfix] fixed the customer address set filter on Installation Note
2017-07-07 15:28:23 +05:30
mbauskar
3f6a5b2539 [hotfix] fixed the customer address set filter on Installation Note 2017-07-07 15:24:01 +05:30
Manas Solanki
cf7f72e586 frappe call only when there is item 2017-07-07 15:09:57 +05:30
mbauskar
74d07c695b Merge branch 'develop' 2017-07-07 14:06:45 +05:30
mbauskar
5cf3868d03 bumped to version 8.3.3 2017-07-07 14:36:45 +06:00
Nabin Hait
1b36336fc3 Added new option in invoice_copy, made state_number read_only (#9695)
* Added new option in invoice_copy, made state_number read_only

* removed the trailing whitespace
2017-07-07 14:05:33 +05:30
mbauskar
3f3ac5652f resolved merge conflicts 2017-07-07 13:42:54 +05:30
mbauskar
7b8d366e3a bumped to version 8.3.2 2017-07-07 14:11:45 +06:00
rohitwaghchaure
a29442d6bf [Fix] Setup wizard translation (#9693) 2017-07-07 13:40:13 +05:30
rohitwaghchaure
bbe16c80ff [Fix] Setup wizard translation issue (#9692) 2017-07-07 13:27:15 +05:30
Nabin Hait
4e21f11864 Merge pull request #9690 from rmehta/additional-discount-fix
[fix] reset flag after promise
2017-07-07 13:26:14 +05:30
Rushabh Mehta
19d52dc503 [fix] remove extra flag 2017-07-07 13:23:23 +05:30
Nabin Hait
701f7cccbf Merge pull request #9688 from nabinhait/pos_fixes
Fixed itemised tax calc to fix pos loading
2017-07-07 13:18:14 +05:30
Nabin Hait
8b486b0f28 Fixed state code of WB and allowed invoice_copy to edit after submit 2017-07-07 13:14:25 +05:30
Rushabh Mehta
6705ab3eaf [fix] discount setting multiple times 2017-07-07 13:14:08 +05:30
Rushabh Mehta
233a19a373 [fix] reset flag after promise 2017-07-07 13:06:29 +05:30
Nabin Hait
fbb5945ff3 Fixed itemised tax calc to fix pos loading 2017-07-07 12:58:22 +05:30
Nabin Hait
7773ee8960 Sales invoice dashboard, multiple letter head in report and email alert docs 2017-07-07 12:49:05 +05:30
Nabin Hait
8ad168ac67 Fixed merge conflict 2017-07-06 23:18:00 +05:30
Nabin Hait
3e9520b276 bumped to version 8.2.5 2017-07-06 23:46:40 +06:00
Rohit Waghchaure
934e69fe0b Remove sales invoice from serial number while making sales return entery using delivery note 2017-07-06 18:19:18 +05:30
rohitwaghchaure
bedb486c55 [Fix] Multi letter head showing in the print (#9644) 2017-07-06 14:50:38 +05:30
Sagar Vora
7640858510 [minor] fix bom price resetting on validation 2017-06-29 22:20:07 +05:30
51 changed files with 1004 additions and 408 deletions

View File

@@ -1,6 +1,12 @@
language: python language: python
dist: trusty dist: trusty
group: deprecated-2017Q2
addons:
apt:
sources:
- google-chrome
packages:
- google-chrome-stable
python: python:
- "2.7" - "2.7"
@@ -8,43 +14,43 @@ python:
services: services:
- mysql - mysql
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
install: install:
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo apt-get purge -y mysql-common mysql-server mysql-client - sudo apt-get purge -y mysql-common mysql-server mysql-client
- nvm install v7.10.0 - nvm install v7.10.0
# - wget https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh
# - sudo bash setup_frappe.sh --skip-setup-bench --mysql-root-password travis --bench-branch develop
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
- sudo python install.py --develop --user travis --without-bench-setup - sudo python install.py --develop --user travis --without-bench-setup
- sudo pip install -e ~/bench - sudo pip install -e ~/bench
# - sudo pip install --upgrade pip
- rm $TRAVIS_BUILD_DIR/.git/shallow - rm $TRAVIS_BUILD_DIR/.git/shallow
- bash $TRAVIS_BUILD_DIR/travis/bench_init.sh - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
- cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
script: before_script:
- wget http://chromedriver.storage.googleapis.com/2.27/chromedriver_linux64.zip
- unzip chromedriver_linux64.zip
- sudo apt-get install libnss3
- sudo apt-get --only-upgrade install google-chrome-stable
- sudo cp chromedriver /usr/local/bin/.
- sudo chmod +x /usr/local/bin/chromedriver
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3
- mysql -u root -ptravis -e 'create database test_frappe'
- echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
- echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
- cd ~/frappe-bench - cd ~/frappe-bench
- bench get-app erpnext $TRAVIS_BUILD_DIR - bench get-app erpnext $TRAVIS_BUILD_DIR
- bench use test_site - bench use test_site
- bench reinstall --yes - bench reinstall --yes
- bench build - bench build
- bench scheduler disable
- bench start & - bench start &
- sleep 10 - sleep 10
- bench --verbose run-tests --driver Firefox
before_script: script:
- mysql -u root -ptravis -e 'create database test_frappe' - set -e
- echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis - bench --verbose run-tests
- echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis - sleep 5
- bench --verbose run-tests --ui-tests
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/92b3bea86d8c5397beef
on_success: always
on_failure: always
on_start: never

View File

@@ -2,8 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
__version__ = '8.3.1' __version__ = '8.3.6'
def get_default_company(user=None): def get_default_company(user=None):
'''Get default company for user''' '''Get default company for user'''

View File

@@ -83,7 +83,7 @@ def validate_expense_against_budget(args):
budget_records = frappe.db.sql(""" budget_records = frappe.db.sql("""
select select
b.{budget_against_field}, ba.budget_amount, b.monthly_distribution, b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
b.action_if_annual_budget_exceeded, b.action_if_annual_budget_exceeded,
b.action_if_accumulated_monthly_budget_exceeded b.action_if_accumulated_monthly_budget_exceeded
from from
@@ -111,15 +111,15 @@ def validate_budget_records(args, budget_records):
args["month_end_date"] = get_last_day(args.posting_date) args["month_end_date"] = get_last_day(args.posting_date)
compare_expense_with_budget(args, budget_amount, compare_expense_with_budget(args, budget_amount,
_("Accumulated Monthly"), monthly_action) _("Accumulated Monthly"), monthly_action, budget.budget_against)
if yearly_action in ("Stop", "Warn") and monthly_action != "Stop" \ if yearly_action in ("Stop", "Warn") and monthly_action != "Stop" \
and yearly_action != monthly_action: and yearly_action != monthly_action:
compare_expense_with_budget(args, flt(budget.budget_amount), compare_expense_with_budget(args, flt(budget.budget_amount),
_("Annual"), yearly_action) _("Annual"), yearly_action, budget.budget_against)
def compare_expense_with_budget(args, budget_amount, action_for, action): def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against):
actual_expense = get_actual_expense(args) actual_expense = get_actual_expense(args)
if actual_expense > budget_amount: if actual_expense > budget_amount:
diff = actual_expense - budget_amount diff = actual_expense - budget_amount
@@ -127,7 +127,7 @@ def compare_expense_with_budget(args, budget_amount, action_for, action):
msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}").format( msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}").format(
_(action_for), frappe.bold(args.account), args.budget_against_field, _(action_for), frappe.bold(args.account), args.budget_against_field,
frappe.bold(args.budget_against), frappe.bold(budget_against),
frappe.bold(fmt_money(budget_amount, currency=currency)), frappe.bold(fmt_money(budget_amount, currency=currency)),
frappe.bold(fmt_money(diff, currency=currency))) frappe.bold(fmt_money(diff, currency=currency)))

View File

@@ -140,6 +140,33 @@ class TestBudget(unittest.TestCase):
budget.load_from_db() budget.load_from_db()
budget.cancel() budget.cancel()
def test_monthly_budget_against_parent_group_cost_center(self):
cost_center = "_Test Cost Center 3 - _TC"
if not frappe.db.exists("Cost Center", cost_center):
frappe.get_doc({
'doctype': 'Cost Center',
'cost_center_name': '_Test Cost Center 3',
'parent_cost_center': "_Test Company - _TC",
'company': '_Test Company',
'is_group': 0
}).insert(ignore_permissions=True)
budget = make_budget("Cost Center", cost_center)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 40000, cost_center)
self.assertRaises(BudgetError, jv.submit)
budget.load_from_db()
budget.cancel()
jv.cancel()
frappe.delete_doc('Journal Entry', jv.name)
frappe.delete_doc('Cost Center', cost_center)
def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None): def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
if budget_against_field == "Project": if budget_against_field == "Project":
budget_against = "_Test Project" budget_against = "_Test Project"
@@ -167,7 +194,8 @@ def make_budget(budget_against=None, cost_center=None):
if budget_against == "Project": if budget_against == "Project":
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")}) budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")})
else: else:
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Cost Center - _TC/_Test Fiscal Year 2013%")}) cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/_Test Fiscal Year 2013")
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
for d in budget_list: for d in budget_list:
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d) frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d) frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)

View File

@@ -291,37 +291,39 @@ frappe.ui.form.on('Payment Entry', {
set_account_currency_and_balance: function(frm, account, currency_field, set_account_currency_and_balance: function(frm, account, currency_field,
balance_field, callback_function) { balance_field, callback_function) {
frappe.call({ if (frm.doc.posting_date) {
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_account_details", frappe.call({
args: { method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_account_details",
"account": account, args: {
"date": frm.doc.posting_date "account": account,
}, "date": frm.doc.posting_date
callback: function(r, rt) { },
if(r.message) { callback: function(r, rt) {
frm.set_value(currency_field, r.message['account_currency']); if(r.message) {
frm.set_value(balance_field, r.message['account_balance']); frm.set_value(currency_field, r.message['account_currency']);
frm.set_value(balance_field, r.message['account_balance']);
if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") { if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"], frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0)); (r.message['account_type'] == "Bank" ? 1 : 0));
if(!frm.doc.received_amount && frm.doc.paid_amount) if(!frm.doc.received_amount && frm.doc.paid_amount)
frm.events.paid_amount(frm); frm.events.paid_amount(frm);
} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") { } else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"], frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0)); (r.message['account_type'] == "Bank" ? 1 : 0));
if(!frm.doc.paid_amount && frm.doc.received_amount) if(!frm.doc.paid_amount && frm.doc.received_amount)
frm.events.received_amount(frm); frm.events.received_amount(frm);
}
if(callback_function) callback_function(frm);
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
} }
if(callback_function) callback_function(frm);
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
} }
} });
}); }
}, },
paid_from_account_currency: function(frm) { paid_from_account_currency: function(frm) {

View File

@@ -492,9 +492,13 @@ def get_outstanding_reference_documents(args):
for d in outstanding_invoices: for d in outstanding_invoices:
d["exchange_rate"] = 1 d["exchange_rate"] = 1
if party_account_currency != company_currency \ if party_account_currency != company_currency:
and d.voucher_type in ("Sales Invoice", "Purchase Invoice"): if d.voucher_type in ("Sales Invoice", "Purchase Invoice"):
d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate") d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
elif d.voucher_type == "Journal Entry":
d["exchange_rate"] = get_exchange_rate(
party_account_currency, company_currency, d.posting_date
)
# Get all SO / PO which are not fully billed or aginst which full advance not paid # Get all SO / PO which are not fully billed or aginst which full advance not paid
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"), orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"),

View File

@@ -12,6 +12,7 @@
"doctype": "DocType", "doctype": "DocType",
"document_type": "", "document_type": "",
"editable_grid": 0, "editable_grid": 0,
"engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
@@ -1927,7 +1928,7 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Item-wise Tax Breakup", "label": "Tax Breakup",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
@@ -4687,7 +4688,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-07-04 17:11:09.477003", "modified": "2017-07-07 13:05:37.469682",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice", "name": "Sales Invoice",

View File

@@ -803,9 +803,10 @@ class SalesInvoice(SellingController):
continue continue
for serial_no in item.serial_no.split("\n"): for serial_no in item.serial_no.split("\n"):
sno = frappe.get_doc('Serial No', serial_no) if serial_no and frappe.db.exists('Serial No', serial_no):
sno.sales_invoice = invoice sno = frappe.get_doc('Serial No', serial_no)
sno.db_update() sno.sales_invoice = invoice
sno.db_update()
def validate_serial_numbers(self): def validate_serial_numbers(self):
""" """

View File

@@ -1107,6 +1107,16 @@ class TestSalesInvoice(unittest.TestCase):
def test_item_wise_tax_breakup(self): def test_item_wise_tax_breakup(self):
si = create_sales_invoice(qty=100, rate=50, do_not_save=True) si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
si.append("items", {
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC",
"qty": 100,
"rate": 50,
"income_account": "Sales - _TC",
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC"
})
si.append("taxes", { si.append("taxes", {
"charge_type": "On Net Total", "charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC", "account_head": "_Test Account Service Tax - _TC",
@@ -1115,8 +1125,8 @@ class TestSalesInvoice(unittest.TestCase):
"rate": 10 "rate": 10
}) })
si.insert() si.insert()
tax_breakup_html = '''\n<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th>\n<th class="text-right" style="min-width: 80px;">Taxable Amount</th>\n<th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">\u20b9 5,000.00</td><td class="text-right">(10.0%) \u20b9 500.00</td></tr></tbody>\n\t</table>\n</div>''' tax_breakup_html = '''\n<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th><th class="text-right" style="min-width: 80px;">Taxable Amount</th><th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">\u20b9 10,000.00</td><td class="text-right">(10.0%) \u20b9 1,000.00</td></tr></tbody>\n\t</table>\n</div>'''
self.assertEqual(si.other_charges_calculation, tax_breakup_html) self.assertEqual(si.other_charges_calculation, tax_breakup_html)

View File

@@ -1,9 +1,3 @@
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __(report.report_name) %}</h2> <h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4> <h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
<h5 class="text-center"> <h5 class="text-center">

View File

@@ -1,9 +1,3 @@
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __("Statement of Account") %}</h2> <h2 class="text-center">{%= __("Statement of Account") %}</h2>
<h4 class="text-center"> <h4 class="text-center">
{% if (filters.party_name) { %} {% if (filters.party_name) { %}

View File

@@ -517,9 +517,9 @@ class calculate_taxes_and_totals(object):
headings = get_table_column_headings(tax_accounts) headings = get_table_column_headings(tax_accounts)
distinct_items = self.get_distinct_items() distinct_items, taxable_amount = self.get_distinct_items()
rows = get_table_rows(distinct_items, item_tax, tax_accounts, company_currency) rows = get_table_rows(distinct_items, item_tax, tax_accounts, company_currency, taxable_amount)
if not rows: if not rows:
self.doc.other_charges_calculation = "" self.doc.other_charges_calculation = ""
@@ -531,8 +531,8 @@ class calculate_taxes_and_totals(object):
<tbody>{rows}</tbody> <tbody>{rows}</tbody>
</table> </table>
</div>'''.format(**{ </div>'''.format(**{
"headings": "\n".join(headings), "headings": "".join(headings),
"rows": "\n".join(rows) "rows": "".join(rows)
}) })
def get_item_tax(self, item_tax, tax_accounts, company_currency): def get_item_tax(self, item_tax, tax_accounts, company_currency):
@@ -568,13 +568,17 @@ class calculate_taxes_and_totals(object):
def get_distinct_items(self): def get_distinct_items(self):
distinct_item_names = [] distinct_item_names = []
distinct_items = [] distinct_items = []
taxable_amount = {}
for item in self.doc.items: for item in self.doc.items:
item_code = item.item_code or item.item_name item_code = item.item_code or item.item_name
if item_code not in distinct_item_names: if item_code not in distinct_item_names:
distinct_item_names.append(item_code) distinct_item_names.append(item_code)
distinct_items.append(item) distinct_items.append(item)
taxable_amount[item_code] = item.net_amount
else:
taxable_amount[item_code] = taxable_amount.get(item_code, 0) + item.net_amount
return distinct_items return distinct_items, taxable_amount
def get_table_column_headings(tax_accounts): def get_table_column_headings(tax_accounts):
headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts] headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts]
@@ -587,7 +591,7 @@ def get_table_column_headings(tax_accounts):
return headings return headings
def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency): def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency, taxable_amount):
rows = [] rows = []
for item in distinct_items: for item in distinct_items:
item_tax_record = item_tax.get(item.item_code or item.item_name) item_tax_record = item_tax.get(item.item_code or item.item_name)
@@ -601,11 +605,12 @@ def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency):
+ item_tax_record[head[0]][1] + "</td>") + item_tax_record[head[0]][1] + "</td>")
else: else:
taxes.append("<td></td>") taxes.append("<td></td>")
item_code = item.item_code or item.item_name
rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{ rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{
"item_name": item.item_name, "item_name": item.item_name,
"taxable_amount": fmt_money(item.net_amount, item.precision("net_amount"), company_currency), "taxable_amount": fmt_money(taxable_amount.get(item_code, 0), item.precision("net_amount"), company_currency),
"taxes": "\n".join(taxes) "taxes": "".join(taxes)
})) }))
return rows return rows

View File

@@ -56,7 +56,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Series", "label": "Series",
"length": 0, "length": 0,
@@ -88,7 +88,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Opportunity From", "label": "Opportunity From",
"length": 0, "length": 0,
@@ -277,8 +277,8 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 0,
"label": "Opportunity Type", "label": "Opportunity Type",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@@ -310,7 +310,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Status", "label": "Status",
"length": 0, "length": 0,
@@ -1189,7 +1189,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-13 14:29:07.077697", "modified": "2017-07-10 15:29:23.921967",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Opportunity", "name": "Opportunity",

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -42,6 +42,7 @@ Email alerts allow you to set conditions according to the field data in your doc
The above example will send an Email Alert when a Task is saved with the status "Open" and the Expected End Date for the Task is the date on or before the date on which it was saved on. The above example will send an Email Alert when a Task is saved with the status "Open" and the Expected End Date for the Task is the date on or before the date on which it was saved on.
### Setting a Message ### Setting a Message
You can use both Jinja Tags (`{% raw %}{{ doc.[field_name] }}{% endraw %}`) and HTML tags in the message textbox. You can use both Jinja Tags (`{% raw %}{{ doc.[field_name] }}{% endraw %}`) and HTML tags in the message textbox.
@@ -64,6 +65,17 @@ You can use both Jinja Tags (`{% raw %}{{ doc.[field_name] }}{% endraw %}`) and
--- ---
### Setting a Value after the Alert is Set
Sometimes to make sure that the email alert is not sent multiple times, you can
define a custom property (via Customize Form) like "Email Alert Sent" and then
set this property after the alert is sent by setting the **Set Property After Alert**
field.
Then you can use that as a condition in the **Condition** rules to ensure emails are not sent multiple times
<img class="screenshot" alt="Setting Property in Email Alert" src="{{docs_base_url}}/assets/img/setup/email/email-alert-subject.png">
### Example ### Example
1. Defining the Criteria 1. Defining the Criteria

View File

@@ -80,6 +80,13 @@ website_route_rules = [
"parents": [{"title": _("Supplier Quotation"), "name": "quotations"}] "parents": [{"title": _("Supplier Quotation"), "name": "quotations"}]
} }
}, },
{"from_route": "/quotes", "to_route": "Quotation"},
{"from_route": "/quotes/<path:name>", "to_route": "order",
"defaults": {
"doctype": "Quotation",
"parents": [{"title": _("Quotes"), "name": "quotes"}]
}
},
{"from_route": "/shipments", "to_route": "Delivery Note"}, {"from_route": "/shipments", "to_route": "Delivery Note"},
{"from_route": "/shipments/<path:name>", "to_route": "order", {"from_route": "/shipments/<path:name>", "to_route": "order",
"defaults": { "defaults": {
@@ -110,6 +117,7 @@ standard_portal_menu_items = [
{"title": _("Projects"), "route": "/project", "reference_doctype": "Project"}, {"title": _("Projects"), "route": "/project", "reference_doctype": "Project"},
{"title": _("Request for Quotations"), "route": "/rfq", "reference_doctype": "Request for Quotation", "role": "Supplier"}, {"title": _("Request for Quotations"), "route": "/rfq", "reference_doctype": "Request for Quotation", "role": "Supplier"},
{"title": _("Supplier Quotation"), "route": "/quotations", "reference_doctype": "Supplier Quotation", "role": "Supplier"}, {"title": _("Supplier Quotation"), "route": "/quotations", "reference_doctype": "Supplier Quotation", "role": "Supplier"},
{"title": _("Quotes"), "route": "/quotes", "reference_doctype": "Quotation", "role":"Customer"},
{"title": _("Orders"), "route": "/orders", "reference_doctype": "Sales Order", "role":"Customer"}, {"title": _("Orders"), "route": "/orders", "reference_doctype": "Sales Order", "role":"Customer"},
{"title": _("Invoices"), "route": "/invoices", "reference_doctype": "Sales Invoice", "role":"Customer"}, {"title": _("Invoices"), "route": "/invoices", "reference_doctype": "Sales Invoice", "role":"Customer"},
{"title": _("Shipments"), "route": "/shipments", "reference_doctype": "Delivery Note", "role":"Customer"}, {"title": _("Shipments"), "route": "/shipments", "reference_doctype": "Delivery Note", "role":"Customer"},

View File

@@ -12,32 +12,31 @@ import frappe.utils
class TestDailyWorkSummary(unittest.TestCase): class TestDailyWorkSummary(unittest.TestCase):
def test_email_trigger(self): def test_email_trigger(self):
settings, employees, emails = self.setup_and_prepare_test() self.setup_and_prepare_test()
for d in self.employees:
for d in employees:
# check that email is sent to this employee # check that email is sent to this employee
self.assertTrue(d.user_id in [d.recipient for d in emails self.assertTrue(d.user_id in [d.recipient for d in self.emails
if settings.subject in d.message]) if self.settings.subject in d.message])
def test_email_trigger_failed(self): def test_email_trigger_failed(self):
hour = '00' hour = '00'
if frappe.utils.nowtime().split(':')[0]=='00': if frappe.utils.nowtime().split(':')[0]=='00':
hour = '01' hour = '01'
settings, employees, emails = self.setup_and_prepare_test(hour) self.setup_and_prepare_test(hour)
for d in employees: for d in self.employees:
# check that email is sent to this employee # check that email is sent to this employee
self.assertFalse(d.user_id in [d.recipient for d in emails self.assertFalse(d.user_id in [d.recipient for d in self.emails
if settings.subject in d.message]) if self.settings.subject in d.message])
def test_incoming(self): def test_incoming(self):
settings, employees, emails = self.setup_and_prepare_test()
# get test mail with message-id as in-reply-to # get test mail with message-id as in-reply-to
self.setup_and_prepare_test()
with open(os.path.join(os.path.dirname(__file__), "test_data", "test-reply.raw"), "r") as f: with open(os.path.join(os.path.dirname(__file__), "test_data", "test-reply.raw"), "r") as f:
test_mails = [f.read().replace('{{ sender }}', employees[-1].user_id)\ test_mails = [f.read().replace('{{ sender }}', self.employees[-1].user_id)\
.replace('{{ message_id }}', emails[-1].message_id)] .replace('{{ message_id }}', self.emails[-1].message_id)]
# pull the mail # pull the mail
email_account = frappe.get_doc("Email Account", "_Test Email Account 1") email_account = frappe.get_doc("Email Account", "_Test Email Account 1")
@@ -52,30 +51,34 @@ class TestDailyWorkSummary(unittest.TestCase):
self.assertTrue('I built Daily Work Summary!' in summary) self.assertTrue('I built Daily Work Summary!' in summary)
def setup_and_prepare_test(self, hour=None): def setup_and_prepare_test(self, hour=None):
if not hour:
hour = frappe.utils.nowtime().split(':')[0]
frappe.db.sql('delete from `tabDaily Work Summary`') frappe.db.sql('delete from `tabDaily Work Summary`')
frappe.db.sql('delete from `tabEmail Queue`') frappe.db.sql('delete from `tabEmail Queue`')
frappe.db.sql('delete from `tabEmail Queue Recipient`') frappe.db.sql('delete from `tabEmail Queue Recipient`')
frappe.db.sql('delete from `tabCommunication`') frappe.db.sql('delete from `tabCommunication`')
# setup email to trigger at this our self.setup_settings(hour)
settings = frappe.get_doc('Daily Work Summary Settings')
settings.companies = []
settings.append('companies', dict(company='_Test Company',
send_emails_at=hour + ':00'))
settings.test_subject = 'this is a subject for testing summary emails'
settings.save()
from erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings \ from erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings \
import trigger_emails import trigger_emails
trigger_emails() trigger_emails()
# check if emails are created # check if emails are created
employees = frappe.get_all('Employee', fields = ['user_id'], self.employees = frappe.get_all('Employee', fields = ['user_id'],
filters=dict(company='_Test Company', status='Active')) filters=dict(company='_Test Company', status='Active', user_id=('!=', 'test@example.com')))
emails = frappe.db.sql("""select r.recipient, q.message, q.message_id from `tabEmail Queue` as q, `tabEmail Queue Recipient` as r where q.name = r.parent""", as_dict=1) self.emails = frappe.db.sql("""select r.recipient, q.message, q.message_id from `tabEmail Queue` as q, `tabEmail Queue Recipient` as r where q.name = r.parent""", as_dict=1)
frappe.db.commit()
def setup_settings(self, hour=None):
# setup email to trigger at this our
if not hour:
hour = frappe.utils.nowtime().split(':')[0]
self.settings = frappe.get_doc('Daily Work Summary Settings')
self.settings.companies = []
self.settings.append('companies', dict(company='_Test Company',
send_emails_at=hour + ':00'))
self.settings.test_subject = 'this is a subject for testing summary emails'
self.settings.save()
return settings, employees, emails

View File

@@ -365,9 +365,6 @@ class BOM(WebsiteGenerator):
base_total_rm_cost = 0 base_total_rm_cost = 0
for d in self.get('items'): for d in self.get('items'):
if d.bom_no:
d.rate = self.get_bom_unitcost(d.bom_no)
d.base_rate = flt(d.rate) * flt(self.conversion_rate) d.base_rate = flt(d.rate) * flt(self.conversion_rate)
d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d)) d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d))
d.base_amount = d.amount * flt(self.conversion_rate) d.base_amount = d.amount * flt(self.conversion_rate)

View File

@@ -151,26 +151,28 @@ frappe.ui.form.on("Production Order", {
}, },
production_item: function(frm) { production_item: function(frm) {
frappe.call({ if (frm.doc.production_item) {
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details", frappe.call({
args: { method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
item: frm.doc.production_item, args: {
project: frm.doc.project item: frm.doc.production_item,
}, project: frm.doc.project
callback: function(r) { },
if(r.message) { callback: function(r) {
erpnext.in_production_item_onchange = true; if(r.message) {
$.each(["description", "stock_uom", "project", "bom_no"], function(i, field) { erpnext.in_production_item_onchange = true;
frm.set_value(field, r.message[field]); $.each(["description", "stock_uom", "project", "bom_no"], function(i, field) {
}); frm.set_value(field, r.message[field]);
});
if(r.message["set_scrap_wh_mandatory"]){ if(r.message["set_scrap_wh_mandatory"]){
frm.toggle_reqd("scrap_warehouse", true); frm.toggle_reqd("scrap_warehouse", true);
}
erpnext.in_production_item_onchange = false;
} }
erpnext.in_production_item_onchange = false;
} }
} });
}); }
}, },
project: function(frm) { project: function(frm) {
@@ -263,7 +265,7 @@ erpnext.production_order = {
erpnext.production_order.stop_production_order(frm, "Resumed"); erpnext.production_order.stop_production_order(frm, "Resumed");
}, __("Status")); }, __("Status"));
} }
if(!frm.doc.skip_transfer){ if(!frm.doc.skip_transfer){
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty))
&& frm.doc.status != 'Stopped') { && frm.doc.status != 'Stopped') {
@@ -272,7 +274,7 @@ erpnext.production_order = {
erpnext.production_order.make_se(frm, 'Material Transfer for Manufacture'); erpnext.production_order.make_se(frm, 'Material Transfer for Manufacture');
}); });
start_btn.addClass('btn-primary'); start_btn.addClass('btn-primary');
} }
} }
if(!frm.doc.skip_transfer){ if(!frm.doc.skip_transfer){
@@ -291,8 +293,9 @@ erpnext.production_order = {
} else { } else {
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') { if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
frm.has_finish_btn = true; frm.has_finish_btn = true;
var finish_btn = frm.add_custom_button(__('Finish'), var finish_btn = frm.add_custom_button(__('Finish'), function() {
cur_frm.cscript['Update Finished Goods']); erpnext.production_order.make_se(frm, 'Manufacture');
});
finish_btn.addClass('btn-primary'); finish_btn.addClass('btn-primary');
} }
} }

View File

@@ -1358,7 +1358,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-13 14:29:00.457874", "modified": "2017-07-10 14:29:00.457874",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order", "name": "Production Order",

View File

@@ -353,7 +353,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-05-15 17:37:20.212361", "modified": "2017-07-10 17:37:20.212361",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order Item", "name": "Production Order Item",

View File

@@ -406,6 +406,7 @@ erpnext.patches.v8_0.change_in_words_varchar_length
erpnext.patches.v8_0.update_stock_qty_value_in_bom_item erpnext.patches.v8_0.update_stock_qty_value_in_bom_item
erpnext.patches.v8_0.create_domain_docs #16-05-2017 erpnext.patches.v8_0.create_domain_docs #16-05-2017
erpnext.patches.v8_0.update_sales_cost_in_project erpnext.patches.v8_0.update_sales_cost_in_project
erpnext.patches.v8_0.create_address_doc_from_address_field_in_company #10-05-2017
erpnext.patches.v8_0.save_system_settings erpnext.patches.v8_0.save_system_settings
erpnext.patches.v8_1.delete_deprecated_reports erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v8_1.setup_gst_india #2017-06-27 erpnext.patches.v8_1.setup_gst_india #2017-06-27
@@ -413,4 +414,5 @@ execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
erpnext.patches.v8_1.gst_fixes #2017-07-06 erpnext.patches.v8_1.gst_fixes #2017-07-06
erpnext.patches.v8_0.update_production_orders erpnext.patches.v8_0.update_production_orders
erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no
erpnext.patches.v8_1.allow_invoice_copy_to_edit_after_submit

View File

@@ -0,0 +1,33 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
# new field address_html is created in place of address field for the company's address in PR #8754 (without patch)
# so here is the patch for moving the address details in the address doc
company_list = []
if 'address' in frappe.db.get_table_columns('Company'):
company_list = frappe.db.sql('''select name, address from `tabCompany`
where address is not null and address != ""''', as_dict=1)
for company in company_list:
add_list = company.address.split(" ")
if ',' in company.address:
add_list = company.address.rpartition(',')
elif ' ' in company.address:
add_list = company.address.rpartition(' ')
else:
add_list = [company.address, None, company.address]
doc = frappe.get_doc({
"doctype":"Address",
"address_line1": add_list[0],
"city": add_list[2],
"links": [{
"link_doctype": "Company",
"link_name": company.name
}]
})
doc.save()

View File

@@ -9,8 +9,8 @@ from frappe.model.mapper import get_mapped_doc
def execute(): def execute():
# for converting student batch into student group # for converting student batch into student group
for doctype in ["Student Group", "Student Group Student", "Student Group Instructor", "Student Attendance"]: for doctype in ["Student Group", "Student Group Student", "Student Group Instructor", "Student Attendance", "Student"]:
frappe.reload_doc("schools", "doctype", doctype) frappe.reload_doc("schools", "doctype", frappe.scrub(doctype))
if frappe.db.table_exists("Student Batch"): if frappe.db.table_exists("Student Batch"):
student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch, student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch,

View File

@@ -0,0 +1,12 @@
import frappe
def execute():
inv_copy_options = "ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nDUPLICATE FOR SUPPLIER\nTRIPLICATE FOR SUPPLIER"
frappe.db.sql("""update `tabCustom Field` set allow_on_submit=1, options=%s
where fieldname='invoice_copy' and dt = 'Sales Invoice'
""", inv_copy_options)
frappe.db.sql("""update `tabCustom Field` set read_only=1
where fieldname='gst_state_number' and dt = 'Address'
""")

View File

@@ -44,7 +44,7 @@ def add_custom_fields():
], ],
'Sales Invoice': [ 'Sales Invoice': [
dict(fieldname='invoice_copy', label='Invoice Copy', dict(fieldname='invoice_copy', label='Invoice Copy',
fieldtype='Select', insert_after='project', print_hide=1, fieldtype='Select', insert_after='project', print_hide=1, allow_on_submit=1,
options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'), options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'),
], ],
'Sales Order Item': [hsn_sac_field], 'Sales Order Item': [hsn_sac_field],

View File

@@ -5,6 +5,7 @@ def execute():
frappe.reload_doc('regional', 'doctype', 'gst_settings') frappe.reload_doc('regional', 'doctype', 'gst_settings')
frappe.reload_doc('regional', 'doctype', 'gst_hsn_code') frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
frappe.reload_doc('stock', 'doctype', 'item') frappe.reload_doc('stock', 'doctype', 'item')
frappe.reload_doc("stock", "doctype", "customs_tariff_number")
for report_name in ('GST Sales Register', 'GST Purchase Register', for report_name in ('GST Sales Register', 'GST Purchase Register',
'GST Itemised Sales Register', 'GST Itemised Purchase Register'): 'GST Itemised Sales Register', 'GST Itemised Purchase Register'):

View File

@@ -689,31 +689,38 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
return '<th style="min-width: 80px;" class="text-right">' + (head || "") + "</th>"; return '<th style="min-width: 80px;" class="text-right">' + (head || "") + "</th>";
} }
} }
).join("\n"); ).join("");
var distinct_item_names = []; var distinct_item_names = [];
var distinct_items = []; var distinct_items = [];
var taxable_amount = {};
$.each(this.frm.doc["items"] || [], function(i, item) { $.each(this.frm.doc["items"] || [], function(i, item) {
if(distinct_item_names.indexOf(item.item_code || item.item_name)===-1) { var item_code = item.item_code || item.item_name;
distinct_item_names.push(item.item_code || item.item_name); if(distinct_item_names.indexOf(item_code)===-1) {
distinct_item_names.push(item_code);
distinct_items.push(item); distinct_items.push(item);
taxable_amount[item_code] = item.net_amount;
} else {
taxable_amount[item_code] = taxable_amount[item_code] + item.net_amount;
} }
}); });
var rows = $.map(distinct_items, function(item) { var rows = $.map(distinct_items, function(item) {
var item_tax_record = item_tax[item.item_code || item.item_name]; var item_code = item.item_code || item.item_name;
var item_tax_record = item_tax[item_code];
if(!item_tax_record) { return null; } if(!item_tax_record) { return null; }
return repl("<tr><td>%(item_name)s</td><td class='text-right'>%(taxable_amount)s</td>%(taxes)s</tr>", { return repl("<tr><td>%(item_name)s</td><td class='text-right'>%(taxable_amount)s</td>%(taxes)s</tr>", {
item_name: item.item_name, item_name: item.item_name,
taxable_amount: format_currency(item.net_amount, taxable_amount: format_currency(taxable_amount[item_code],
company_currency, precision("net_amount", item)), company_currency, precision("net_amount", item)),
taxes: $.map(tax_accounts, function(head) { taxes: $.map(tax_accounts, function(head) {
return item_tax_record[head[0]] ? return item_tax_record[head[0]] ?
"<td class='text-right'>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" : "<td class='text-right'>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
"<td></td>"; "<td></td>";
}).join("\n") }).join("")
}); });
}).join("\n"); }).join("");
if(!rows) return ""; if(!rows) return "";
return '<div class="tax-break-up" style="overflow-x: auto;">\ return '<div class="tax-break-up" style="overflow-x: auto;">\

View File

@@ -63,37 +63,32 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}); });
frappe.ui.form.on(this.frm.doctype, "additional_discount_percentage", function(frm) { frappe.ui.form.on(this.frm.doctype, "additional_discount_percentage", function(frm) {
if (frm.via_discount_amount) {
return;
}
if(!frm.doc.apply_discount_on) { if(!frm.doc.apply_discount_on) {
frappe.msgprint(__("Please set 'Apply Additional Discount On'")); frappe.msgprint(__("Please set 'Apply Additional Discount On'"));
return return;
} }
frm.via_discount_percentage = true; frm.via_discount_percentage = true;
if(frm.doc.additional_discount_percentage && frm.doc.discount_amount) { if(frm.doc.additional_discount_percentage && frm.doc.discount_amount) {
// Reset discount amount and net / grand total // Reset discount amount and net / grand total
frm.set_value("discount_amount", 0); frm.doc.discount_amount = 0;
frm.cscript.calculate_taxes_and_totals();
} }
var total = flt(frm.doc[frappe.model.scrub(frm.doc.apply_discount_on)]); var total = flt(frm.doc[frappe.model.scrub(frm.doc.apply_discount_on)]);
var discount_amount = flt(total*flt(frm.doc.additional_discount_percentage) / 100, var discount_amount = flt(total*flt(frm.doc.additional_discount_percentage) / 100,
precision("discount_amount")); precision("discount_amount"));
frm.set_value("discount_amount", discount_amount); frm.set_value("discount_amount", discount_amount)
delete frm.via_discount_percentage; .then(() => delete frm.via_discount_percentage);
}); });
frappe.ui.form.on(this.frm.doctype, "discount_amount", function(frm) { frappe.ui.form.on(this.frm.doctype, "discount_amount", function(frm) {
frm.cscript.set_dynamic_labels(); frm.cscript.set_dynamic_labels();
if (!frm.via_discount_percentage) { if (!frm.via_discount_percentage) {
frm.via_discount_amount = true; frm.doc.additional_discount_percentage = 0;
frm.set_value("additional_discount_percentage", 0);
delete frm.via_discount_amount;
} }
frm.cscript.calculate_taxes_and_totals(); frm.cscript.calculate_taxes_and_totals();

View File

@@ -68,13 +68,13 @@ var erpnext_slides = [
slide.get_input("company_name").on("change", function () { slide.get_input("company_name").on("change", function () {
var parts = slide.get_input("company_name").val().split(" "); var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join(""); var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join("");
slide.get_field("company_abbr").set_input(abbr.slice(0, 5).toUpperCase()); slide.get_field("company_abbr").set_value(abbr.slice(0, 5).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change"); }).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
slide.get_input("company_abbr").on("change", function () { slide.get_input("company_abbr").on("change", function () {
if (slide.get_input("company_abbr").val().length > 5) { if (slide.get_input("company_abbr").val().length > 5) {
frappe.msgprint("Company Abbreviation cannot have more than 5 characters"); frappe.msgprint("Company Abbreviation cannot have more than 5 characters");
slide.get_field("company_abbr").set_input(""); slide.get_field("company_abbr").set_value("");
} }
}); });
} }
@@ -189,6 +189,32 @@ var erpnext_slides = [
} }
}, },
{
// Users
name: 'users',
domains: ["all"],
title: __("Add Users"),
help: __("Add users to your organization, other than yourself"),
add_more: 1,
max_count: 3,
fields: [
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"user_fullname",
label:__("Full Name"), static: 1},
{fieldtype:"Data", fieldname:"user_email", label:__("Email ID"),
placeholder:__("user@example.com"), options: "Email", static: 1},
{fieldtype:"Column Break"},
{fieldtype: "Check", fieldname: "user_sales",
label:__("Sales"), "default": 1, static: 1,
hidden: frappe.setup.domain==='Education' ? 1 : 0},
{fieldtype: "Check", fieldname: "user_purchaser",
label:__("Purchaser"), "default": 1, static: 1,
hidden: frappe.setup.domain==='Education' ? 1 : 0},
{fieldtype: "Check", fieldname: "user_accountant",
label:__("Accountant"), "default": 1, static: 1,
hidden: frappe.setup.domain==='Education' ? 1 : 0},
]
},
{ {
// Taxes // Taxes
@@ -198,7 +224,8 @@ var erpnext_slides = [
title: __("Add Taxes"), title: __("Add Taxes"),
help: __("List your tax heads (e.g. VAT, Customs etc; they should have unique names) and their standard rates. This will create a standard template, which you can edit and add more later."), help: __("List your tax heads (e.g. VAT, Customs etc; they should have unique names) and their standard rates. This will create a standard template, which you can edit and add more later."),
add_more: 1, add_more: 1,
max_count: 4, max_count: 3,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break"}, {fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"tax", label:__("Tax"), {fieldtype:"Data", fieldname:"tax", label:__("Tax"),
@@ -216,7 +243,8 @@ var erpnext_slides = [
title: __("Add Customers"), title: __("Add Customers"),
help: __("List a few of your customers. They could be organizations or individuals."), help: __("List a few of your customers. They could be organizations or individuals."),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break"}, {fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"customer", label:__("Customer"), {fieldtype:"Data", fieldname:"customer", label:__("Customer"),
@@ -235,7 +263,8 @@ var erpnext_slides = [
title: __("Your Suppliers"), title: __("Your Suppliers"),
help: __("List a few of your suppliers. They could be organizations or individuals."), help: __("List a few of your suppliers. They could be organizations or individuals."),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break"}, {fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"supplier", label:__("Supplier"), {fieldtype:"Data", fieldname:"supplier", label:__("Supplier"),
@@ -254,7 +283,8 @@ var erpnext_slides = [
title: __("Your Products or Services"), title: __("Your Products or Services"),
help: __("List your products or services that you buy or sell. Make sure to check the Item Group, Unit of Measure and other properties when you start."), help: __("List your products or services that you buy or sell. Make sure to check the Item Group, Unit of Measure and other properties when you start."),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break", show_section_border: true}, {fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"item", label:__("Item"), {fieldtype:"Data", fieldname:"item", label:__("Item"),
@@ -262,16 +292,16 @@ var erpnext_slides = [
{fieldtype:"Select", label:__("Group"), fieldname:"item_group", {fieldtype:"Select", label:__("Group"), fieldname:"item_group",
options:[__("Products"), __("Services"), options:[__("Products"), __("Services"),
__("Raw Material"), __("Consumable"), __("Sub Assemblies")], __("Raw Material"), __("Consumable"), __("Sub Assemblies")],
"default": __("Products")}, "default": __("Products"), static: 1},
{fieldtype:"Select", fieldname:"item_uom", label:__("UOM"), {fieldtype:"Select", fieldname:"item_uom", label:__("UOM"),
options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"), options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"),
__("Hour"), __("Minute"), __("Litre"), __("Meter"), __("Gram")], __("Hour"), __("Minute"), __("Litre"), __("Meter"), __("Gram")],
"default": __("Unit")}, "default": __("Unit"), static: 1},
{fieldtype: "Check", fieldname: "is_sales_item", label:__("We sell this Item"), default: 1}, {fieldtype: "Check", fieldname: "is_sales_item", label:__("We sell this Item"), default: 1, static: 1},
{fieldtype: "Check", fieldname: "is_purchase_item", label:__("We buy this Item")}, {fieldtype: "Check", fieldname: "is_purchase_item", label:__("We buy this Item"), static: 1},
{fieldtype:"Column Break"}, {fieldtype:"Column Break"},
{fieldtype:"Currency", fieldname:"item_price", label:__("Rate")}, {fieldtype:"Currency", fieldname:"item_price", label:__("Rate"), static: 1},
{fieldtype:"Attach Image", fieldname:"item_img", label:__("Attach Image"), is_private: 0}, {fieldtype:"Attach Image", fieldname:"item_img", label:__("Attach Image"), is_private: 0, static: 1},
], ],
get_item_count: function() { get_item_count: function() {
return this.item_count; return this.item_count;
@@ -285,7 +315,8 @@ var erpnext_slides = [
title: __("Program"), title: __("Program"),
help: __("Example: Masters in Computer Science"), help: __("Example: Masters in Computer Science"),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break", show_section_border: true}, {fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"program", label:__("Program"), placeholder: __("Program Name")}, {fieldtype:"Data", fieldname:"program", label:__("Program"), placeholder: __("Program Name")},
@@ -299,7 +330,8 @@ var erpnext_slides = [
title: __("Course"), title: __("Course"),
help: __("Example: Basic Mathematics"), help: __("Example: Basic Mathematics"),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break", show_section_border: true}, {fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"course", label:__("Course"), placeholder: __("Course Name")}, {fieldtype:"Data", fieldname:"course", label:__("Course"), placeholder: __("Course Name")},
@@ -313,7 +345,8 @@ var erpnext_slides = [
title: __("Instructor"), title: __("Instructor"),
help: __("People who teach at your organisation"), help: __("People who teach at your organisation"),
add_more: 1, add_more: 1,
max_count: 6, max_count: 5,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break", show_section_border: true}, {fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"instructor", label:__("Instructor"), placeholder: __("Instructor Name")}, {fieldtype:"Data", fieldname:"instructor", label:__("Instructor"), placeholder: __("Instructor Name")},
@@ -327,20 +360,21 @@ var erpnext_slides = [
title: __("Room"), title: __("Room"),
help: __("Classrooms/ Laboratories etc where lectures can be scheduled."), help: __("Classrooms/ Laboratories etc where lectures can be scheduled."),
add_more: 1, add_more: 1,
max_count: 4, max_count: 3,
mandatory_entry: 1,
fields: [ fields: [
{fieldtype:"Section Break", show_section_border: true}, {fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"room", label:__("Room")}, {fieldtype:"Data", fieldname:"room", label:__("Room")},
{fieldtype:"Column Break"}, {fieldtype:"Column Break"},
{fieldtype:"Int", fieldname:"room_capacity", label:__("Room") + " Capacity"}, {fieldtype:"Int", fieldname:"room_capacity", label:__("Room") + " Capacity", static: 1},
] ]
}, },
{ {
// last slide: Bootstrap // last slide: Sample Data
name: 'bootstrap', name: 'bootstrap',
domains: ["all"], domains: ["all"],
title: __("Bootstrap"), title: __("Sample Data"),
fields: [{fieldtype: "Section Break"}, fields: [{fieldtype: "Section Break"},
{fieldtype: "Check", fieldname: "add_sample_data", {fieldtype: "Check", fieldname: "add_sample_data",
label: __("Add a few sample records"), "default": 1}, label: __("Add a few sample records"), "default": 1},

View File

@@ -72,5 +72,5 @@ state_numbers = {
"Tripura": "16", "Tripura": "16",
"Uttar Pradesh": "35", "Uttar Pradesh": "35",
"Uttarakhand": "36", "Uttarakhand": "36",
"West Bengal": "37" "West Bengal": "19"
} }

View File

@@ -15,7 +15,7 @@
"state_name": "Uttarakhand" "state_name": "Uttarakhand"
}, },
{ {
"state_number": "37", "state_number": "19",
"state_code": "WB", "state_code": "WB",
"state_name": "West Bengal" "state_name": "West Bengal"
}, },

View File

@@ -84,7 +84,7 @@ def make_custom_fields():
dict(fieldname='gst_state', label='GST State', fieldtype='Select', dict(fieldname='gst_state', label='GST State', fieldtype='Select',
options='\n'.join(states), insert_after='gstin'), options='\n'.join(states), insert_after='gstin'),
dict(fieldname='gst_state_number', label='GST State Number', dict(fieldname='gst_state_number', label='GST State Number',
fieldtype='Int', insert_after='gst_state'), fieldtype='Int', insert_after='gst_state', read_only=1),
], ],
'Purchase Invoice': [ 'Purchase Invoice': [
dict(fieldname='supplier_gstin', label='Supplier GSTIN', dict(fieldname='supplier_gstin', label='Supplier GSTIN',
@@ -102,8 +102,8 @@ def make_custom_fields():
fieldtype='Data', insert_after='company_address', fieldtype='Data', insert_after='company_address',
options='company_address.gstin', print_hide=1), options='company_address.gstin', print_hide=1),
dict(fieldname='invoice_copy', label='Invoice Copy', dict(fieldname='invoice_copy', label='Invoice Copy',
fieldtype='Select', insert_after='project', print_hide=1, fieldtype='Select', insert_after='project', print_hide=1, allow_on_submit=1,
options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER') options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nDUPLICATE FOR SUPPLIER\nTRIPLICATE FOR SUPPLIER')
], ],
'Item': [ 'Item': [
dict(fieldname='gst_hsn_code', label='HSN/SAC', dict(fieldname='gst_hsn_code', label='HSN/SAC',

View File

@@ -19,6 +19,6 @@ def validate_gstin_for_india(doc, method):
if doc.gst_state: if doc.gst_state:
doc.gst_state_number = state_numbers[doc.gst_state] doc.gst_state_number = state_numbers[doc.gst_state]
if doc.gst_state_number != doc.gstin[:2]: if doc.gstin != "NA" and doc.gst_state_number != doc.gstin[:2]:
frappe.throw(_("First 2 digits of GSTIN should match with State number {0}") frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
.format(doc.gst_state_number)) .format(doc.gst_state_number))

View File

@@ -7,10 +7,10 @@
"docstatus": 0, "docstatus": 0,
"doctype": "Print Format", "doctype": "Print Format",
"font": "Default", "font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div class=\\\"print-heading\\\">\\n\\t<h2>\\n\\t\\tSALES INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-center\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small>{{ doc.invoice_copy }}</small>\\n\\t{% endif -%}\\n</h2>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"<hr>\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Item-wise Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]", "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div class=\\\"print-heading\\\">\\n\\t<h2>\\n\\t\\tTAX INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-center\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small>{{ doc.invoice_copy }}</small>\\n\\t{% endif -%}\\n</h2>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"<hr>\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]",
"idx": 0, "idx": 0,
"line_breaks": 0, "line_breaks": 0,
"modified": "2017-07-06 17:47:38.279783", "modified": "2017-07-07 13:06:20.042807",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Regional", "module": "Regional",
"name": "GST Tax Invoice", "name": "GST Tax Invoice",

View File

@@ -143,9 +143,10 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Today", "default": "0",
"fieldname": "enrollment_date", "description": "Check this if the Student is residing at the Institute's Hostel.",
"fieldtype": "Date", "fieldname": "boarding_student",
"fieldtype": "Check",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
@@ -153,9 +154,10 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Enrollment Date", "label": "Boarding Student",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@@ -163,7 +165,7 @@
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
@@ -321,6 +323,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Today",
"fieldname": "enrollment_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Enrollment Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -370,7 +403,7 @@
"label": "Mode of Transportation", "label": "Mode of Transportation",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "\nSchool Bus\nPublic Transport\nSelf-Driving Vehicle\nPick/Drop by Guardian", "options": "\nWalking\nSchool Bus\nPublic Transport\nSelf-Driving Vehicle\nPick/Drop by Guardian",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@@ -638,7 +671,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-30 08:21:49.430996", "modified": "2017-07-10 18:16:15.810616",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Program Enrollment", "name": "Program Enrollment",

View File

@@ -589,67 +589,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_18",
"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": "Guardian Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "guardians",
"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": "Guardians",
"length": 0,
"no_copy": 0,
"options": "Student Guardian",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -859,6 +798,67 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_18",
"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": "Guardian Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "guardians",
"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": "Guardians",
"length": 0,
"no_copy": 0,
"options": "Student Guardian",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -1114,7 +1114,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-30 08:21:50.423784", "modified": "2017-07-07 16:30:08.930882",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Student", "name": "Student",

View File

@@ -7,10 +7,24 @@ def get_data():
'fieldname': 'student', 'fieldname': 'student',
'transactions': [ 'transactions': [
{ {
'items': ['Student Log', 'Student Group', 'Program Enrollment'] 'label': _('Admission'),
'items': ['Program Enrollment']
}, },
{ {
'items': ['Fees', 'Assessment Result', 'Student Attendance', 'Student Leave Application'] 'label': _('Student Activity'),
'items': ['Student Log', 'Student Group', ]
},
{
'label': _('Assessment'),
'items': ['Assessment Result']
},
{
'label': _('Attendance'),
'items': ['Student Attendance', 'Student Leave Application']
},
{
'label': _('Fee'),
'items': ['Fees']
} }
] ]
} }

View File

@@ -135,22 +135,24 @@ schools.StudentsEditor = Class.extend({
frappe.confirm(__("Do you want to update attendance?<br>Present: {0}\ frappe.confirm(__("Do you want to update attendance?<br>Present: {0}\
<br>Absent: {1}", [students_present.length, students_absent.length]), <br>Absent: {1}", [students_present.length, students_absent.length]),
function() { //ifyes function() { //ifyes
frappe.call({ if(!frappe.request.ajax_count) {
method: "erpnext.schools.api.mark_attendance", frappe.call({
freeze: true, method: "erpnext.schools.api.mark_attendance",
freeze_message: "Marking attendance", freeze: true,
args: { freeze_message: "Marking attendance",
"students_present": students_present, args: {
"students_absent": students_absent, "students_present": students_present,
"student_group": frm.doc.student_group, "students_absent": students_absent,
"course_schedule": frm.doc.course_schedule, "student_group": frm.doc.student_group,
"date": frm.doc.date "course_schedule": frm.doc.course_schedule,
}, "date": frm.doc.date
callback: function(r) { },
$(me.wrapper.find(".btn-mark-att")).attr("disabled", false); callback: function(r) {
frm.trigger("student_group"); $(me.wrapper.find(".btn-mark-att")).attr("disabled", false);
} frm.trigger("student_group");
}); }
});
}
}, },
function() { //ifno function() { //ifno
$(me.wrapper.find(".btn-mark-att")).attr("disabled", false); $(me.wrapper.find(".btn-mark-att")).attr("disabled", false);

View File

@@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
"autoname": "SLog.####", "autoname": "SLog.####",
@@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -43,64 +45,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_on_submit": 0, "allow_bulk_edit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "type",
"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": 1,
"label": "Type",
"length": 0,
"no_copy": 0,
"options": "General\nAcademic\nMedical\nAchievement",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -131,6 +76,38 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "type",
"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": 1,
"label": "Type",
"length": 0,
"no_copy": 0,
"options": "General\nAcademic\nMedical\nAchievement",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -160,6 +137,160 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_year",
"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": "Academic Year",
"length": 0,
"no_copy": 0,
"options": "Academic 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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_term",
"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": "Academic Term",
"length": 0,
"no_copy": 0,
"options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "program",
"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": "Program",
"length": 0,
"no_copy": 0,
"options": "Program",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_batch",
"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": "Student Batch",
"length": 0,
"no_copy": 0,
"options": "Student Batch Name",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -188,6 +319,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -217,17 +349,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-17 17:18:19.596892", "modified": "2017-07-06 12:42:05.777673",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Student Log", "name": "Student Log",

View File

@@ -30,12 +30,8 @@ erpnext.selling.InstallationNote = frappe.ui.form.Controller.extend({
setup_queries: function() { setup_queries: function() {
var me = this; var me = this;
this.frm.set_query("customer_address", function() { frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
return { frm.set_query('customer_address', erpnext.queries.address_query);
filters: {'customer': me.frm.doc.customer }
}
});
this.frm.set_query('contact_person', erpnext.queries.contact_query); this.frm.set_query('contact_person', erpnext.queries.contact_query);
this.frm.set_query("customer", function() { this.frm.set_query("customer", function() {

View File

@@ -86,6 +86,17 @@ class Quotation(SellingController):
print_lst.append(lst1) print_lst.append(lst1)
return print_lst return print_lst
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)
list_context.update({
'show_sidebar': True,
'show_search': True,
'no_breadcrumbs': True,
'title': _('Quotes'),
})
return list_context
@frappe.whitelist() @frappe.whitelist()
def make_sales_order(source_name, target_doc=None): def make_sales_order(source_name, target_doc=None):

View File

@@ -69,7 +69,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
context.update({ context.update({
"items": get_product_list_for_group(product_group = self.name, start=start, "items": get_product_list_for_group(product_group = self.name, start=start,
limit=context.page_length + 1, search=frappe.form_dict.get("search")), limit=context.page_length + 1, search=frappe.form_dict.get("search")),
"parent_groups": get_parent_item_groups(self.name), "parents": get_parent_item_groups(self.parent_item_group),
"title": self.name, "title": self.name,
"products_as_list": cint(frappe.db.get_single_value('Website Settings', 'products_as_list')) "products_as_list": cint(frappe.db.get_single_value('Website Settings', 'products_as_list'))
}) })
@@ -136,7 +136,8 @@ def get_group_item_count(item_group):
def get_parent_item_groups(item_group_name): def get_parent_item_groups(item_group_name):
item_group = frappe.get_doc("Item Group", item_group_name) item_group = frappe.get_doc("Item Group", item_group_name)
return frappe.db.sql("""select name, route from `tabItem Group` return [{"name": frappe._("Home"), "route":"/"}]+\
frappe.db.sql("""select name, route from `tabItem Group`
where lft <= %s and rgt >= %s where lft <= %s and rgt >= %s
and show_in_website=1 and show_in_website=1
order by lft asc""", (item_group.lft, item_group.rgt), as_dict=True) order by lft asc""", (item_group.lft, item_group.rgt), as_dict=True)
@@ -146,6 +147,6 @@ def invalidate_cache_for(doc, item_group=None):
item_group = doc.name item_group = doc.name
for d in get_parent_item_groups(item_group): for d in get_parent_item_groups(item_group):
d = frappe.get_doc("Item Group", d.name) item_group_name = frappe.db.get_value("Item Group", d.get('name'))
if d.route: if item_group_name:
clear_cache(d.route) clear_cache(frappe.db.get_value('Item Group', item_group_name, 'route'))

View File

@@ -351,7 +351,7 @@ def create_items(args):
for i in xrange(1,6): for i in xrange(1,6):
item = args.get("item_" + str(i)) item = args.get("item_" + str(i))
if item: if item:
item_group = args.get("item_group_" + str(i)) item_group = _(args.get("item_group_" + str(i)))
is_sales_item = args.get("is_sales_item_" + str(i)) is_sales_item = args.get("is_sales_item_" + str(i))
is_purchase_item = args.get("is_purchase_item_" + str(i)) is_purchase_item = args.get("is_purchase_item_" + str(i))
is_stock_item = item_group!=_("Services") is_stock_item = item_group!=_("Services")
@@ -373,7 +373,7 @@ def create_items(args):
"is_purchase_item": is_purchase_item, "is_purchase_item": is_purchase_item,
"is_stock_item": is_stock_item and 1 or 0, "is_stock_item": is_stock_item and 1 or 0,
"item_group": item_group, "item_group": item_group,
"stock_uom": args.get("item_uom_" + str(i)), "stock_uom": _(args.get("item_uom_" + str(i))),
"default_warehouse": default_warehouse "default_warehouse": default_warehouse
}).insert() }).insert()

View File

@@ -146,10 +146,6 @@ class Item(WebsiteGenerator):
return cstr(frappe.db.get_value('Item Group', self.item_group, return cstr(frappe.db.get_value('Item Group', self.item_group,
'route')) + '/' + self.scrub(self.item_name + '-' + random_string(5)) 'route')) + '/' + self.scrub(self.item_name + '-' + random_string(5))
def get_parents(self, context):
item_group, route = frappe.db.get_value('Item Group', self.item_group, ['name', 'route'])
context.parents = [{'name': route, 'label': item_group}]
def validate_website_image(self): def validate_website_image(self):
"""Validate if the website image is a public file""" """Validate if the website image is a public file"""
auto_set_website_image = False auto_set_website_image = False
@@ -242,15 +238,12 @@ class Item(WebsiteGenerator):
context.show_search=True context.show_search=True
context.search_link = '/product_search' context.search_link = '/product_search'
context.parent_groups = get_parent_item_groups(self.item_group) + \ context.parents = get_parent_item_groups(self.item_group)
[{"name": self.name}]
self.set_variant_context(context) self.set_variant_context(context)
self.set_attribute_context(context) self.set_attribute_context(context)
self.set_disabled_attributes(context) self.set_disabled_attributes(context)
self.get_parents(context)
return context return context
def set_variant_context(self, context): def set_variant_context(self, context):

View File

@@ -1597,7 +1597,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": ":Company", "default": ":Company",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2044,7 +2044,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-16 17:23:01.404744", "modified": "2017-07-10 06:31:31.457497",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Purchase Receipt Item", "name": "Purchase Receipt Item",

View File

@@ -85,6 +85,10 @@ class SerialNo(StockController):
self.supplier, self.supplier_name = \ self.supplier, self.supplier_name = \
frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no, frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no,
["supplier", "supplier_name"]) ["supplier", "supplier_name"])
# If sales return entry
if self.purchase_document_type == 'Delivery Note':
self.sales_invoice = None
else: else:
for fieldname in ("purchase_document_type", "purchase_document_no", for fieldname in ("purchase_document_type", "purchase_document_no",
"purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"): "purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"):

View File

@@ -960,7 +960,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:cint(frappe.sys_defaults.auto_accounting_for_stock)", "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
"fieldname": "expense_account", "fieldname": "expense_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1020,7 +1020,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": ":Company", "default": ":Company",
"depends_on": "eval:cint(frappe.sys_defaults.auto_accounting_for_stock)", "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1266,7 +1266,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-16 17:32:56.989049", "modified": "2017-07-10 06:29:22.805345",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock Entry Detail", "name": "Stock Entry Detail",

View File

@@ -1,48 +1,216 @@
$.extend(frappe.test_data, { $.extend(frappe.test_data, {
'Customer': { "Customer": {
'Test Customer 1': [ "Test Customer 1": [
{customer_name: 'Test Customer 1'} {customer_name: "Test Customer 1"}
], ],
'Test Customer 2': [ "Test Customer 2": [
{customer_name: 'Test Customer 2'} {customer_name: "Test Customer 2"}
], ],
'Test Customer 3': [ "Test Customer 3": [
{customer_name: 'Test Customer 3'} {customer_name: "Test Customer 3"}
], ],
}, },
'Item': { "Item": {
'Test Product 1': [ "Test Product 1": [
{item_code: 'Test Product 1'}, {item_code: "Test Product 1"},
{item_group: 'Products'}, {item_group: "Products"},
{is_stock_item: 1}, {is_stock_item: 1},
{standard_rate: 100}, {standard_rate: 100},
{opening_stock: 100}, {opening_stock: 100},
], ],
'Test Product 2': [ "Test Product 2": [
{item_code: 'Test Product 2'}, {item_code: "Test Product 2"},
{item_group: 'Products'}, {item_group: "Products"},
{is_stock_item: 1}, {is_stock_item: 1},
{standard_rate: 150}, {standard_rate: 150},
{opening_stock: 200}, {opening_stock: 200},
], ],
'Test Product 3': [ "Test Product 3": [
{item_code: 'Test Product 3'}, {item_code: "Test Product 3"},
{item_group: 'Products'}, {item_group: "Products"},
{is_stock_item: 1}, {is_stock_item: 1},
{standard_rate: 250}, {standard_rate: 250},
{opening_stock: 100}, {opening_stock: 100},
], ],
'Test Service 1': [ "Test Service 1": [
{item_code: 'Test Service 1'}, {item_code: "Test Service 1"},
{item_group: 'Services'}, {item_group: "Services"},
{is_stock_item: 0}, {is_stock_item: 0},
{standard_rate: 200} {standard_rate: 200}
], ],
'Test Service 2': [ "Test Service 2": [
{item_code: 'Test Service 2'}, {item_code: "Test Service 2"},
{item_group: 'Services'}, {item_group: "Services"},
{is_stock_item: 0}, {is_stock_item: 0},
{standard_rate: 300} {standard_rate: 300}
] ]
},
"Lead": {
"LEAD-00001": [
{lead_name: "Test Lead 1"}
],
"LEAD-00002": [
{lead_name: "Test Lead 2"}
],
"LEAD-00003": [
{lead_name: "Test Lead 3"}
]
},
"Address": {
"Test1-Billing": [
{address_title:"Test1"},
{address_type: "Billing"},
{address_line1: "Billing Street 1"},
{city: "Billing City 1"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 1"}
]
]}
],
"Test1-Shipping": [
{address_title:"Test1"},
{address_type: "Shipping"},
{address_line1: "Shipping Street 1"},
{city: "Shipping City 1"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 1"}
]
]}
],
"Test1-Warehouse": [
{address_title:"Test1"},
{address_type: "Warehouse"},
{address_line1: "Warehouse Street 1"},
{city: "Warehouse City 1"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 1"}
]
]}
],
"Test2-Billing": [
{address_title:"Test2"},
{address_type: "Billing"},
{address_line1: "Billing Street 2"},
{city: "Billing City 2"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 2"}
]
]}
],
"Test2-Shipping": [
{address_title:"Test2"},
{address_type: "Shipping"},
{address_line1: "Shipping Street 2"},
{city: "Shipping City 2"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 2"}
]
]}
],
"Test2-Warehouse": [
{address_title:"Test2"},
{address_type: "Warehouse"},
{address_line1: "Warehouse Street 2"},
{city: "Warehouse City 2"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 2"}
]
]}
]
},
"Contact": {
"Contact 1-Test Customer 1": [
{first_name: "Contact 1"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 1"}
]
]}
],
"Contact 2-Test Customer 1": [
{first_name: "Contact 2"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 1"}
]
]}
],
"Contact 1-Test Customer 2": [
{first_name: "Contact 1"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 2"}
]
]}
],
"Contact 2-Test Customer 2": [
{first_name: "Contact 2"},
{links: [
[
{link_doctype: "Customer"},
{link_name: "Test Customer 2"}
]
]}
],
},
"Price List": {
"Test-Buying-USD": [
{price_list_name: "Test-Buying-USD"},
{currency: "USD"},
{buying: "1"}
],
"Test-Buying-EUR": [
{price_list_name: "Test-Buying-EUR"},
{currency: "EUR"},
{buying: "1"}
],
"Test-Selling-USD": [
{price_list_name: "Test-Selling-USD"},
{currency: "USD"},
{selling: "1"}
],
"Test-Selling-EUR": [
{price_list_name: "Test-Selling-EUR"},
{currency: "EUR"},
{selling: "1"}
],
},
"Terms and Conditions": {
"Test Term 1": [
{title: "Test Term 1"}
],
"Test Term 2": [
{title: "Test Term 2"}
]
},
"Sales Taxes and Charges Template": {
"TEST In State GST": [
{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")) }
]
]}
]
} }
}); });

View File

@@ -1,29 +1,120 @@
QUnit.module('sales'); QUnit.module("sales");
QUnit.test("test quotation", function(assert) { QUnit.test("test: lead", function (assert) {
assert.expect(2); assert.expect(1);
let done = assert.async();
let random = frappe.utils.get_random(10);
frappe.run_serially([
() => frappe.tests.setup_doctype("Lead"),
() => frappe.set_route("List", "Lead"),
() => frappe.new_doc("Lead"),
() => cur_frm.set_value("lead_name", random),
() => cur_frm.save(),
() => {
assert.ok(cur_frm.doc.lead_name.includes(random));
return done();
}
]);
});
QUnit.test("test: opportunity", function (assert) {
assert.expect(1);
let done = assert.async(); let done = assert.async();
frappe.run_serially([ frappe.run_serially([
() => frappe.tests.setup_doctype('Customer'),
() => frappe.tests.setup_doctype('Item'),
() => { () => {
return frappe.tests.make('Quotation', [ return frappe.tests.make("Opportunity", [{
{customer: 'Test Customer 1'}, enquiry_from: "Lead"
{items: [ },
[ {
{'item_code': 'Test Product 1'}, lead: "LEAD-00002"
{'qty': 5} }
]);
},
() => {
assert.ok(cur_frm.doc.lead === "LEAD-00002");
return done();
}
]);
});
QUnit.test("test: quotation", function (assert) {
assert.expect(18);
let done = assert.async();
frappe.run_serially([
() => frappe.tests.setup_doctype("Customer"),
() => frappe.tests.setup_doctype("Item"),
() => frappe.tests.setup_doctype("Address"),
() => frappe.tests.setup_doctype("Contact"),
() => frappe.tests.setup_doctype("Price List"),
() => frappe.tests.setup_doctype("Terms and Conditions"),
() => frappe.tests.setup_doctype("Sales Taxes and Charges Template"),
() => {
return frappe.tests.make("Quotation", [{
customer: "Test Customer 1"
},
{
items: [
[{
"item_code": "Test Product 1"
},
{
"qty": 5
}
] ]
]} ]
}
]); ]);
}, },
() => { () => {
// get_item_details // get_item_details
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1'); assert.ok(cur_frm.doc.items[0].item_name == "Test Product 1", "Added Test Product 1");
// calculate_taxes_and_totals // calculate_taxes_and_totals
assert.ok(cur_frm.doc.grand_total==500); assert.ok(cur_frm.doc.grand_total === 500, "Total Amount is correct");
}, },
() => cur_frm.set_value("customer_address", "Test1-Billing"),
() => cur_frm.set_value("shipping_address_name", "Test1-Warehouse"),
() => cur_frm.set_value("contact_person", "Contact 1-Test Customer 1"),
() => cur_frm.set_value("currency", "USD"),
() => frappe.timeout(0.3),
() => cur_frm.set_value("selling_price_list", "Test-Selling-USD"),
() => frappe.timeout(0.5),
() => cur_frm.doc.items[0].rate = 200,
() => frappe.timeout(0.3),
() => cur_frm.set_value("tc_name", "Test Term 1"),
() => cur_frm.set_value("taxes_and_charges", "TEST In State GST"),
() => frappe.timeout(0.3),
() => cur_frm.save(),
() => {
// Check Address and Contact Info
assert.ok(cur_frm.doc.address_display.includes("Billing Street 1"), "Address Changed");
assert.ok(cur_frm.doc.shipping_address.includes("Warehouse Street 1"), "Address Changed");
assert.ok(cur_frm.doc.contact_display == "Contact 1", "Contact info changed");
// Check Currency
assert.ok(cur_frm.doc_currency == "USD", "Currency Changed");
assert.ok(cur_frm.doc.selling_price_list == "Test-Selling-USD", "Price List Changed");
assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually");
assert.ok(cur_frm.doc.total == 1000, "New Total Calculated");
// Check Terms and Condtions
assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked");
// Check Taxes
assert.ok(cur_frm.doc.taxes[0].account_head.includes("CGST"));
assert.ok(cur_frm.doc.taxes[1].account_head.includes("SGST"));
assert.ok(cur_frm.doc.grand_total == 1180, "Tax Amount Added to Total");
assert.ok(cur_frm.doc.taxes_and_charges == "TEST In State GST", "Tax Template Selected");
},
() => frappe.timeout(0.3),
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"),
() => assert.ok(RegExp(/QTN-\d\d\d\d\d/g).test($("#header-html small").text())),
() => assert.ok($(".important .text-right.value").text().includes("$ 1,180.00")),
() => assert.ok($(".section-break+ .section-break .column-break:nth-child(1) .data-field:nth-child(1) .value").text().includes("Billing Street 1"), "Print Preview Works As Expected"),
() => frappe.timeout(0.3),
() => cur_frm.print_doc(),
() => done() () => done()
]); ]);
}); });