Compare commits

...

55 Commits

Author SHA1 Message Date
Nabin Hait
f7d81c7a7f Merge branch 'develop' 2017-04-25 20:44:54 +05:30
Nabin Hait
5b73a4864a bumped to version 8.0.18 2017-04-25 21:14:54 +06:00
Nabin Hait
85622f9ccb Update update_status_as_paid_for_completed_expense_claim.py 2017-04-25 20:43:29 +05:30
pawan
c27d9f712b Add Report Links 2017-04-25 20:12:55 +05:30
Umair Sayyed
175646572a updated help pages 2017-04-25 16:27:50 +05:30
Nabin Hait
7cfacb315b Merge branch 'RicardoJohann-accumulated_header_std' into develop 2017-04-25 16:26:53 +05:30
Nabin Hait
d5d8db7a3f Cleanup on financial statement PR 2017-04-25 16:26:33 +05:30
Nabin Hait
39bcb3de4b Merge branch 'accumulated_header_std' of https://github.com/RicardoJohann/erpnext into RicardoJohann-accumulated_header_std 2017-04-25 16:13:54 +05:30
Ishan Loya
09fe8e0522 Add bank guarantee to Accounts module display screen 2017-04-25 16:08:22 +05:30
Ishan Loya
17737e4ab1 Change permissions, change account fieldname and add notes section 2017-04-25 16:08:22 +05:30
Ishan Loya
2fca72ae8e Change owner 2017-04-25 16:08:22 +05:30
Ishan Loya
0dbe8547e7 Add screenshot to documentation, change naming series to BG-#####, make Bank Guarantee number unique 2017-04-25 16:08:22 +05:30
Ishan Loya
e1ed5ba726 Remove commented out code 2017-04-25 16:08:22 +05:30
Ishan Loya
0fc57a7df2 Change doctype owner 2017-04-25 16:08:22 +05:30
Ishan Loya
c7a72684fd Add bank guarantee doctype with documentation 2017-04-25 16:08:22 +05:30
Nabin Hait
e0c34bfd77 Merge branch 'PawanMeh-fixes_8466' into develop 2017-04-25 16:05:28 +05:30
Nabin Hait
020dedd00e Cleaned up and commonified the campaign efficiency and lead owner efficiency report 2017-04-25 16:05:01 +05:30
Nabin Hait
28dad095fa Merge branch 'fixes_8466' of https://github.com/PawanMeh/erpnext into PawanMeh-fixes_8466 2017-04-25 15:00:45 +05:30
Nabin Hait
e7125c0ea2 Merge branch 'develop' 2017-04-25 14:30:50 +05:30
Nabin Hait
8590d5b05d bumped to version 8.0.17 2017-04-25 15:00:50 +06:00
sburanaw
66951e528f Fix an import typo in get_item_details.py 2017-04-25 14:09:51 +05:30
Nabin Hait
9b20e07431 [fix] currency field precision 2017-04-25 14:09:29 +05:30
Manas Solanki
d7afa69c6f fix 2017-04-25 14:08:43 +05:30
Manas Solanki
c61dc9c7ea Change in the assessment tool 2017-04-25 14:08:43 +05:30
mbauskar
9cf6d630e9 [minor] fixes for expense claim status 2017-04-25 13:15:50 +05:30
Faris Ansari
5687e2da9d [ui-fix] POS item list 2017-04-24 19:22:05 +05:30
Nabin Hait
e3c122d8c4 AR report: filter based on customer group and credit days based on field. Fixed #8214 2017-04-24 19:06:07 +05:30
Nabin Hait
4cc5e61f60 Update course_schedule.py 2017-04-24 19:00:49 +05:30
Manas Solanki
6293263095 test case fixed 2017-04-24 19:00:49 +05:30
Manas Solanki
810e483757 Changes in the student group 2017-04-24 19:00:49 +05:30
Nabin Hait
398f144833 Merge branch 'develop' 2017-04-24 18:59:01 +05:30
Nabin Hait
e2741e85fd bumped to version 8.0.16 2017-04-24 19:29:01 +06:00
Rohit Waghchaure
dd70fbfdae [fix] Letter head not showing in the report 2017-04-24 18:57:51 +05:30
Manas Solanki
6eaf281b2b Export and import program enrollments 2017-04-24 18:44:12 +05:30
pawan
134487ab2a Changes after review 2017-04-24 13:48:40 +05:30
pawan
7bd7df3742 Changes after review 2017-04-24 13:19:22 +05:30
Ishan Loya
56c1b2a625 Make proposed corrections 2017-04-24 10:44:36 +05:30
Ishan Loya
b12e15dcc4 Change modified by 2017-04-24 10:44:36 +05:30
Ishan Loya
e5fdd47fd8 Hide 'Qty Transferred for Manufacturing' field if skip material transfer 2017-04-24 10:44:36 +05:30
Ishan Loya
04c69fb46d Minor fix 2017-04-24 10:44:36 +05:30
Ishan Loya
f04ef8dfe0 Update documentation for Production Order skipping material transfer entry option 2017-04-24 10:44:36 +05:30
Ishan Loya
7544904857 Add option to skip material transfer for production orders 2017-04-24 10:44:36 +05:30
Rushabh Mehta
c44910370b [fix] is_sample_item 2017-04-24 10:28:38 +05:30
Rushabh Mehta
551406ab11 [enhance] automatic batch selection in Delivery Note and Stock Entry 2017-04-24 10:28:38 +05:30
Rushabh Mehta
e385b5b97b [enhance] automatic batch creation, move and split 2017-04-24 10:28:38 +05:30
mbauskar
bb2670d57a [fixes] minor fixes in bank reconciliation form and report 2017-04-24 10:23:50 +05:30
mbauskar
0b293133be [minor] fixes for unsupported operand type(s) for +=: 'int' and 'NoneType' 2017-04-21 21:40:30 +05:30
ibi
83c1c3a171 fleet_management: replace references to fleet_management by hr in vehicle_log doctype 2017-04-21 17:57:07 +05:30
mbauskar
c3d642e5d1 [minor] allow bulk edit for doctype 2017-04-21 17:50:40 +05:30
Manas Solanki
8230ce095f [Fix] fixed routing to the assessment result 2017-04-21 17:49:52 +05:30
Nabin Hait
e713a7d840 Merge branch 'develop' 2017-04-21 11:49:09 +05:30
Nabin Hait
557847a5ba bumped to version 8.0.15 2017-04-21 12:19:09 +06:00
mbauskar
9bac58cdc6 [fixes] fixes in setup wizard for education domain 2017-04-21 11:38:28 +05:30
pawan
83c8ed0827 ”[fix] 2017-04-17 01:02:56 +05:30
Ricardo Johann
033e2fa8b6 changed accumulated header 2017-03-31 02:18:54 -03:00
103 changed files with 5929 additions and 3764 deletions

View File

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

View File

@@ -0,0 +1,30 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bank Guarantee', {
refresh: function(frm) {
cur_frm.set_query("account", function() {
return {
"filters": {
"account_type": "Bank",
"is_group": 0
}
};
});
cur_frm.set_query("project", function() {
return {
"filters": {
"customer": cur_frm.doc.customer
}
};
});
},
start_date: function(frm) {
end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
validity: function(frm) {
end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
}
});

View File

@@ -0,0 +1,448 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "BG-.#####",
"beta": 0,
"creation": "2016-12-17 10:43:35.731631",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer",
"length": 0,
"no_copy": 0,
"options": "Customer",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "project",
"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": "Project",
"length": 0,
"no_copy": 0,
"options": "Project",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bank Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "start_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Start Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "validity",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Validity in Days",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "end_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "End Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "bank_guarantee_number",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bank Guarantee Number",
"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": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "section_break_10",
"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": "More Information",
"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": "more_information",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Notes",
"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": "amended_from",
"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": "Amended From",
"length": 0,
"no_copy": 1,
"options": "Bank Guarantee",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-04-25 13:31:49.627831",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Guarantee",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "customer",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "customer",
"track_changes": 0,
"track_seen": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class BankGuarantee(Document):
pass

View File

@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
# test_records = frappe.get_test_records('Bank Guarantee')
class TestBankGuarantee(unittest.TestCase):
pass

View File

@@ -3,13 +3,13 @@
frappe.ui.form.on("Bank Reconciliation", {
setup: function(frm) {
frm.get_docfield("payment_entries").allow_bulk_edit = 1;
frm.add_fetch("bank_account", "account_currency", "account_currency");
},
onload: function(frm) {
var default_bank_account = locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"];
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
frm.set_value("bank_account", default_bank_account);
frm.set_query("bank_account", function() {

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -7,11 +8,15 @@
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 0,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Select account head of the bank where cheque was deposited.",
"fieldname": "bank_account",
"fieldtype": "Link",
@@ -19,7 +24,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Bank Account",
"length": 0,
"no_copy": 0,
@@ -28,6 +35,7 @@
"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,
@@ -35,16 +43,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account_currency",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Account Currency",
"length": 0,
"no_copy": 0,
@@ -53,6 +65,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -60,16 +73,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "From Date",
"length": 0,
"no_copy": 0,
@@ -77,6 +94,7 @@
"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,
@@ -84,16 +102,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "To Date",
"length": 0,
"no_copy": 0,
@@ -101,6 +123,7 @@
"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,
@@ -108,16 +131,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "include_reconciled_entries",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Include Reconciled Entries",
"length": 0,
"no_copy": 0,
@@ -125,6 +152,7 @@
"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,
@@ -132,16 +160,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_payment_entries",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Payment Entries",
"length": 0,
"no_copy": 0,
@@ -150,6 +182,7 @@
"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,
@@ -157,16 +190,20 @@
"unique": 0
},
{
"allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "payment_entries",
"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": "Payment Entries",
"length": 0,
"no_copy": 0,
@@ -175,6 +212,7 @@
"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,
@@ -182,16 +220,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "update_clearance_date",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Update Clearance Date",
"length": 0,
"no_copy": 0,
@@ -200,6 +242,7 @@
"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,
@@ -207,16 +250,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Amount",
"length": 0,
"no_copy": 0,
@@ -225,6 +272,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -232,19 +280,19 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 1,
"hide_toolbar": 1,
"icon": "fa fa-check",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-06-28 13:11:09.396353",
"modified": "2017-04-21 16:58:26.902732",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation",
@@ -274,7 +322,8 @@
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_seen": 0,
"version": 0
"track_changes": 0,
"track_seen": 0
}

View File

@@ -514,7 +514,7 @@ class JournalEntry(AccountsController):
def update_expense_claim(self):
for d in self.accounts:
if d.reference_type=="Expense Claim" and d.party:
if d.reference_type=="Expense Claim" and d.reference_name:
doc = frappe.get_doc("Expense Claim", d.reference_name)
update_reimbursed_amount(doc)

View File

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

View File

@@ -16,6 +16,21 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
},
{
"fieldname":"credit_days_based_on",
"label": __("Credit Days Based On"),
"fieldtype": "Select",
"options": "" + NEWLINE + "Fixed Days" + NEWLINE + "Last Day of the Next Month"
},
{
"fieldtype": "Break",
},
{
"fieldname":"report_date",
"label": __("As on Date"),
@@ -29,9 +44,6 @@ frappe.query_reports["Accounts Receivable"] = {
"options": 'Posting Date' + NEWLINE + 'Due Date',
"default": "Posting Date"
},
{
"fieldtype": "Break",
},
{
"fieldname":"range1",
"label": __("Ageing Range 1"),

View File

@@ -71,7 +71,10 @@ class ReceivablePayableReport(object):
"width": 100
})
if args.get("party_type") == "Customer":
columns += [_("Territory") + ":Link/Territory:80"]
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
@@ -139,7 +142,7 @@ class ReceivablePayableReport(object):
# customer territory / supplier type
if args.get("party_type") == "Customer":
row += [self.get_territory(gle.party)]
row += [self.get_territory(gle.party), self.get_customer_group(gle.party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(gle.party)]
@@ -186,6 +189,9 @@ class ReceivablePayableReport(object):
def get_territory(self, party_name):
return self.get_party_map("Customer").get(party_name, {}).get("territory") or ""
def get_customer_group(self, party_name):
return self.get_party_map("Customer").get(party_name, {}).get("customer_group") or ""
def get_supplier_type(self, party_name):
return self.get_party_map("Supplier").get(party_name, {}).get("supplier_type") or ""
@@ -193,12 +199,12 @@ class ReceivablePayableReport(object):
def get_party_map(self, party_type):
if not hasattr(self, "party_map"):
if party_type == "Customer":
self.party_map = dict(((r.name, r) for r in frappe.db.sql("""select {0}, {1}, {2} from `tab{3}`"""
.format("name", "customer_name", "territory", party_type), as_dict=True)))
select_fields = "name, customer_name, territory, customer_group"
elif party_type == "Supplier":
self.party_map = dict(((r.name, r) for r in frappe.db.sql("""select {0}, {1}, {2} from `tab{3}`"""
.format("name", "supplier_name", "supplier_type", party_type), as_dict=True)))
select_fields = "name, supplier_name, supplier_type"
self.party_map = dict(((r.name, r) for r in frappe.db.sql("select {0} from `tab{1}`"
.format(select_fields, party_type), as_dict=True)))
return self.party_map
@@ -251,6 +257,19 @@ class ReceivablePayableReport(object):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
if party_type_field=="customer":
if self.filters.get("customer_group"):
lft, rgt = frappe.db.get_value("Customer Group",
self.filters.get("customer_group"), ["lft", "rgt"])
conditions.append("""party in (select name from tabCustomer
where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1}
and name=tabCustomer.customer_group))""".format(lft, rgt))
if self.filters.get("credit_days_based_on"):
conditions.append("party in (select name from tabCustomer where credit_days_based_on=%s)")
values.append(self.filters.get("credit_days_based_on"))
return " and ".join(conditions), values
def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher):

View File

@@ -16,6 +16,21 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
},
{
"fieldname":"credit_days_based_on",
"label": __("Credit Days Based On"),
"fieldtype": "Select",
"options": "" + NEWLINE + "Fixed Days" + NEWLINE + "Last Day of the Next Month"
},
{
"fieldtype": "Break",
},
{
"fieldname":"report_date",
"label": __("Date"),
@@ -29,9 +44,6 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"options": 'Posting Date' + NEWLINE + 'Due Date',
"default": "Posting Date"
},
{
"fieldtype": "Break",
},
{
"fieldname":"range1",
"label": __("Ageing Range 1"),

View File

@@ -27,7 +27,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
str(self.filters.range3) + _("-Above") + ":Currency/currency:100"]
if args.get("party_type") == "Customer":
columns += [_("Territory") + ":Link/Territory:80"]
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
@@ -58,7 +61,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
]
if args.get("party_type") == "Customer":
row += [self.get_territory(party)]
row += [self.get_territory(party), self.get_customer_group(party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(party)]
@@ -107,7 +110,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
if args.get("party_type") == "Supplier":
cols += ["supplier_type", "remarks"]
if args.get("party_type") == "Customer":
cols += ["territory", "remarks"]
cols += ["territory", "customer_group", "remarks"]
return self.make_data_dict(cols, voucherwise_data)

View File

@@ -3,6 +3,12 @@
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"] = erpnext.financial_statements;
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),
"fieldtype": "Check"
});
});

View File

@@ -8,11 +8,23 @@ from frappe.utils import flt, cint
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity, filters.company)
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.accumulated_values, filters.company)
asset = get_data(filters.company, "Asset", "Debit", period_list, only_current_fiscal_year=False)
liability = get_data(filters.company, "Liability", "Credit", period_list, only_current_fiscal_year=False)
equity = get_data(filters.company, "Equity", "Credit", period_list, only_current_fiscal_year=False)
asset = get_data(filters.company, "Asset", "Debit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
liability = get_data(filters.company, "Liability", "Credit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
equity = get_data(filters.company, "Equity", "Credit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
provisional_profit_loss, total_credit = get_provisional_profit_loss(asset, liability, equity,
period_list, filters.company)
@@ -43,9 +55,9 @@ def execute(filters=None):
if total_credit:
data.append(total_credit)
columns = get_columns(filters.periodicity, period_list, company=filters.company)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, company=filters.company)
chart = get_chart_data(columns, asset, liability, equity)
chart = get_chart_data(filters, columns, asset, liability, equity)
return columns, data, message, chart
@@ -107,7 +119,7 @@ def check_opening_balance(asset, liability, equity):
return _("Previous Financial Year is not closed"),opening_balance
return None,None
def get_chart_data(columns, asset, liability, equity):
def get_chart_data(filters, columns, asset, liability, equity):
x_intervals = ['x'] + [d.get("label") for d in columns[2:]]
asset_data, liability_data, equity_data = [], [], []
@@ -128,9 +140,14 @@ def get_chart_data(columns, asset, liability, equity):
if equity_data:
columns.append(["Equity"] + equity_data)
return {
chart = {
"data": {
'x': 'x',
'columns': columns
}
}
if not filters.accumulated_values:
chart["chart_type"] = "bar"
return chart

View File

@@ -22,7 +22,8 @@ frappe.query_reports["Bank Clearance Summary"] = {
"fieldtype": "Link",
"options": "Account",
"reqd": 1,
"default": locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"],
"default": frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
"get_query": function() {
return {
"query": "erpnext.controllers.queries.get_account_list",

View File

@@ -8,7 +8,8 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
"label": __("Bank Account"),
"fieldtype": "Link",
"options": "Account",
"default": locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"],
"default": frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
"reqd": 1,
"get_query": function() {
return {

View File

@@ -11,7 +11,7 @@ from erpnext.accounts.utils import get_fiscal_year
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.company)
filters.periodicity, filters.accumulated_values, filters.company)
operation_accounts = {
"section_name": "Operations",

View File

@@ -13,12 +13,16 @@
height: 37px;
}
</style>
{% var letterhead= filters.letter_head || 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[frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head")] %}
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.company %}</h3>
<h4 class="text-center">{%= filters.fiscal_year %}</h3>
<h3 class="text-center">{%= filters.company %}</h3>
<h3 class="text-center">{%= filters.fiscal_year %}</h3>
<h5 class="text-center">{%= __("Currency") %} : {%= erpnext.get_currency(filters.company) %} </h4>
{% if (filters.from_date) { %}
<h4 class="text-center">{%= dateutil.str_to_user(filters.from_date) %} - {%= dateutil.str_to_user(filters.to_date) %}</h3>
{% } %}
@@ -47,7 +51,7 @@
<td class="text-right">
{% var fieldname = report.columns[i].field; %}
{% if (!is_null(row[fieldname])) { %}
{%= format_currency(row[fieldname], row.currency) %}
{%= format_number(row[fieldname], null)%}
{% } %}
</td>
{% } %}

View File

@@ -4,9 +4,10 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, getdate, get_first_day, add_months, add_days, formatdate
from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff,
add_months, add_days, formatdate, cint)
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, company):
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False, company=None):
"""Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
Periodicity can be (Yearly, Quarterly, Monthly)"""
@@ -58,11 +59,14 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, company):
# common processing
for opts in period_list:
key = opts["to_date"].strftime("%b_%Y").lower()
if periodicity == "Monthly":
if periodicity == "Monthly" and not accumulated_values:
label = formatdate(opts["to_date"], "MMM YYYY")
else:
label = get_label(periodicity, opts["from_date"], opts["to_date"])
if not accumulated_values:
label = get_label(periodicity, opts["from_date"], opts["to_date"])
else:
label = get_label(periodicity, period_list[0]["from_date"], opts["to_date"])
opts.update({
"key": key.replace(" ", "_").replace("-", "_"),
"label": label,
@@ -139,7 +143,8 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accum
if entry.posting_date <= period.to_date:
if (accumulated_values or entry.posting_date >= period.from_date) and \
(not ignore_accumulated_values_for_fy or entry.fiscal_year == period.to_date_fiscal_year):
(not ignore_accumulated_values_for_fy or
entry.fiscal_year == period.to_date_fiscal_year):
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
if entry.posting_date < period_list[0].year_start_date:

View File

@@ -1,6 +1,9 @@
{% var letterhead= filters.letter_head || 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[filters.letter_head || frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head")] %}
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __("Statement of Account") %}</h2>
<h4 class="text-center">{%= (filters.party || filters.account) && ((filters.party || filters.account) + ", ") || "" %} {%= filters.company %}</h4>
<h5 class="text-center">

View File

@@ -9,12 +9,15 @@ from erpnext.accounts.report.financial_statements import (get_period_list, get_c
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.company)
filters.periodicity, filters.accumulated_values, filters.company)
income = get_data(filters.company, "Income", "Credit", period_list, filters = filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company)

View File

@@ -4,13 +4,13 @@
from __future__ import unicode_literals
import frappe
import frappe.defaults
from frappe.utils import nowdate, cstr, flt, cint, now, getdate
from frappe import throw, _
from frappe.utils import formatdate
from frappe.utils import formatdate, get_number_format_info
# imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency
import frappe.defaults
from erpnext.accounts.report.financial_statements import sort_root_accounts
class FiscalYearError(frappe.ValidationError): pass
@@ -537,15 +537,14 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
return difference
def get_currency_precision(currency=None):
if not currency:
currency = frappe.db.get_value("Company",
frappe.db.get_default("Company"), "default_currency", cache=True)
currency_format = frappe.db.get_value("Currency", currency, "number_format", cache=True)
from frappe.utils import get_number_format_info
return get_number_format_info(currency_format)[2]
def get_currency_precision():
precision = cint(frappe.db.get_default("currency_precision"))
if not precision:
number_format = frappe.db.get_default("number_format") or "#,###.##"
precision = get_number_format_info(number_format)[2]
return precision
def get_stock_rbnb_difference(posting_date, company):
stock_items = frappe.db.sql_list("""select distinct item_code
from `tabStock Ledger Entry` where company=%s""", company)

View File

@@ -800,7 +800,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "9",
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"print_width": "100px",
@@ -1659,7 +1659,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-04-18 18:49:08.604055",
"modified": "2017-04-25 18:49:08.604055",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -159,6 +159,11 @@ def get_data():
"is_query_report": True,
"doctype": "Journal Entry"
},
{
"type": "doctype",
"name": "Bank Guarantee",
"doctype": "Bank Guarantee"
},
]
},
{

View File

@@ -68,6 +68,18 @@ def get_data():
"name": "Inactive Customers",
"doctype": "Sales Order"
},
{
"type": "report",
"is_query_report": True,
"name": "Campaign Efficiency",
"doctype": "Lead"
},
{
"type": "report",
"is_query_report": True,
"name": "Lead Owner Efficiency",
"doctype": "Lead"
}
]
},
{

View File

@@ -177,6 +177,19 @@ class StockController(AccountsController):
stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
return stock_ledger
def make_batches(self, warehouse_field):
'''Create batches if required. Called before submit'''
for d in self.items:
if d.get(warehouse_field) and not d.batch_no:
has_batch_no, create_new_batch = frappe.db.get_value('Item', d.item_code, ['has_batch_no', 'create_new_batch'])
if has_batch_no and create_new_batch:
d.batch_no = frappe.get_doc(dict(
doctype='Batch',
item=d.item_code,
supplier=getattr(self, 'supplier', None),
reference_doctype=self.doctype,
reference_name=self.name)).insert().name
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]

View File

@@ -0,0 +1,19 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Campaign Efficiency"] = {
"filters": [
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
}
]
};

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-04-17 00:20:27.248275",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
"modified": "2017-04-17 00:20:27.248275",
"modified_by": "Administrator",
"module": "CRM",
"name": "Campaign Efficiency",
"owner": "Administrator",
"ref_doctype": "Lead",
"report_name": "Campaign Efficiency",
"report_type": "Script Report",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
},
{
"role": "System Manager"
}
]
}

View File

@@ -0,0 +1,89 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
def execute(filters=None):
columns, data = [], []
columns=get_columns()
data=get_lead_data(filters, "Campaign Name")
return columns, data
def get_columns():
return [
_("Campaign Name") + ":data:130",
_("Lead Count") + ":Int:80",
_("Opp Count") + ":Int:80",
_("Quot Count") + ":Int:80",
_("Order Count") + ":Int:100",
_("Order Value") + ":Float:100",
_("Opp/Lead %") + ":Float:100",
_("Quot/Lead %") + ":Float:100",
_("Order/Quot %") + ":Float:100"
]
def get_lead_data(filters, based_on):
based_on_field = frappe.scrub(based_on)
conditions = get_filter_conditions(filters)
lead_details = frappe.db.sql("""
select {based_on_field}, name
from `tabLead`
where {based_on_field} is not null and {based_on_field} != '' {conditions}
""".format(based_on_field=based_on_field, conditions=conditions), filters, as_dict=1)
lead_map = frappe._dict()
for d in lead_details:
lead_map.setdefault(d.get(based_on_field), []).append(d.name)
data = []
for based_on_value, leads in lead_map.items():
row = {
based_on: based_on_value,
"Lead Count": len(leads)
}
row["Quot Count"]= get_lead_quotation_count(leads)
row["Opp Count"] = get_lead_opp_count(leads)
row["Order Count"] = get_quotation_ordered_count(leads)
row["Order Value"] = get_order_amount(leads)
row["Opp/Lead %"] = row["Opp Count"] / row["Lead Count"] * 100
row["Quot/Lead %"] = row["Quot Count"] / row["Lead Count"] * 100
row["Order/Quot %"] = row["Order Count"] / (row["Quot Count"] or 1) * 100
data.append(row)
return data
def get_filter_conditions(filters):
conditions=""
if filters.from_date:
conditions += " and date(creation) >= %(from_date)s"
if filters.to_date:
conditions += " and date(creation) <= %(to_date)s"
return conditions
def get_lead_quotation_count(leads):
return frappe.db.sql("""select count(name) from `tabQuotation`
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
def get_lead_opp_count(leads):
return frappe.db.sql("""select count(name) from `tabOpportunity`
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
def get_quotation_ordered_count(leads):
return frappe.db.sql("""select count(name)
from `tabQuotation` where status = 'Ordered'
and lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
def get_order_amount(leads):
return frappe.db.sql("""select sum(base_net_amount)
from `tabSales Order Item`
where prevdoc_docname in (
select name from `tabQuotation` where status = 'Ordered'
and lead in (%s)
)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Lead Owner Efficiency"] = {
"filters": [
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
}
]};

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-04-17 00:39:39.885905",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
"modified": "2017-04-17 00:45:10.139004",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead Owner Efficiency",
"owner": "Administrator",
"ref_doctype": "Lead",
"report_name": "Lead Owner Efficiency",
"report_type": "Script Report",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
},
{
"role": "System Manager"
}
]
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.crm.report.campaign_efficiency.campaign_efficiency import get_lead_data
def execute(filters=None):
columns, data = [], []
columns=get_columns()
data=get_lead_data(filters, "Lead Owner")
return columns, data
def get_columns():
return [
_("Lead Owner") + ":Data:130",
_("Lead Count") + ":Int:80",
_("Opp Count") + ":Int:80",
_("Quot Count") + ":Int:80",
_("Order Count") + ":Int:100",
_("Order Value") + ":Float:100",
_("Opp/Lead %") + ":Float:100",
_("Quot/Lead %") + ":Float:100",
_("Order/Quot %") + ":Float:100"
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,9 @@
A Bank Guarantee is a guarantee from a lending institution such as a bank ensuring the liabilities of a debtor will be met. In other words, if the debtor fails to settle a debt, the bank covers it. A Bank Guarantee enables the customer, or debtor, to acquire goods, buy equipment or draw down loans, and thereby expand business activity.
A client may ask you to provide a Bank Guarantee from a third party such as a bank. This guarantee is for a specified amount, which is usually a percentage of the total value of the contract. The Bank Guarantee is valid for a specified duration after which it expires and must be returned to you by the client.
This document allows you to track Bank Guarantees given to clients. You can set Email Alerts as the Bank Guarantee expiry date approaches to remind yourself to get the Bank Guarantee back from your client.
<img class="screenshot" alt="Bank Guarantee" src="{{docs_base_url}}/assets/img/accounts/bank-guarantee.png">
{next}

View File

@@ -10,6 +10,7 @@ multi-currency-accounting
advance-payment-entry
payment-request
credit-limit
bank-guarantee
accounting-reports
accounting-entries
managing-fixed-assets

View File

@@ -1,29 +1,35 @@
Taxes selected in the Tax and Other Charges in transactions are applied on all the items. If you need different taxes applied on items selected in the same transaction, you should setup you item and tax master as explained in the steps below.
In the sales and purchase transactions, you can apply taxes and other charges on the items. For the ease of applying taxes, you can fetch values from the [Sales Taxes and Charges master](/contents//setting-up/setting-up-taxes). Taxes and charges are applied equally on all the items. For example, if tax GST 16% is added in the tax table, then it will be applied on all the items. However, if you need to have different tax rate applied on some of the items, following is how you should setup Items and Sales Taxes and Other Charges master in your ERPNext account.
Let's assume that we are creating a Sales Order. We have Sales Taxes and Charges master for GST 16%. Out of all the Sales Items, on one item, only 12% GST will be applied, while one more item is exempted from the tax.
####Step 1: Mention Tax Applicable in the Item master
Item master has tax table where you can list taxes which will be applied on it.
Items on which differential tax rate is applied, you should mention tax rate for that item in the Item master itself. Item master has tax table where you can list taxes which will be applied on it.
![Item wise Tax]({{docs_base_url}}/assets/old_images/erpnext/item-wise-tax.png)
> Tax rate mentioned in the item master gets preference over tax rate entered in the transactions.
Tax rate mentioned in the item master gets preference over tax rate entered in the transactions.
Here is the example of Item on which 12% GST is applied only.
For example, if you provide tax rate for VAT as 10% for item ABC, where for same VAT ledger 12% rate is entered in the Sales Order/Invoice, for item ABC, tax rate applied would be 10%, as mentioned in the item master.
<img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/item-wise-tax.png">
For the item which is exempted from GST totally, mention 0% as tax rate in the Item master.
<img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/exempted-item.png">
####Step 2: Setup Taxes and Other Charges
In Taxes and Other Charges master, you should select all the applicable taxes which could be applicable on item.
In Sales Taxes and Other Charges master, select GST 16% account and mention Tax Rate as 16. This tax rate will be applied on all the Items selected in the Sales Order, unless specific Tax Rate is defined in the Item master.
For example, if few items has VAT 5 applied on them, other has Service Tax applied, and some other has Excise Duty applicable, then you tax master should have all these taxes selected.
<img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/tax-master.png">
![item wise tax master]({{docs_base_url}}/assets/old_images/erpnext/item-wise-tax-master.png)
<div class="well">If you want to have tax rate always applied from the Item master, then you should update Rate for the tax account as zero in the Taxes and Charges master.</div>
####Step 3: Set Tax Rate as Zero in Taxes and Charges Template
####Step 3: Tax Calculation in transaction
In the Taxes and Other Charges master, tax rate will be updated as ZERO. It means, tax rate applicable on items will be pulled from the respective Item master. While for other items, 0% tax will be applied, means no other taxes will be applied on that item.
In the Sales Order, we have selected many Items. For the items mentioned in blue, tax rate is applied based on tax rate mentioned in the taxes table. For the items highlited in red, tax rate has fetched for them from the respective item master.
Based on the above setting, you will have taxes applied on items as mentioned in the respective item master. Check following for an instance.
<img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/tax-calulation.png">
![item wise tax calculation]({{docs_base_url}}/assets/old_images/erpnext/item-wise-tax-calc.png)
Please note that item's tax rate will be pulled from the item master only if you have update same tax account (GST 16% in this case) in both Item master and tax master.
{next}

View File

@@ -62,6 +62,13 @@ by:
<img class="screenshot" alt="Stock Entry for PO" src="{{docs_base_url}}/assets/img/manufacturing/PO-material-transfer-updated.png">
#### Material Transfer through Stock Entry
Use cases for this option are:
* If material transfer is done in bulk and/or is not required to be tracked against a particular Production Order
* If the responsibility for Material Transfer and Production Entry lies with two separate users
If this is the case, you can select the Skip Material Transfer check box, which will allow you to make the “Manufacture” Stock Entry directly by clicking on the Finish button.
### Making Time Logs
* Progress in the Production Order can be tracked using [Timesheet]({{docs_base_url}}/user/manual/en/projects/timesheet/timesheet-against-production-order.html)

View File

@@ -2,7 +2,7 @@
You can globally switch off certain desktop module via:
> Setup > Settings > Show or Hide Modules
> Setup > Permissions > Show / Hide Modules
For example if you are in the services business, you want to hide the Manufacturing Module, you can do this via **Show or Hide Modules**

View File

@@ -1,27 +1,45 @@
Batch inventory feature in ERPNext allows you to group multiple units of an item,
Batch feature in ERPNext allows you to group multiple units of an item,
and assign them a unique value/number/tag called Batch No.
The practice of stocking based on batch is mainly followed in the pharmaceutical industry.
Medicines/drugs produced in a particular batched is assigned a unique id.
This helps them updating and tracking manufacturing and expiry date for all the units produced under specific batch.
This is done based on the Item. If the Item is batched, then a Batch number must be mentioned in every stock transaction. Batch numbers can be maintained manually or automatically
> Note: To set item as a batch item, "Has Batch No" field should be updated as Yes in the Item master.
### Item Setup
On every stock transaction (Purchase Receipt, Delivery Note, POS Invoice) made for batch item,
you should provide item's Batch No.
To set item as a batch item, "Has Batch No" field should be checked in the Item master.
If you want automatic batch creation at the time of Purchase Receipt, you must check "Create New Batches Automatically"
<img class="screenshot" alt="Item Setup for Batches" src="{{docs_base_url}}/assets/img/stock/item_setup_for_batch.png">
### Creating Batches
If you have not selected "Create New Batches Automatically", you will have to make Batches Manually as you go along.
To create new Batch No. master for an item, go to:
> Stock > Setup > Batch > New
Batch master is created before creation of Purchase Receipt.
Hence eveytime there is Purchase Receipt or Production entry being made for a batch item,
you will first create its Batch No, and then select it in Purcase order or Production Entry.
### Splitting and Moving Batches
<img class="screenshot" alt="batch" src="{{docs_base_url}}/assets/img/stock/batch.png">
When you open a batch, you will see all the quantities relating this that batch on the page.
> Note: In stock transactions, Batch IDs will be filtered based on Item Code, Warehouse,
Batch Expiry Date (compared with Posting date of a transaction) and Actual Qty in Warehouse.
<img class="screenshot" alt="Batch View" src="{{docs_base_url}}/assets/img/stock/batch_view.png">
To move the batch from one warehouse to another, you can click on the move button.
You can also split the batch into smaller one by clicking on "Split". This will create a new Batch based on this Batch and the quantities will be split between the batches.
### Transacting Items with Batches
Batch master is created before creation of Purchase Receipt.
Hence eveytime there is Purchase Receipt or Production Order being made for a batch item,
you will first create its Batch No, and then select it in Purchase order or Production Entry.
On every stock transaction (Purchase Receipt, Delivery Note, POS Invoice) made for batch item,
you should provide item's Batch No.
> Note: In stock transactions, Batch IDs will be filtered based on Item Code, Warehouse,
Batch Expiry Date (compared with Posting date of a transaction) and Actual Qty in Warehouse.
While searching for Batch ID without value in Warehouse field, then Actual Qty filter won't be applied.
{next}

View File

@@ -18,14 +18,20 @@ erpnext.hr.ExpenseClaimController = frappe.ui.form.Controller.extend({
});
},
expense_type: function(frm, cdt, cdn) {
expense_type: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(!doc.company) {
d.expense_type = "";
frappe.msgprint(__("Please set the Company"));
this.frm.refresh_fields()
return;
}
return frappe.call({
method: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_claim_account",
args: {
"expense_claim_type": d.expense_type,
"company": frm.company
"company": doc.company
},
callback: function(r) {
if (r.message) {

View File

@@ -6,7 +6,7 @@ frappe.ui.form.on("Vehicle Log", {
vehicle_log=frappe.model.get_doc(cdt,cdn);
if (vehicle_log.license_plate) {
frappe.call({
method: "erpnext.fleet_management.doctype.vehicle_log.vehicle_log.get_make_model",
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model",
args: {
license_plate: vehicle_log.license_plate
},
@@ -19,7 +19,7 @@ frappe.ui.form.on("Vehicle Log", {
},
expense_claim: function(frm){
frappe.call({
method: "erpnext.fleet_management.doctype.vehicle_log.vehicle_log.make_expense_claim",
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim",
args:{
docname: frm.doc.name
},

View File

@@ -72,15 +72,17 @@ frappe.ui.form.on("Production Order", {
message = title;
// pending qty
var pending_complete = frm.doc.material_transferred_for_manufacturing - frm.doc.produced_qty;
if(pending_complete) {
var title = __('{0} items in progress', [pending_complete]);
bars.push({
'title': title,
'width': ((pending_complete / frm.doc.qty * 100) - added_min) + '%',
'progress_class': 'progress-bar-warning'
})
message = message + '. ' + title;
if(!frm.doc.skip_transfer){
var pending_complete = frm.doc.material_transferred_for_manufacturing - frm.doc.produced_qty;
if(pending_complete) {
var title = __('{0} items in progress', [pending_complete]);
bars.push({
'title': title,
'width': ((pending_complete / frm.doc.qty * 100) - added_min) + '%',
'progress_class': 'progress-bar-warning'
})
message = message + '. ' + title;
}
}
frm.dashboard.add_progress(__('Status'), bars, message);
}
@@ -122,21 +124,32 @@ erpnext.production_order = {
frm.add_custom_button(__('Re-open'), cur_frm.cscript['Unstop Production Order'], __("Status"));
}
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
if(!frm.doc.skip_transfer){
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
frm.has_start_btn = true;
var btn = frm.add_custom_button(__('Start'),
cur_frm.cscript['Transfer Raw Materials']);
btn.addClass('btn-primary');
}
}
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing)) && frm.doc.status != 'Stopped') {
frm.has_finish_btn = true;
var btn = frm.add_custom_button(__('Finish'),
cur_frm.cscript['Update Finished Goods']);
if(!frm.doc.skip_transfer){
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing)) && frm.doc.status != 'Stopped') {
frm.has_finish_btn = true;
var btn = frm.add_custom_button(__('Finish'),
cur_frm.cscript['Update Finished Goods']);
if(doc.material_transferred_for_manufacturing==doc.qty) {
// all materials transferred for manufacturing,
// make this primary
if(doc.material_transferred_for_manufacturing==doc.qty) {
// all materials transferred for manufacturing,
// make this primary
btn.addClass('btn-primary');
}
}
} else {
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
frm.has_finish_btn = true;
var btn = frm.add_custom_button(__('Finish'),
cur_frm.cscript['Update Finished Goods']);
btn.addClass('btn-primary');
}
}
@@ -235,9 +248,13 @@ $.extend(cur_frm.cscript, {
make_se: function(purpose) {
var me = this;
var max = (purpose === "Manufacture") ?
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
if(!this.frm.doc.skip_transfer){
var max = (purpose === "Manufacture") ?
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
} else {
var max = flt(this.frm.doc.qty) - flt(this.frm.doc.produced_qty);
}
frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
description: __("Max: {0}", [max]), 'default': max },
@@ -315,4 +332,4 @@ cur_frm.fields_dict['project'].get_query = function(doc, dt, dn) {
['Project', 'status', 'not in', 'Completed, Cancelled']
]
}
}
}

View File

@@ -319,13 +319,43 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Check if material transfer entry is not required",
"fieldname": "skip_transfer",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Skip Material Transfer",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:doc.docstatus==1",
"depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
"description": "",
"fieldname": "material_transferred_for_manufacturing",
"fieldtype": "Float",
@@ -1316,7 +1346,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-04-10 12:13:09.312186",
"modified": "2017-04-21 16:31:19.509721",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Order",

View File

@@ -535,7 +535,7 @@ def make_stock_entry(production_order_id, purpose, qty=None):
stock_entry.from_warehouse = production_order.wip_warehouse
stock_entry.to_warehouse = production_order.fg_warehouse
additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
stock_entry.project = frappe.db.get_value("Stock Entry",{"production_order": production_order_id,"purpose": "Material Transfer for Manufacture"}, "project")
stock_entry.project = production_order.project
stock_entry.set("additional_costs", additional_costs)
stock_entry.get_items()

View File

@@ -389,3 +389,4 @@ erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate
erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices
erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically
erpnext.patches.v8_0.set_project_copied_from
erpnext.patches.v8_0.update_status_as_paid_for_completed_expense_claim

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
""" set status as Paid in Expense Claim if total_sactioned_amount
and total_amount_reimbursed is equal """
frappe.reload_doctype('Expense Claim')
frappe.db.sql("""
update
`tabExpense Claim`
set status = 'Paid'
where
total_sanctioned_amount = total_amount_reimbursed
""")

View File

@@ -297,6 +297,9 @@ body[data-route="pos"] .item-list {
body[data-route="pos"] .item-list .image-field {
height: 140px;
}
body[data-route="pos"] .item-list .image-field .placeholder-text {
font-size: 50px;
}
body[data-route="pos"] .item-list .pos-item-wrapper {
position: relative;
}

View File

@@ -351,6 +351,10 @@ body[data-route="pos"] {
.image-field {
height: 140px;
.placeholder-text {
font-size: 50px;
}
}
.pos-item-wrapper {

View File

@@ -8,10 +8,11 @@ cur_frm.add_fetch("supervisor", "instructor_name", "supervisor_name");
frappe.ui.form.on("Assessment Plan", {
refresh: function(frm) {
if (!frm.doc.__islocal) {
if (frm.doc.docstatus == 1) {
frm.add_custom_button(__("Assessment Result"), function() {
frappe.route_options = {
assessment_plan: frm.doc.name
assessment_plan: frm.doc.name,
student_batch: frm.doc.student_batch
}
frappe.set_route("Form", "Assessment Result Tool");
});

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "field:assessment_name",
@@ -13,6 +14,7 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -42,36 +44,7 @@
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "assessment_code",
"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": "Assessment Code",
"length": 0,
"no_copy": 0,
"options": "Assessment Code",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -102,209 +75,7 @@
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Course",
"length": 0,
"no_copy": 0,
"options": "Course",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "maximum_assessment_score",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Maximum Assessment Score",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grading_scale",
"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": 1,
"label": "Grading Scale",
"length": 0,
"no_copy": 0,
"options": "Grading Scale",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Student Group",
"length": 0,
"no_copy": 0,
"options": "Student Group",
"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_10",
"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,
@@ -335,6 +106,159 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_group",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Student Group",
"length": 0,
"no_copy": 0,
"options": "Student Group",
"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": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Course",
"length": 0,
"no_copy": 0,
"options": "Course",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "maximum_assessment_score",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Maximum Assessment Score",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grading_scale",
"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": 1,
"label": "Grading Scale",
"length": 0,
"no_copy": 0,
"options": "Grading Scale",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -366,6 +290,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -396,6 +321,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -426,6 +352,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -456,6 +383,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -485,6 +413,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -513,6 +442,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -542,6 +472,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -571,6 +502,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -601,6 +533,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -630,6 +563,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -658,6 +592,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -688,6 +623,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -717,18 +653,18 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-02-13 19:34:09.724549",
"modified": "2017-04-25 12:23:32.528982",
"modified_by": "Administrator",
"module": "Schools",
"name": "Assessment Plan",

View File

@@ -1,3 +1,4 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
@@ -5,10 +6,15 @@ cur_frm.add_fetch("assessment_plan", "student_group", "student_group");
cur_frm.add_fetch("assessment_plan", "student_batch", "student_batch");
frappe.ui.form.on('Assessment Result Tool', {
refresh: function(frm) {
frm.disable_save();
frm.page.clear_indicator();
},
refresh: function(frm) {
if (frappe.route_options) {
frm.set_value("student_batch", frappe.route_options.student_batch);
frm.set_value("assessment_plan", frappe.route_options.assessment_plan);
frappe.route_options = null;
}
frm.disable_save();
frm.page.clear_indicator();
},
assessment_plan: function(frm) {
if(!(frm.doc.student_batch || frm.doc.student_group)) return;

View File

@@ -15,6 +15,6 @@ class Course(Document):
if self.assessment_criteria:
total_weightage = 0
for criteria in self.assessment_criteria:
total_weightage += criteria.weightage
total_weightage += criteria.weightage or 0
if total_weightage != 100:
frappe.throw(_("Total Weightage of all Assessment Criteria must be 100%"))

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "",
@@ -23,6 +24,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Assessment Criteria",
@@ -52,6 +54,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
@@ -80,6 +83,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Weightage",
@@ -92,23 +96,23 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-01 18:01:40.682674",
"modified": "2017-04-21 20:04:26.621419",
"modified_by": "Administrator",
"module": "Schools",
"name": "Course Assessment Criteria",
@@ -118,6 +122,7 @@
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,

View File

@@ -13,7 +13,6 @@ class CourseSchedule(Document):
self.set_title()
self.validate_mandatory()
self.validate_course()
self.set_student_batch()
self.validate_date()
self.validate_overlap()

View File

@@ -24,28 +24,28 @@ class TestCourseSchedule(unittest.TestCase):
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
student_group="TC1-TP2--2014-2015-2014-2015 (_Test Academic Term)", room="RM0002", do_not_save= 1)
student_group="Course-TC101-2014-2015 (_Test Academic Term)", room="RM0002", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_room_conflict(self):
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
student_group="TC1-TP2--2014-2015-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", do_not_save= 1)
student_group="Course-TC101-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_no_conflict(self):
cs1 = make_course_schedule_test_record(simulate= True)
make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
student_group="TC1-TP2-2014-2015-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", room="RM0002")
student_group="Course-TC102-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", room="RM0002")
def make_course_schedule_test_record(**args):
args = frappe._dict(args)
course_schedule = frappe.new_doc("Course Schedule")
course_schedule.student_group = args.student_group or "TC-TP1-2014-2015-2014-2015 (_Test Academic Term)"
course_schedule.course = args.course or "TC100"
course_schedule.student_group = args.student_group or "Course-TC101-2014-2015 (_Test Academic Term)"
course_schedule.course = args.course or "TC101"
course_schedule.instructor = args.instructor or "_T-Instructor-00001"
course_schedule.room = args.room or "RM0001"

View File

@@ -1,7 +1,7 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "PE.#####",
"beta": 0,
@@ -14,6 +14,7 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -44,6 +45,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -74,6 +76,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -104,6 +107,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -134,6 +138,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -164,6 +169,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -192,6 +198,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -222,6 +229,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -252,6 +260,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -282,6 +291,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -312,6 +322,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -341,6 +352,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -370,6 +382,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -400,6 +413,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -429,6 +443,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -460,6 +475,7 @@
"width": ""
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -489,6 +505,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -530,7 +547,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-04-12 12:12:10.148274",
"modified": "2017-04-24 18:22:43.567607",
"modified_by": "Administrator",
"module": "Schools",
"name": "Program Enrollment",

View File

@@ -0,0 +1,8 @@
[
{
"batch_name": "_Batch 1"
},
{
"batch_name": "_Batch 2"
}
]

View File

@@ -1,19 +1,23 @@
cur_frm.add_fetch("student", "title", "student_name");
frappe.ui.form.on("Student Group", {
onload: function(frm) {
frm.set_query("academic_term", function() {
return {
"filters": {
"academic_year": (frm.doc.academic_year)
}
};
});
},
refresh: function(frm) {
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Course Schedule"), function() {
frappe.route_options = {
student_group: frm.doc.name
}
frappe.set_route("List", "Course Schedule");
});
frm.add_custom_button(__("Assessment Plan"), function() {
frappe.route_options = {
student_group: frm.doc.name
}
frappe.set_route("List", "Assessment Plan");
});
frm.add_custom_button(__("Update Email Group"), function() {
@@ -30,19 +34,84 @@ frappe.ui.form.on("Student Group", {
});
}
},
group_based_on: function(frm) {
if (frm.doc.group_based_on == "Batch") {
frm.doc.course = null;
}
else if (frm.doc.group_based_on == "Course") {
frm.doc.program = null;
frm.doc.batch = null;
}
frm.trigger("set_name");
},
onload: function(frm) {
frm.set_query("academic_term", function() {
return {
"filters": {
"academic_year": (frm.doc.academic_year)
set_name: function(frm) {
var name;
if (frm.doc.group_based_on == "Course") {
name = "Course-" + frm.doc.course + "-" + (frm.doc.academic_term?frm.doc.academic_term:frm.doc.academic_year);
} else if (frm.doc.group_based_on == "Batch") {
name = "Batch-" + frm.doc.program + "-" + frm.doc.batch + "-"
+ (frm.doc.academic_term?frm.doc.academic_term:frm.doc.academic_year);
} else if (frm.doc.group_based_on == "Activity") {
name = "Activity" + "-" + (frm.doc.academic_term?frm.doc.academic_term:frm.doc.academic_year);
}
frm.set_value("student_group_name", name);
},
program:function(frm) {
frm.trigger("set_name");
},
batch:function(frm) {
frm.trigger("set_name");
},
course:function(frm) {
frm.trigger("set_name");
},
get_students: function(frm) {
if (frm.doc.group_based_on != "Activity") {
var student_list = [];
var max_roll_no = 0;
$.each(frm.doc.students, function(i,d) {
student_list.push(d.student);
if (d.group_roll_number>max_roll_no) {
max_roll_no = d.group_roll_number;
}
};
});
});
frappe.call({
method: "erpnext.schools.doctype.student_group.student_group.get_students",
args: {
"academic_year": frm.doc.academic_year,
"group_based_on": frm.doc.group_based_on,
"program": frm.doc.program,
"batch" : frm.doc.batch,
"course": frm.doc.course
},
callback: function(r) {
if(r.message) {
$.each(r.message, function(i, d) {
if(!in_list(student_list, d.student)) {
var s = frm.add_child("students");
s.student = d.student;
s.student_name = d.student_name;
if (d.active === 0) {
s.active = 0;
}
s.group_roll_number = ++max_roll_no;
}
});
frm.save();
} else {
frappe.msgprint(__("Student Group is already updated."))
}
}
})
} else {
frappe.msgprint(__("Select students manually for the Activity based Group"));
}
}
});
//If Student Batch is entered, deduce program, academic_year and academic term from it
cur_frm.add_fetch("student_batch", "program", "program");
cur_frm.add_fetch("student_batch", "academic_term", "academic_term");
cur_frm.add_fetch("student_batch", "academic_year", "academic_year");
});

View File

@@ -1,8 +1,9 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "",
"autoname": "field:student_group_name",
"beta": 0,
"creation": "2015-09-07 12:55:52.072792",
"custom": 0,
@@ -13,36 +14,7 @@
"engine": "InnoDB",
"fields": [
{
"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": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Student Batch",
"length": 0,
"no_copy": 0,
"options": "Student Batch",
"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,
@@ -54,7 +26,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Academic Year",
"length": 0,
@@ -73,111 +45,24 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_term",
"fieldtype": "Link",
"fieldname": "group_based_on",
"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": "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": 1,
"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,
"label": "Group Based on",
"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,
"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": 1,
"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": 1,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Course",
"length": 0,
"no_copy": 0,
"options": "Course",
"options": "\nBatch\nCourse\nActivity",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -191,6 +76,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -221,11 +107,200 @@
"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_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "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": 1,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.group_based_on == 'Batch'",
"fieldname": "program",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"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": 1,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.group_based_on == 'Batch'",
"fieldname": "batch",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "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": 1,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.group_based_on == 'Course'",
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Course",
"length": 0,
"no_copy": 0,
"options": "Course",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 1,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "group_based_on",
"fieldname": "student_group_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Student Group Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
@@ -251,6 +326,37 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_students",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Students",
"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": 1,
"bold": 0,
"collapsible": 0,
@@ -281,12 +387,13 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -294,14 +401,45 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"label": "Instructors",
"length": 0,
"no_copy": 1,
"options": "Student Group",
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"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": "instructors",
"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": "Instructors",
"length": 0,
"no_copy": 0,
"options": "Student Group Instructor",
"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,
@@ -310,18 +448,18 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-02-17 17:16:31.682311",
"modified": "2017-04-24 15:53:35.593913",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group",
@@ -372,7 +510,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "program, course",
"search_fields": "program, batch, course",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",

View File

@@ -10,47 +10,59 @@ from erpnext.schools.utils import validate_duplicate_student
from erpnext.schools.api import get_student_batch_students
class StudentGroup(Document):
def autoname(self):
self.name = frappe.db.get_value("Course", self.course, "course_abbreviation")
if not self.name:
self.name = self.course
if self.student_batch:
self.name += "-" + self.student_batch
else:
prog_abb = frappe.db.get_value("Program", self.program, "program_abbreviation")
if not prog_abb:
prog_abb = self.program
if prog_abb:
self.name += "-" + prog_abb
if self.academic_year:
self.name += "-" + self.academic_year
if self.academic_term:
self.name += "-" + self.academic_term
def validate(self):
self.validate_mandatory_fields()
self.validate_strength()
self.validate_student_name()
self.validate_name()
if self.student_batch:
self.validate_student_batch()
self.validate_students()
validate_duplicate_student(self.students)
def validate_mandatory_fields(self):
if self.group_based_on == "Course" and not self.course:
frappe.throw(_("Please select Course"))
elif self.group_based_on == "Batch" and (not self.program or not self.batch):
frappe.throw(_("Please select Program and Batch"))
def validate_strength(self):
if self.max_strength and len(self.students) > self.max_strength:
frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength))
def validate_student_name(self):
def validate_students(self):
program_enrollment = get_program_enrollment(self.academic_year, self.group_based_on, self.program, self.batch, self.course)
students = [d.student for d in program_enrollment] if program_enrollment else None
for d in self.students:
d.student_name = frappe.db.get_value("Student", d.student, "title")
def validate_name(self):
if frappe.db.exists("Student Batch", self.name):
frappe.throw(_("""Student Batch exists with same name"""))
if self.group_based_on != "Activity" and d.student not in students:
frappe.throw(_("{0} - {1} is not enrolled in the given {2}".format(d.student, d.student_name, self.group_based_on)))
if not frappe.db.get_value("Student", d.student, "enabled") and d.active:
d.active = 0
frappe.throw(_("{0} - {1} is inactive student".format(d.student, d.student_name)))
def validate_student_batch(self):
student_batch_students = []
for d in get_student_batch_students(self.student_batch):
student_batch_students.append(d.student)
for d in self.students:
if d.student not in student_batch_students:
frappe.throw(_("""Student {0}: {1} does not belong to Student Batch {2}""".format(d.student, d.student_name, self.student_batch)))
@frappe.whitelist()
def get_students(academic_year, group_based_on, program=None, batch=None, course=None):
enrolled_students = get_program_enrollment(academic_year, group_based_on, program, batch, course)
if enrolled_students:
student_list = []
for s in enrolled_students:
if frappe.db.get_value("Student", s.student, "enabled"):
s.update({"active": 1})
else:
s.update({"active": 0})
student_list.append(s)
return student_list
def get_program_enrollment(academic_year, group_based_on, program=None, batch=None, course=None):
if group_based_on == "Batch":
return frappe.db.sql('''select student, student_name from `tabProgram Enrollment` where academic_year = %s
and program = %s and student_batch_name = %s order by student_name asc''',(academic_year, program, batch), as_dict=1)
elif group_based_on == "Course":
return frappe.db.sql('''
select
pe.student, pe.student_name
from
`tabProgram Enrollment` pe, `tabProgram Enrollment Course` pec
where
pe.name = pec.parent and pec.course = %s
order by
pe.student_name asc
''', (course), as_dict=1)

View File

@@ -1,14 +1,30 @@
[
{
"student_group_name": "Batch-_TP1-_Batch 1-2014-2015 (_Test Academic Term)",
"group_based_on": "Batch",
"program": "_TP1",
"course": "TC100",
"batch": "_Batch 1",
"academic_year": "2014-2015",
"academic_term": "2014-2015 (_Test Academic Term)"
},
{
"program": "_TP2",
"student_group_name": "Course-TC101-2014-2015 (_Test Academic Term)",
"group_based_on": "Course",
"course": "TC101",
"academic_year": "2014-2015",
"academic_term": "2014-2015 (_Test Academic Term)"
},
{
"student_group_name": "Course-TC102-2014-2015 (_Test Academic Term)",
"group_based_on": "Course",
"course": "TC102",
"academic_year": "2014-2015",
"academic_term": "2014-2015 (_Test Academic Term)"
},
{
"student_group_name": "Activity-2014-2015 (_Test Academic Term)",
"group_based_on": "Activity",
"academic_year": "2014-2015",
"academic_term": "2014-2015 (_Test Academic Term)"
}
]

View File

@@ -0,0 +1,129 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-04-17 16:06:01.406768",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "instructor",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Instructor",
"length": 0,
"no_copy": 0,
"options": "Instructor",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "instructor_name",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Instructor Name",
"length": 0,
"no_copy": 0,
"options": "instructor.instructor_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
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-04-17 16:06:05.792863",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group Instructor",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class StudentGroupInstructor(Document):
pass

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -21,6 +22,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Student",
@@ -39,33 +41,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_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,
"bold": 0,
@@ -77,6 +52,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Student Name",
@@ -94,6 +70,63 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "group_roll_number",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Group Roll Number",
"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,
"bold": 0,
@@ -106,6 +139,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Active",
@@ -124,17 +158,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-01-27 14:49:54.533005",
"modified": "2017-04-12 14:56:07.532226",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group Student",
@@ -144,6 +178,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,

View File

@@ -7,4 +7,4 @@ import frappe
from frappe.model.document import Document
class StudentGroupStudent(Document):
pass
pass

View File

@@ -14,6 +14,7 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -47,6 +48,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -75,6 +77,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -102,6 +105,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -134,6 +138,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -163,6 +168,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -195,6 +201,7 @@
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -223,6 +230,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -252,6 +260,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -282,6 +291,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -310,6 +320,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -342,6 +353,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -375,6 +387,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -402,6 +415,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -432,6 +446,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -461,6 +476,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -490,6 +506,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -518,6 +535,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -551,6 +569,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -584,6 +603,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -613,6 +633,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -646,6 +667,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -674,6 +696,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -705,6 +728,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -735,6 +759,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -765,6 +790,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -792,6 +818,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -813,7 +840,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"permlevel": 0,
"precision": "9",
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px",
@@ -827,6 +854,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -856,6 +884,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -889,6 +918,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -919,6 +949,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -946,6 +977,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -979,6 +1011,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1008,6 +1041,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1041,6 +1075,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1071,6 +1106,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1100,6 +1136,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -1130,6 +1167,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1160,6 +1198,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1188,6 +1227,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1217,6 +1257,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1247,6 +1288,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1276,6 +1318,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1304,6 +1347,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1337,6 +1381,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1370,6 +1415,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1400,6 +1446,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1427,6 +1474,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -1457,6 +1505,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1489,6 +1538,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1533,7 +1583,7 @@
"istable": 1,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-04-18 18:47:26.869235",
"modified": "2017-04-25 10:34:17.987184",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",

View File

@@ -3,8 +3,6 @@
{% include 'erpnext/selling/sales_common.js' %}
cur_frm.add_fetch('customer', 'tax_id', 'tax_id');
frappe.ui.form.on("Sales Order", {
setup: function(frm) {
$.extend(frm.cscript, new erpnext.selling.SalesOrderController({frm: frm}));
@@ -14,6 +12,7 @@ frappe.ui.form.on("Sales Order", {
'Material Request': 'Material Request',
'Purchase Order': 'Purchase Order'
}
frm.add_fetch('customer', 'tax_id', 'tax_id');
},
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {

View File

@@ -10,7 +10,7 @@ from datetime import timedelta
from dateutil.relativedelta import relativedelta
from frappe.core.doctype.user.user import STANDARD_USERS
import frappe.desk.notifications
from erpnext.accounts.utils import get_balance_on, get_count_on, get_currency_precision
from erpnext.accounts.utils import get_balance_on, get_count_on
user_specific_content = ["calendar_events", "todo_list"]

View File

@@ -571,6 +571,7 @@ def create_program(args):
for i in xrange(1,6):
if args.get("program_" + str(i)):
program = frappe.new_doc("Program")
program.program_code = args.get("program_" + str(i))
program.program_name = args.get("program_" + str(i))
try:
program.save()
@@ -581,6 +582,7 @@ def create_course(args):
for i in xrange(1,6):
if args.get("course_" + str(i)):
course = frappe.new_doc("Course")
course.course_code = args.get("course_" + str(i))
course.course_name = args.get("course_" + str(i))
try:
course.save()

View File

@@ -1,12 +1,137 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
cur_frm.fields_dict['item'].get_query = function(doc, cdt, cdn) {
return {
query: "erpnext.controllers.queries.item_query",
filters:{
'is_stock_item': 1,
'has_batch_no': 1
frappe.ui.form.on('Batch', {
setup: (frm) => {
frm.fields_dict['item'].get_query = function(doc, cdt, cdn) {
return {
query: "erpnext.controllers.queries.item_query",
filters:{
'is_stock_item': 1,
'has_batch_no': 1
}
}
}
},
refresh: (frm) => {
if(!frm.is_new()) {
frm.add_custom_button(__("View Ledger"), () => {
frappe.route_options = {
batch_no: frm.doc.name
};
frappe.set_route("query-report", "Stock Ledger");
});
frm.trigger('make_dashboard');
}
},
make_dashboard: (frm) => {
if(!frm.is_new()) {
frappe.call({
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
args: {batch_no: frm.doc.name},
callback: (r) => {
if(!r.message) {
return;
}
var section = frm.dashboard.add_section(`<h5 style="margin-top: 0px;">
${ __("Stock Levels") }</a></h5>`);
// sort by qty
r.message.sort(function(a, b) { a.qty > b.qty ? 1 : -1 });
var rows = $('<div></div>').appendTo(section);
// show
(r.message || []).forEach(function(d) {
if(d.qty > 0) {
$(`<div class='row' style='margin-bottom: 10px;'>
<div class='col-sm-3 small' style='padding-top: 3px;'>${d.warehouse}</div>
<div class='col-sm-3 small text-right' style='padding-top: 3px;'>${d.qty}</div>
<div class='col-sm-6'>
<button class='btn btn-default btn-xs btn-move' style='margin-right: 7px;'
data-qty = "${d.qty}"
data-warehouse = "${d.warehouse}">
${__('Move')}</button>
<button class='btn btn-default btn-xs btn-split'
data-qty = "${d.qty}"
data-warehouse = "${d.warehouse}">
${__('Split')}</button>
</div>
</div>`).appendTo(rows);
}
});
// move - ask for target warehouse and make stock entry
rows.find('.btn-move').on('click', function() {
var $btn = $(this);
frappe.prompt({
fieldname: 'to_warehouse',
label: __('To Warehouse'),
fieldtype: 'Link',
options: 'Warehouse'
},
(data) => {
frappe.call({
method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
args: {
item_code: frm.doc.item,
batch_no: frm.doc.name,
qty: $btn.attr('data-qty'),
from_warehouse: $btn.attr('data-warehouse'),
to_warehouse: data.to_warehouse
},
callback: (r) => {
frappe.show_alert(__('Stock Entry {0} created',
['<a href="#Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
frm.refresh();
},
});
},
__('Select Target Warehouse'),
__('Move')
)
});
// split - ask for new qty and batch ID (optional)
// and make stock entry via batch.batch_split
rows.find('.btn-split').on('click', function() {
var $btn = $(this);
frappe.prompt([{
fieldname: 'qty',
label: __('New Batch Qty'),
fieldtype: 'Float',
'default': $btn.attr('data-qty')
},
{
fieldname: 'new_batch_id',
label: __('New Batch ID (Optional)'),
fieldtype: 'Data',
}],
(data) => {
frappe.call({
method: 'erpnext.stock.doctype.batch.batch.split_batch',
args: {
item_code: frm.doc.item,
batch_no: frm.doc.name,
qty: data.qty,
warehouse: $btn.attr('data-warehouse'),
new_batch_id: data.new_batch_id
},
callback: (r) => {
frm.refresh();
},
});
},
__('Split Batch'),
__('Split')
)
})
frm.dashboard.show();
}
});
}
}
}
})

View File

@@ -1,8 +1,9 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "field:batch_id",
"autoname": "",
"beta": 0,
"creation": "2013-03-05 14:50:38",
"custom": 0,
@@ -17,12 +18,14 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.__islocal",
"fieldname": "batch_id",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Batch ID",
@@ -36,7 +39,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -52,6 +55,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Item",
@@ -71,6 +75,66 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "image",
"fieldtype": "Attach Image",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "image",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parent_batch",
"fieldname": "parent_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": "Parent Batch",
"length": 0,
"no_copy": 0,
"options": "Batch",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -82,6 +146,7 @@
"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,
@@ -109,6 +174,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expiry Date",
@@ -127,6 +193,153 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "source",
"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": "Source",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "supplier",
"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": "Supplier",
"length": 0,
"no_copy": 0,
"options": "Supplier",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_9",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference_doctype",
"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": "Source Document Type",
"length": 0,
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Source Document Name",
"length": 0,
"no_copy": 0,
"options": "reference_doctype",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -138,6 +351,7 @@
"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,
@@ -165,6 +379,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Batch Description",
@@ -185,18 +400,19 @@
"width": "300px"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-archive",
"idx": 1,
"image_field": "image",
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 5,
"modified": "2016-11-07 05:50:33.973883",
"modified": "2017-04-20 03:22:19.888058",
"modified_by": "Administrator",
"module": "Stock",
"name": "Batch",
@@ -212,7 +428,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -224,9 +439,12 @@
"write": 1
}
],
"quick_entry": 0,
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "DESC",
"title_field": "item",
"track_changes": 0,
"track_seen": 0
}

View File

@@ -6,7 +6,27 @@ import frappe
from frappe import _
from frappe.model.document import Document
class UnableToSelectBatchError(frappe.ValidationError): pass
class Batch(Document):
def autoname(self):
'''Generate random ID for batch if not specified'''
if not self.batch_id:
if frappe.db.get_value('Item', self.item, 'create_new_batch'):
temp = None
while not temp:
temp = frappe.generate_hash()[:7].upper()
if frappe.db.exists('Batch', temp):
temp = None
self.batch_id = temp
else:
frappe.throw(_('Batch ID is mandatory'), frappe.MandatoryError)
self.name = self.batch_id
def onload(self):
self.image = frappe.db.get_value('Item', self.item, 'image')
def validate(self):
self.item_has_batch_enabled()
@@ -14,3 +34,86 @@ class Batch(Document):
def item_has_batch_enabled(self):
if frappe.db.get_value("Item",self.item,"has_batch_no") == 0:
frappe.throw(_("The selected item cannot have Batch"))
@frappe.whitelist()
def get_batch_qty(batch_no=None, warehouse=None, item_code=None):
'''Returns batch actual qty if warehouse is passed,
or returns dict of qty by warehouse if warehouse is None
The user must pass either batch_no or batch_no + warehouse or item_code + warehouse
:param batch_no: Optional - give qty for this batch no
:param warehouse: Optional - give qty for this warehouse
:param item_code: Optional - give qty for this item'''
frappe.has_permission('Batch', throw=True)
out = 0
if batch_no and warehouse:
out = float(frappe.db.sql("""select sum(actual_qty)
from `tabStock Ledger Entry`
where warehouse=%s and batch_no=%s""",
(warehouse, batch_no))[0][0] or 0)
if batch_no and not warehouse:
out = frappe.db.sql('''select warehouse, sum(actual_qty) as qty
from `tabStock Ledger Entry`
where batch_no=%s
group by warehouse''', batch_no, as_dict=1)
if not batch_no and item_code and warehouse:
out = frappe.db.sql('''select batch_no, sum(actual_qty) as qty
from `tabStock Ledger Entry`
where item_code = %s and warehouse=%s
group by batch_no''', (item_code, warehouse), as_dict=1)
return out
@frappe.whitelist()
def split_batch(batch_no, item_code, warehouse, qty, new_batch_id = None):
'''Split the batch into a new batch'''
batch = frappe.get_doc(dict(doctype='Batch', item=item_code, batch_id=new_batch_id)).insert()
stock_entry = frappe.get_doc(dict(
doctype='Stock Entry',
purpose='Repack',
items=[
dict(
item_code = item_code,
qty = float(qty or 0),
s_warehouse = warehouse,
batch_no = batch_no
),
dict(
item_code = item_code,
qty = float(qty or 0),
t_warehouse = warehouse,
batch_no = batch.name
),
]
))
stock_entry.insert()
stock_entry.submit()
return batch.name
def set_batch_nos(doc, warehouse_field, throw = False):
'''Automatically select `batch_no` for outgoing items in item table'''
for d in doc.items:
has_batch_no = frappe.db.get_value('Item', d.item_code, 'has_batch_no')
warehouse = d.get(warehouse_field, None)
if has_batch_no and not d.batch_no and warehouse:
d.batch_no = get_batch_no(d.item_code, warehouse, d.qty, throw)
def get_batch_no(item_code, warehouse, qty, throw=False):
'''get the smallest batch with for the given item_code, warehouse and qty'''
batches = sorted(
get_batch_qty(item_code = item_code, warehouse = warehouse),
lambda a, b: 1 if a.qty > b.qty else -1)
batch_no = None
for b in batches:
if b.qty >= qty:
batch_no = b.batch_no
# found!
break
if not batch_no:
frappe.msgprint(_('Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement').format(frappe.bold(item_code)))
if throw: raise UnableToSelectBatchError
return batch_no

View File

@@ -6,10 +6,148 @@ import frappe
from frappe.exceptions import ValidationError
import unittest
from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError
class TestBatch(unittest.TestCase):
def test_item_has_batch_enabled(self):
self.assertRaises(ValidationError, frappe.get_doc({
"doctype": "Batch",
"name": "_test Batch",
"item": "_Test Item"
}).save)
}).save)
def make_batch_item(self):
from erpnext.stock.doctype.item.test_item import make_item
if not frappe.db.exists('ITEM-BATCH-1'):
make_item('ITEM-BATCH-1', dict(has_batch_no = 1, create_new_batch = 1))
def test_purchase_receipt(self, batch_qty = 100):
'''Test automated batch creation from Purchase Receipt'''
self.make_batch_item()
receipt = frappe.get_doc(dict(
doctype = 'Purchase Receipt',
supplier = '_Test Supplier',
items = [
dict(
item_code = 'ITEM-BATCH-1',
qty = batch_qty,
rate = 10
)
]
)).insert()
receipt.submit()
self.assertTrue(receipt.items[0].batch_no)
self.assertEquals(get_batch_qty(receipt.items[0].batch_no,
receipt.items[0].warehouse), batch_qty)
return receipt
def test_stock_entry_incoming(self):
'''Test batch creation via Stock Entry (Production Order)'''
self.make_batch_item()
stock_entry = frappe.get_doc(dict(
doctype = 'Stock Entry',
purpose = 'Material Receipt',
company = '_Test Company',
items = [
dict(
item_code = 'ITEM-BATCH-1',
qty = 90,
t_warehouse = '_Test Warehouse - _TC',
cost_center = 'Main - _TC',
rate = 10
)
]
)).insert()
stock_entry.submit()
self.assertTrue(stock_entry.items[0].batch_no)
self.assertEquals(get_batch_qty(stock_entry.items[0].batch_no, stock_entry.items[0].t_warehouse), 90)
def test_delivery_note(self):
'''Test automatic batch selection for outgoing items'''
batch_qty = 15
receipt = self.test_purchase_receipt(batch_qty)
delivery_note = frappe.get_doc(dict(
doctype = 'Delivery Note',
customer = '_Test Customer',
company = receipt.company,
items = [
dict(
item_code = 'ITEM-BATCH-1',
qty = batch_qty,
rate = 10,
warehouse = receipt.items[0].warehouse
)
]
)).insert()
delivery_note.submit()
# shipped with same batch
self.assertEquals(delivery_note.items[0].batch_no, receipt.items[0].batch_no)
# balance is 0
self.assertEquals(get_batch_qty(receipt.items[0].batch_no,
receipt.items[0].warehouse), 0)
def test_delivery_note_fail(self):
'''Test automatic batch selection for outgoing items'''
receipt = self.test_purchase_receipt(100)
delivery_note = frappe.get_doc(dict(
doctype = 'Delivery Note',
customer = '_Test Customer',
company = receipt.company,
items = [
dict(
item_code = 'ITEM-BATCH-1',
qty = 5000,
rate = 10,
warehouse = receipt.items[0].warehouse
)
]
))
self.assertRaises(UnableToSelectBatchError, delivery_note.insert)
def test_stock_entry_outgoing(self):
'''Test automatic batch selection for outgoing stock entry'''
batch_qty = 16
receipt = self.test_purchase_receipt(batch_qty)
stock_entry = frappe.get_doc(dict(
doctype = 'Stock Entry',
purpose = 'Material Issue',
company = receipt.company,
items = [
dict(
item_code = 'ITEM-BATCH-1',
qty = batch_qty,
s_warehouse = receipt.items[0].warehouse,
)
]
)).insert()
stock_entry.submit()
# assert same batch is selected
self.assertEqual(stock_entry.items[0].batch_no, receipt.items[0].batch_no)
# balance is 0
self.assertEquals(get_batch_qty(receipt.items[0].batch_no,
receipt.items[0].warehouse), 0)
def test_batch_split(self):
'''Test batch splitting'''
receipt = self.test_purchase_receipt()
from erpnext.stock.doctype.batch.batch import split_batch
new_batch = split_batch(receipt.items[0].batch_no, 'ITEM-BATCH-1', receipt.items[0].warehouse, 22)
self.assertEquals(get_batch_qty(receipt.items[0].batch_no, receipt.items[0].warehouse), 78)
self.assertEquals(get_batch_qty(new_batch, receipt.items[0].warehouse), 22)

View File

@@ -11,7 +11,7 @@ import frappe.defaults
from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from frappe.desk.notifications import clear_doctype_notifications
from erpnext.stock.doctype.batch.batch import set_batch_nos
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -106,6 +106,9 @@ class DeliveryNote(SellingController):
self.validate_uom_is_integer("uom", "qty")
self.validate_with_previous_doc()
if self._action != 'submit':
set_batch_nos(self, 'warehouse', True)
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
make_packing_list(self)

View File

@@ -7,7 +7,7 @@
"beta": 0,
"creation": "2013-05-03 10:45:46",
"custom": 0,
"default_print_format": "Standard",
"default_print_format": "",
"description": "A Product or a Service that is bought, sold or kept in stock.",
"docstatus": 0,
"doctype": "DocType",
@@ -714,103 +714,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"depends_on": "eval:doc.is_stock_item",
"fieldname": "has_batch_no",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Has Batch No",
"length": 0,
"no_copy": 0,
"oldfieldname": "has_batch_no",
"oldfieldtype": "Select",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"depends_on": "eval:doc.is_stock_item",
"description": "Selecting \"Yes\" will give a unique identity to each entity of this item which can be viewed in the Serial No master.",
"fieldname": "has_serial_no",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Has Serial No",
"length": 0,
"no_copy": 0,
"oldfieldname": "has_serial_no",
"oldfieldtype": "Select",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "has_serial_no",
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
"fieldname": "serial_no_series",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Serial Number Series",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -1150,6 +1053,193 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no",
"columns": 0,
"depends_on": "is_stock_item",
"fieldname": "serial_nos_and_batches",
"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": "Serial Nos and Batches",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"depends_on": "eval:doc.is_stock_item",
"fieldname": "has_batch_no",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Has Batch No",
"length": 0,
"no_copy": 0,
"oldfieldname": "has_batch_no",
"oldfieldtype": "Select",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "has_batch_no",
"description": "",
"fieldname": "create_new_batch",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Automatically Create New Batch",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_37",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"depends_on": "eval:doc.is_stock_item",
"description": "",
"fieldname": "has_serial_no",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Has Serial No",
"length": 0,
"no_copy": 0,
"oldfieldname": "has_serial_no",
"oldfieldtype": "Select",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "has_serial_no",
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
"fieldname": "serial_no_series",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Serial Number Series",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -2954,8 +3044,8 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2017-03-24 15:46:18.569291",
"modified_by": "d.ottenbreit@eso-electronic.de",
"modified": "2017-04-19 08:14:26.785497",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
"owner": "Administrator",

View File

@@ -50,8 +50,11 @@ class PurchaseReceipt(BuyingController):
self.validate_posting_time()
super(PurchaseReceipt, self).validate()
if not self._action=="submit":
if self._action=="submit":
self.make_batches('warehouse')
else:
self.set_status()
self.po_required()
self.validate_with_previous_doc()
self.validate_uom_is_integer("uom", ["qty", "received_qty"])
@@ -62,7 +65,6 @@ class PurchaseReceipt(BuyingController):
if getdate(self.posting_date) > getdate(nowdate()):
throw(_("Posting Date cannot be future date"))
def validate_with_previous_doc(self):
super(PurchaseReceipt, self).validate_with_previous_doc({
"Purchase Order": {

View File

@@ -9,6 +9,7 @@ from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
import json
@@ -48,6 +49,11 @@ class StockEntry(StockController):
self.validate_with_material_request()
self.validate_batch()
if self._action == 'submit':
self.make_batches('t_warehouse')
else:
set_batch_nos(self, 's_warehouse', True)
self.set_actual_qty()
self.calculate_rate_and_amount(update_finished_item_rate=False)
@@ -86,8 +92,10 @@ class StockEntry(StockController):
if item.item_code not in stock_items:
frappe.throw(_("{0} is not a stock Item").format(item.item_code))
item_details = self.get_item_details(frappe._dict({"item_code": item.item_code,
"company": self.company, "project": self.project, "uom": item.uom}), for_update=True)
item_details = self.get_item_details(frappe._dict(
{"item_code": item.item_code, "company": self.company,
"project": self.project, "uom": item.uom, 's_warehouse': item.s_warehouse}),
for_update=True)
for f in ("uom", "stock_uom", "description", "item_name", "expense_account",
"cost_center", "conversion_factor"):
@@ -462,7 +470,9 @@ class StockEntry(StockController):
def get_item_details(self, args=None, for_update=False):
item = frappe.db.sql("""select stock_uom, description, image, item_name,
expense_account, buying_cost_center, item_group from `tabItem`
expense_account, buying_cost_center, item_group, has_serial_no,
has_batch_no
from `tabItem`
where name = %s
and disabled=0
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""",
@@ -472,7 +482,7 @@ class StockEntry(StockController):
item = item[0]
ret = {
ret = frappe._dict({
'uom' : item.stock_uom,
'stock_uom' : item.stock_uom,
'description' : item.description,
@@ -486,8 +496,10 @@ class StockEntry(StockController):
'batch_no' : '',
'actual_qty' : 0,
'basic_rate' : 0,
'serial_no' : ''
}
'serial_no' : '',
'has_serial_no' : item.has_serial_no,
'has_batch_no' : item.has_batch_no
})
for d in [["Account", "expense_account", "default_expense_account"],
["Cost Center", "cost_center", "cost_center"]]:
company = frappe.db.get_value(d[0], ret.get(d[1]), "company")
@@ -507,6 +519,11 @@ class StockEntry(StockController):
stock_and_rate = args.get('warehouse') and get_warehouse_details(args) or {}
ret.update(stock_and_rate)
# automatically select batch for outgoing item
if (args.get('s_warehouse', None) and args.get('qty') and
ret.get('has_batch_no') and not args.get('batch_no')):
args.batch_no = get_batch_no(args['item_code'], args['s_warehouse'], args['qty'])
return ret
def get_items(self):

View File

@@ -6,6 +6,20 @@ from frappe.utils import cint, flt
@frappe.whitelist()
def make_stock_entry(**args):
'''Helper function to make a Stock Entry
:item_code: Item to be moved
:qty: Qty to be moved
:from_warehouse: Optional
:to_warehouse: Optional
:rate: Optional
:serial_no: Optional
:batch_no: Optional
:posting_date: Optional
:posting_time: Optional
:do_not_save: Optional flag
:do_not_submit: Optional flag
'''
s = frappe.new_doc("Stock Entry")
args = frappe._dict(args)
@@ -71,6 +85,7 @@ def make_stock_entry(**args):
"basic_rate": args.rate or args.basic_rate,
"conversion_factor": 1.0,
"serial_no": args.serial_no,
'batch_no': args.batch_no,
'cost_center': args.cost_center,
'expense_account': args.expense_account
})

View File

@@ -58,7 +58,7 @@ class StockLedgerEntry(Document):
def validate_item(self):
item_det = frappe.db.sql("""select name, has_batch_no, docstatus,
is_stock_item, has_variants, stock_uom
is_stock_item, has_variants, stock_uom, create_new_batch
from tabItem where name=%s""", self.item_code, as_dict=True)
if not item_det:
@@ -75,7 +75,7 @@ class StockLedgerEntry(Document):
if not self.batch_no:
frappe.throw(_("Batch number is mandatory for Item {0}").format(self.item_code))
elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, self.item_code))
frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, self.item_code))
elif item_det.has_batch_no ==0 and self.batch_no:
frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
@@ -116,7 +116,7 @@ class StockLedgerEntry(Document):
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
else:
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.posting_date, self.fiscal_year, self.company,
validate_fiscal_year(self.posting_date, self.fiscal_year, self.company,
self.meta.get_label("posting_date"), self)
def block_transactions_against_group_warehouse(self):

View File

@@ -152,7 +152,6 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
setup: function() {
var me = this;
this.frm.get_docfield("items").allow_bulk_edit = 1;
this.setup_posting_date_time_check();

View File

@@ -10,9 +10,11 @@
"description": "This tool helps you to update or fix the quantity and valuation of stock in the system. It is typically used to synchronise the system values and what actually exists in your warehouses.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 0,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -43,6 +45,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -72,6 +75,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -101,6 +105,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -128,6 +133,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -159,6 +165,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -189,6 +196,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -218,6 +226,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -246,6 +255,7 @@
"unique": 0
},
{
"allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -276,6 +286,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -304,6 +315,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -334,6 +346,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -364,6 +377,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -392,6 +406,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -420,6 +435,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -461,7 +477,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
"modified": "2017-03-15 15:03:08.579943",
"modified": "2017-04-21 16:58:53.475787",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Reconciliation",

View File

@@ -143,13 +143,11 @@ class StockReconciliation(StockController):
# item should not be serialized
if item.has_serial_no == 1:
raise frappe.ValidationError, _("Serialized Item {0} cannot be updated \
using Stock Reconciliation").format(item_code)
raise frappe.ValidationError, _("Serialized Item {0} cannot be updated using Stock Reconciliation, please use Stock Entry").format(item_code)
# item managed batch-wise not allowed
if item.has_batch_no == 1:
raise frappe.ValidationError, _("Item: {0} managed batch-wise, can not be reconciled using \
Stock Reconciliation, instead use Stock Entry").format(item_code)
raise frappe.ValidationError, _("Batched Item {0} cannot be updated using Stock Reconciliation, instead use Stock Entry").format(item_code)
# docstatus should be < 2
validate_cancelled_item(item_code, item.docstatus, verbose=0)

View File

@@ -9,6 +9,7 @@ import json
from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item, set_transaction_type
from erpnext.setup.utils import get_exchange_rate
from frappe.model.meta import get_field_precision
from erpnext.stock.doctype.batch.batch import get_batch_no
@frappe.whitelist()
def get_item_details(args):
@@ -74,7 +75,12 @@ def get_item_details(args):
out.update(get_pricing_rule_for_item(args))
if args.get("doctype") in ("Sales Invoice", "Delivery Note") and out.stock_qty > 0:
out.serial_no = get_serial_no(out)
if out.has_serial_no:
out.serial_no = get_serial_no(out)
if out.has_batch_no:
out.batch_no = get_batch_no(out.item_code, out.warehouse, out.qty)
if args.transaction_date and item.lead_time_days:
out.schedule_date = out.lead_time_date = add_days(args.transaction_date,
@@ -154,6 +160,8 @@ def get_basic_details(args, item):
"income_account": get_default_income_account(args, item),
"expense_account": get_default_expense_account(args, item),
"cost_center": get_default_cost_center(args, item),
'has_serial_no': item.has_serial_no,
'has_batch_no': item.has_batch_no,
"batch_no": None,
"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
item.get("taxes")))),
@@ -187,9 +195,11 @@ def get_basic_details(args, item):
out.stock_qty = out.qty * out.conversion_factor
# if default specified in item is for another company, fetch from company
for d in [["Account", "income_account", "default_income_account"],
for d in [
["Account", "income_account", "default_income_account"],
["Account", "expense_account", "default_expense_account"],
["Cost Center", "cost_center", "cost_center"], ["Warehouse", "warehouse", ""]]:
["Cost Center", "cost_center", "cost_center"],
["Warehouse", "warehouse", ""]]:
company = frappe.db.get_value(d[0], out.get(d[1]), "company")
if not out[d[1]] or (company and args.company != company):
out[d[1]] = frappe.db.get_value("Company", args.company, d[2]) if d[2] else None
@@ -359,15 +369,6 @@ def get_serial_nos_by_fifo(args):
"qty": abs(cint(args.stock_qty))
}))
def get_actual_batch_qty(batch_no,warehouse,item_code):
actual_batch_qty = 0
if batch_no:
actual_batch_qty = flt(frappe.db.sql("""select sum(actual_qty)
from `tabStock Ledger Entry`
where warehouse=%s and item_code=%s and batch_no=%s""",
(warehouse, item_code, batch_no))[0][0])
return actual_batch_qty
@frappe.whitelist()
def get_conversion_factor(item_code, uom):
variant_of = frappe.db.get_value("Item", item_code, "variant_of")
@@ -403,10 +404,10 @@ def get_bin_details_and_serial_nos(item_code, warehouse, stock_qty=None, serial_
return bin_details_and_serial_nos
@frappe.whitelist()
def get_batch_qty(batch_no,warehouse,item_code):
actual_batch_qty = get_actual_batch_qty(batch_no,warehouse,item_code)
def get_batch_qty(batch_no, warehouse, item_code):
from erpnext.stock.doctype.batch import batch
if batch_no:
return {'actual_batch_qty': actual_batch_qty}
return {'actual_batch_qty': batch.get_batch_qty(batch_no, warehouse)}
@frappe.whitelist()
def apply_price_list(args, as_doc=False):

Some files were not shown because too many files have changed in this diff Show More