Merge branch 'develop'

This commit is contained in:
mbauskar 2017-07-06 16:12:02 +05:30
commit afdd7a626c
226 changed files with 44440 additions and 41222 deletions

View File

@ -131,6 +131,7 @@
"getCookies": true, "getCookies": true,
"get_url_arg": true, "get_url_arg": true,
"get_server_fields": true, "get_server_fields": true,
"set_multiple": true "set_multiple": true,
"QUnit": true
} }
} }

46
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@frappe.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
__version__ = '8.2.4' __version__ = '8.3.0'
def get_default_company(user=None): def get_default_company(user=None):

View File

@ -62,13 +62,13 @@ class BankReconciliation(Document):
for d in entries: for d in entries:
row = self.append('payment_entries', {}) row = self.append('payment_entries', {})
amount = d.debit if d.debit else d.credit
d.amount = fmt_money(d.debit if d.debit else d.credit, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr")) d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
d.pop("credit") d.pop("credit")
d.pop("debit") d.pop("debit")
d.pop("account_currency") d.pop("account_currency")
row.update(d) row.update(d)
self.total_amount += flt(d.amount) self.total_amount += flt(amount)
def update_clearance_date(self): def update_clearance_date(self):
clearance_date_updated = False clearance_date_updated = False

View File

@ -3238,7 +3238,7 @@
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 1,
"label": "Status", "label": "Status",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@ -3767,10 +3767,11 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-13 14:28:57.930167", "modified": "2017-06-29 10:48:09.707735",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice", "name": "Purchase Invoice",
"name_case": "Title Case",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {

View File

@ -71,17 +71,19 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}); });
if(!from_delivery_note && !is_delivered_by_supplier) { if(!from_delivery_note && !is_delivered_by_supplier) {
cur_frm.add_custom_button(__('Delivery'), cur_frm.cscript['Make Delivery Note'], cur_frm.add_custom_button(__('Delivery'),
__("Make")); cur_frm.cscript['Make Delivery Note'], __("Make"));
} }
} }
if(doc.outstanding_amount!=0 && !cint(doc.is_return)) { if(doc.outstanding_amount!=0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment'), this.make_payment_entry, __("Make")); cur_frm.add_custom_button(__('Payment'),
this.make_payment_entry, __("Make"));
} }
if(doc.outstanding_amount>0 && !cint(doc.is_return)) { if(doc.outstanding_amount>0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'), this.make_payment_request, __("Make")); cur_frm.add_custom_button(__('Payment Request'),
this.make_payment_request, __("Make"));
} }
@ -303,6 +305,23 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
} }
this.frm.refresh_fields(); this.frm.refresh_fields();
},
company_address: function() {
var me = this;
if(this.frm.doc.company_address) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
args: {"address_dict": this.frm.doc.company_address },
callback: function(r) {
if(r.message) {
me.frm.set_value("company_address_display", r.message)
}
}
})
} else {
this.frm.set_value("company_address_display", "");
}
} }
}); });
@ -324,12 +343,12 @@ cur_frm.cscript.hide_fields = function(doc) {
} }
} }
/*
var item_fields_stock = ['batch_no', 'actual_batch_qty', 'actual_qty', 'expense_account', var item_fields_stock = ['batch_no', 'actual_batch_qty', 'actual_qty', 'expense_account',
'warehouse', 'expense_account', 'quality_inspection'] 'warehouse', 'expense_account', 'quality_inspection']
cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock, cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
(cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false)); (cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false));
*/
// India related fields // India related fields
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']); if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
@ -483,7 +502,7 @@ frappe.ui.form.on('Sales Invoice', {
'Delivery Note': 'Delivery', 'Delivery Note': 'Delivery',
'Sales Invoice': 'Sales Return', 'Sales Invoice': 'Sales Return',
'Payment Request': 'Payment Request', 'Payment Request': 'Payment Request',
'Payment': 'Payment Entry' 'Payment Entry': 'Payment'
}, },
frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(doc, cdt, cdn){ frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(doc, cdt, cdn){
return{ return{

View File

@ -190,7 +190,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -200,37 +200,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "due_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": "Payment Due Date",
"length": 0,
"no_copy": 1,
"oldfieldname": "due_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -253,7 +222,7 @@
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Project", "options": "Project",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -314,7 +283,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -345,7 +314,7 @@
"options": "POS Profile", "options": "POS Profile",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -510,6 +479,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "due_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": "Payment Due Date",
"length": 0,
"no_copy": 1,
"oldfieldname": "due_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -844,6 +844,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "territory",
"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": "Territory",
"length": 0,
"no_copy": 0,
"options": "Territory",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -949,13 +980,13 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Company Address", "label": "Company Address Name",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Address", "options": "Address",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -971,24 +1002,23 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "territory", "fieldname": "company_address_display",
"fieldtype": "Link", "fieldtype": "Small Text",
"hidden": 0, "hidden": 1,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Territory", "label": "Company Address",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Territory",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@ -1479,7 +1509,7 @@
"options": "Sales Invoice Timesheet", "options": "Sales Invoice Timesheet",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1882,6 +1912,36 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "sec_tax_breakup",
"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": "Item-wise Tax Breakup",
"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_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -1889,7 +1949,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "other_charges_calculation", "fieldname": "other_charges_calculation",
"fieldtype": "HTML", "fieldtype": "Text",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
@ -1899,12 +1959,12 @@
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Taxes and Charges Calculation", "label": "Taxes and Charges Calculation",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 1,
"oldfieldtype": "HTML", "oldfieldtype": "HTML",
"permlevel": 0, "permlevel": 0,
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@ -2511,7 +2571,7 @@
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 1, "in_standard_filter": 0,
"label": "Outstanding Amount", "label": "Outstanding Amount",
"length": 0, "length": 0,
"no_copy": 1, "no_copy": 1,
@ -2984,7 +3044,7 @@
"options": "Account", "options": "Account",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -3597,7 +3657,7 @@
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 1,
"label": "Status", "label": "Status",
"length": 0, "length": 0,
"no_copy": 1, "no_copy": 1,
@ -4450,7 +4510,7 @@
"options": "Print Format", "options": "Print Format",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -4511,7 +4571,7 @@
"length": 0, "length": 0,
"no_copy": 1, "no_copy": 1,
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -4542,7 +4602,7 @@
"length": 0, "length": 0,
"no_copy": 1, "no_copy": 1,
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -4627,10 +4687,11 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-22 14:45:35.257640", "modified": "2017-07-04 17:11:09.477003",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice", "name": "Sales Invoice",
"name_case": "Title Case",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {

View File

@ -132,8 +132,7 @@ class SalesInvoice(SellingController):
self.update_billing_status_for_zero_amount_refdoc("Sales Order") self.update_billing_status_for_zero_amount_refdoc("Sales Order")
self.check_credit_limit() self.check_credit_limit()
if self.update_stock: self.update_serial_no()
self.update_serial_no()
if not cint(self.is_pos) == 1 and not self.is_return: if not cint(self.is_pos) == 1 and not self.is_return:
self.update_against_document_in_jv() self.update_against_document_in_jv()

View File

@ -1105,6 +1105,22 @@ class TestSalesInvoice(unittest.TestCase):
for i, k in enumerate(expected_values["keys"]): for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.get(k), expected_values[d.item_code][i]) self.assertEquals(d.get(k), expected_values[d.item_code][i])
def test_item_wise_tax_breakup(self):
si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
si.append("taxes", {
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 10
})
si.insert()
tax_breakup_html = '''\n<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th>\n<th class="text-right" style="min-width: 80px;">Taxable Amount</th>\n<th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">\u20b9 5,000.00</td><td class="text-right">(10.0%) \u20b9 500.00</td></tr></tbody>\n\t</table>\n</div>'''
self.assertEqual(si.other_charges_calculation, tax_breakup_html)
def create_sales_invoice(**args): def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice") si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args) args = frappe._dict(args)

View File

@ -11,6 +11,7 @@
"doctype": "DocType", "doctype": "DocType",
"document_type": "Document", "document_type": "Document",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
@ -1423,7 +1424,7 @@
"collapsible": 1, "collapsible": 1,
"collapsible_depends_on": "eval:doc.serial_no || doc.batch_no", "collapsible_depends_on": "eval:doc.serial_no || doc.batch_no",
"columns": 0, "columns": 0,
"depends_on": "", "depends_on": "eval: parent.update_stock",
"fieldname": "warehouse_and_reference", "fieldname": "warehouse_and_reference",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -2165,7 +2166,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-07-03 19:34:14.820285", "modified": "2017-07-06 17:54:03.347700",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice Item", "name": "Sales Invoice Item",

View File

@ -10,7 +10,7 @@ from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff,
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False, def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
company=None, reset_period_on_fy_change=True): company=None, reset_period_on_fy_change=True):
"""Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label} """Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
Periodicity can be (Yearly, Quarterly, Monthly)""" Periodicity can be (Yearly, Quarterly, Monthly)"""
@ -85,8 +85,8 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v
return period_list return period_list
def get_fiscal_year_data(from_fiscal_year, to_fiscal_year): def get_fiscal_year_data(from_fiscal_year, to_fiscal_year):
fiscal_year = frappe.db.sql("""select min(year_start_date) as year_start_date, fiscal_year = frappe.db.sql("""select min(year_start_date) as year_start_date,
max(year_end_date) as year_end_date from `tabFiscal Year` where max(year_end_date) as year_end_date from `tabFiscal Year` where
name between %(from_fiscal_year)s and %(to_fiscal_year)s""", name between %(from_fiscal_year)s and %(to_fiscal_year)s""",
{'from_fiscal_year': from_fiscal_year, 'to_fiscal_year': to_fiscal_year}, as_dict=1) {'from_fiscal_year': from_fiscal_year, 'to_fiscal_year': to_fiscal_year}, as_dict=1)
@ -110,7 +110,7 @@ def get_label(periodicity, from_date, to_date):
label = formatdate(from_date, "MMM YY") + "-" + formatdate(to_date, "MMM YY") label = formatdate(from_date, "MMM YY") + "-" + formatdate(to_date, "MMM YY")
return label return label
def get_data(company, root_type, balance_must_be, period_list, filters=None, def get_data(company, root_type, balance_must_be, period_list, filters=None,
accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False, accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False,
ignore_accumulated_values_for_fy=False): ignore_accumulated_values_for_fy=False):
@ -119,16 +119,16 @@ def get_data(company, root_type, balance_must_be, period_list, filters=None,
return None return None
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts) accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
company_currency = frappe.db.get_value("Company", company, "default_currency") company_currency = frappe.db.get_value("Company", company, "default_currency")
gl_entries_by_account = {} gl_entries_by_account = {}
for root in frappe.db.sql("""select lft, rgt from tabAccount for root in frappe.db.sql("""select lft, rgt from tabAccount
where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1): where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1):
set_gl_entries_by_account(company, set_gl_entries_by_account(company,
period_list[0]["year_start_date"] if only_current_fiscal_year else None, period_list[0]["year_start_date"] if only_current_fiscal_year else None,
period_list[-1]["to_date"], period_list[-1]["to_date"],
root.lft, root.rgt, filters, root.lft, root.rgt, filters,
gl_entries_by_account, ignore_closing_entries=ignore_closing_entries) gl_entries_by_account, ignore_closing_entries=ignore_closing_entries)
@ -136,7 +136,7 @@ def get_data(company, root_type, balance_must_be, period_list, filters=None,
accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values) accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values)
out = prepare_data(accounts, balance_must_be, period_list, company_currency) out = prepare_data(accounts, balance_must_be, period_list, company_currency)
out = filter_out_zero_value_rows(out, parent_children_map) out = filter_out_zero_value_rows(out, parent_children_map)
if out: if out:
add_total_row(out, root_type, balance_must_be, period_list, company_currency) add_total_row(out, root_type, balance_must_be, period_list, company_currency)
@ -151,13 +151,13 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accum
if entry.posting_date <= period.to_date: if entry.posting_date <= period.to_date:
if (accumulated_values or entry.posting_date >= period.from_date) and \ if (accumulated_values or entry.posting_date >= period.from_date) and \
(not ignore_accumulated_values_for_fy or (not ignore_accumulated_values_for_fy or
entry.fiscal_year == period.to_date_fiscal_year): entry.fiscal_year == period.to_date_fiscal_year):
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit) 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: if entry.posting_date < period_list[0].year_start_date:
d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit) d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit)
def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values): def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values):
"""accumulate children's values in parent accounts""" """accumulate children's values in parent accounts"""
for d in reversed(accounts): for d in reversed(accounts):
@ -165,7 +165,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accu
for period in period_list: for period in period_list:
accounts_by_name[d.parent_account][period.key] = \ accounts_by_name[d.parent_account][period.key] = \
accounts_by_name[d.parent_account].get(period.key, 0.0) + d.get(period.key, 0.0) accounts_by_name[d.parent_account].get(period.key, 0.0) + d.get(period.key, 0.0)
accounts_by_name[d.parent_account]["opening_balance"] = \ accounts_by_name[d.parent_account]["opening_balance"] = \
accounts_by_name[d.parent_account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0) accounts_by_name[d.parent_account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0)
@ -173,15 +173,15 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
data = [] data = []
year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d") year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d")
year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d") year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d")
for d in accounts: for d in accounts:
# add to output # add to output
has_value = False has_value = False
total = 0 total = 0
row = frappe._dict({ row = frappe._dict({
"account_name": d.account_name, "account_name": _(d.account_name),
"account": d.name, "account": _(d.name),
"parent_account": d.parent_account, "parent_account": _(d.parent_account),
"indent": flt(d.indent), "indent": flt(d.indent),
"year_start_date": year_start_date, "year_start_date": year_start_date,
"year_end_date": year_end_date, "year_end_date": year_end_date,
@ -192,7 +192,7 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
if d.get(period.key) and balance_must_be=="Credit": if d.get(period.key) and balance_must_be=="Credit":
# change sign based on Debit or Credit, since calculation is done using (debit - credit) # change sign based on Debit or Credit, since calculation is done using (debit - credit)
d[period.key] *= -1 d[period.key] *= -1
row[period.key] = flt(d.get(period.key, 0.0), 3) row[period.key] = flt(d.get(period.key, 0.0), 3)
if abs(row[period.key]) >= 0.005: if abs(row[period.key]) >= 0.005:
@ -203,9 +203,9 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
row["has_value"] = has_value row["has_value"] = has_value
row["total"] = total row["total"] = total
data.append(row) data.append(row)
return data return data
def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False): def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False):
data_with_value = [] data_with_value = []
for d in data: for d in data:
@ -224,8 +224,8 @@ def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False
def add_total_row(out, root_type, balance_must_be, period_list, company_currency): def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
total_row = { total_row = {
"account_name": "'" + _("Total {0} ({1})").format(root_type, balance_must_be) + "'", "account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"account": "'" + _("Total {0} ({1})").format(root_type, balance_must_be) + "'", "account": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"currency": company_currency "currency": company_currency
} }
@ -235,11 +235,11 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
total_row.setdefault(period.key, 0.0) total_row.setdefault(period.key, 0.0)
total_row[period.key] += row.get(period.key, 0.0) total_row[period.key] += row.get(period.key, 0.0)
row[period.key] = "" row[period.key] = ""
total_row.setdefault("total", 0.0) total_row.setdefault("total", 0.0)
total_row["total"] += flt(row["total"]) total_row["total"] += flt(row["total"])
row["total"] = "" row["total"] = ""
if total_row.has_key("total"): if total_row.has_key("total"):
out.append(total_row) out.append(total_row)

View File

@ -278,7 +278,7 @@ class GrossProfitGenerator(object):
inner join `tabSales Invoice Item` on `tabSales Invoice Item`.parent = `tabSales Invoice`.name inner join `tabSales Invoice Item` on `tabSales Invoice Item`.parent = `tabSales Invoice`.name
{sales_team_table} {sales_team_table}
where where
`tabSales Invoice`.docstatus = 1 and `tabSales Invoice`.is_return != 1 {conditions} {match_cond} `tabSales Invoice`.docstatus = 1 {conditions} {match_cond}
order by order by
`tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc""" `tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc"""
.format(conditions=conditions, sales_person_cols=sales_person_cols, .format(conditions=conditions, sales_person_cols=sales_person_cols,

View File

@ -270,6 +270,9 @@ def make_purchase_receipt(source_name, target_doc=None):
doc = get_mapped_doc("Purchase Order", source_name, { doc = get_mapped_doc("Purchase Order", source_name, {
"Purchase Order": { "Purchase Order": {
"doctype": "Purchase Receipt", "doctype": "Purchase Receipt",
"field_map": {
"per_billed": "per_billed"
},
"validation": { "validation": {
"docstatus": ["=", 1], "docstatus": ["=", 1],
} }

View File

@ -3,8 +3,10 @@
# See license.txt # See license.txt
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe
import unittest import unittest
import frappe
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
from frappe.utils import nowdate from frappe.utils import nowdate
class TestRequestforQuotation(unittest.TestCase): class TestRequestforQuotation(unittest.TestCase):
@ -28,6 +30,31 @@ class TestRequestforQuotation(unittest.TestCase):
self.assertEquals(sq1.get('items')[0].item_code, "_Test Item") self.assertEquals(sq1.get('items')[0].item_code, "_Test Item")
self.assertEquals(sq1.get('items')[0].qty, 5) self.assertEquals(sq1.get('items')[0].qty, 5)
def test_make_supplier_quotation_with_special_characters(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
supplier = frappe.new_doc("Supplier")
supplier.supplier_name = "_Test Supplier '1"
supplier.supplier_type = "_Test Supplier Type"
supplier.insert()
rfq = make_request_for_quotation(supplier_wt_appos)
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
sq.submit()
frappe.form_dict = frappe.local("form_dict")
frappe.form_dict.name = rfq.name
self.assertEqual(
check_supplier_has_docname_access(supplier_wt_appos[0].get('supplier')),
True
)
# reset form_dict
frappe.form_dict.name = None
def test_make_supplier_quotation_from_portal(self): def test_make_supplier_quotation_from_portal(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
rfq = make_request_for_quotation() rfq = make_request_for_quotation()
@ -44,8 +71,11 @@ class TestRequestforQuotation(unittest.TestCase):
self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500) self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500)
def make_request_for_quotation(): def make_request_for_quotation(supplier_data=None):
supplier_data = get_supplier_data() """
:param supplier_data: List containing supplier data
"""
supplier_data = supplier_data if supplier_data else get_supplier_data()
rfq = frappe.new_doc('Request for Quotation') rfq = frappe.new_doc('Request for Quotation')
rfq.transaction_date = nowdate() rfq.transaction_date = nowdate()
rfq.status = 'Draft' rfq.status = 'Draft'
@ -77,3 +107,8 @@ def get_supplier_data():
"supplier": "_Test Supplier 1", "supplier": "_Test Supplier 1",
"supplier_name": "_Test Supplier 1" "supplier_name": "_Test Supplier 1"
}] }]
supplier_wt_appos = [{
"supplier": "_Test Supplier '1",
"supplier_name": "_Test Supplier '1",
}]

View File

@ -0,0 +1,8 @@
### Production Order Enahancement
- Show required items child table.
- Source warehouse for each Raw Materials, in Production Order Item and BOM Item table.
- Group warehouse allowed for Source and WIP warehouse.
### GST Tax Invoice Print Format
- Added print format to show tax(GST) breakup.
- Total Stock Summary report.
- Include Search Fields in Customer Query.

View File

@ -137,7 +137,14 @@ def get_data():
{ {
"type": "doctype", "type": "doctype",
"name": "Assessment Result Tool" "name": "Assessment Result Tool"
} },
{
"type": "report",
"is_query_report": True,
"name": "Course wise Assessment Report",
"doctype": "Assessment Result"
},
] ]
}, },
{ {

View File

@ -169,6 +169,7 @@ def create_variant(item, args):
return variant return variant
def copy_attributes_to_variant(item, variant): def copy_attributes_to_variant(item, variant):
from frappe.model import no_value_fields from frappe.model import no_value_fields
@ -181,8 +182,9 @@ def copy_attributes_to_variant(item, variant):
exclude_fields += ['manufacturer', 'manufacturer_part_no'] exclude_fields += ['manufacturer', 'manufacturer_part_no']
for field in item.meta.fields: for field in item.meta.fields:
if field.fieldtype not in no_value_fields and (not field.no_copy)\ # "Table" is part of `no_value_field` but we shouldn't ignore tables
and field.fieldname not in exclude_fields: if (field.fieldtype == 'Table' or field.fieldtype not in no_value_fields) \
and (not field.no_copy) and field.fieldname not in exclude_fields:
if variant.get(field.fieldname) != item.get(field.fieldname): if variant.get(field.fieldname) != item.get(field.fieldname):
variant.set(field.fieldname, item.get(field.fieldname)) variant.set(field.fieldname, item.get(field.fieldname))
variant.variant_of = item.name variant.variant_of = item.name

View File

@ -68,14 +68,17 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
fields = ["name", "customer_name", "customer_group", "territory"] fields = ["name", "customer_name", "customer_group", "territory"]
meta = frappe.get_meta("Customer") meta = frappe.get_meta("Customer")
fields = fields + [f for f in meta.get_search_fields() if not f in fields] searchfields = meta.get_search_fields()
searchfields = searchfields + [f for f in [searchfield or "name", "customer_name"] \
if not f in searchfields]
fields = fields + [f for f in searchfields if not f in fields]
fields = ", ".join(fields) fields = ", ".join(fields)
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
return frappe.db.sql("""select {fields} from `tabCustomer` return frappe.db.sql("""select {fields} from `tabCustomer`
where docstatus < 2 where docstatus < 2
and ({key} like %(txt)s and ({scond}) and disabled=0
or customer_name like %(txt)s) and disabled=0
{mcond} {mcond}
order by order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
@ -84,7 +87,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
name, customer_name name, customer_name
limit %(start)s, %(page_len)s""".format(**{ limit %(start)s, %(page_len)s""".format(**{
"fields": fields, "fields": fields,
"key": searchfield, "scond": searchfields,
"mcond": get_match_cond(doctype) "mcond": get_match_cond(doctype)
}), { }), {
'txt': "%%%s%%" % txt, 'txt': "%%%s%%" % txt,

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import json import json
import frappe, erpnext import frappe, erpnext
from frappe import _, scrub from frappe import _, scrub
from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction from frappe.utils import cint, flt, cstr, fmt_money, round_based_on_smallest_currency_fraction
from erpnext.controllers.accounts_controller import validate_conversion_rate, \ from erpnext.controllers.accounts_controller import validate_conversion_rate, \
validate_taxes_and_charges, validate_inclusive_tax validate_taxes_and_charges, validate_inclusive_tax
@ -24,6 +24,9 @@ class calculate_taxes_and_totals(object):
if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]: if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
self.calculate_total_advance() self.calculate_total_advance()
if self.doc.meta.get_field("other_charges_calculation"):
self.set_item_wise_tax_breakup()
def _calculate(self): def _calculate(self):
self.calculate_item_values() self.calculate_item_values()
@ -504,3 +507,105 @@ class calculate_taxes_and_totals(object):
rate_with_margin = flt(item.price_list_rate) + flt(margin_value) rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
return rate_with_margin return rate_with_margin
def set_item_wise_tax_breakup(self):
item_tax = {}
tax_accounts = []
company_currency = erpnext.get_company_currency(self.doc.company)
item_tax, tax_accounts = self.get_item_tax(item_tax, tax_accounts, company_currency)
headings = get_table_column_headings(tax_accounts)
distinct_items = self.get_distinct_items()
rows = get_table_rows(distinct_items, item_tax, tax_accounts, company_currency)
if not rows:
self.doc.other_charges_calculation = ""
else:
self.doc.other_charges_calculation = '''
<div class="tax-break-up" style="overflow-x: auto;">
<table class="table table-bordered table-hover">
<thead><tr>{headings}</tr></thead>
<tbody>{rows}</tbody>
</table>
</div>'''.format(**{
"headings": "\n".join(headings),
"rows": "\n".join(rows)
})
def get_item_tax(self, item_tax, tax_accounts, company_currency):
for tax in self.doc.taxes:
tax_amount_precision = tax.precision("tax_amount")
tax_rate_precision = tax.precision("rate");
item_tax_map = self._load_item_tax_rate(tax.item_wise_tax_detail)
for item_code, tax_data in item_tax_map.items():
if not item_tax.get(item_code):
item_tax[item_code] = {}
if isinstance(tax_data, list):
tax_rate = ""
if tax_data[0]:
if tax.charge_type == "Actual":
tax_rate = fmt_money(flt(tax_data[0], tax_amount_precision),
tax_amount_precision, company_currency)
else:
tax_rate = cstr(flt(tax_data[0], tax_rate_precision)) + "%"
tax_amount = fmt_money(flt(tax_data[1], tax_amount_precision),
tax_amount_precision, company_currency)
item_tax[item_code][tax.name] = [tax_rate, tax_amount]
else:
item_tax[item_code][tax.name] = [cstr(flt(tax_data, tax_rate_precision)) + "%", ""]
tax_accounts.append([tax.name, tax.account_head])
return item_tax, tax_accounts
def get_distinct_items(self):
distinct_item_names = []
distinct_items = []
for item in self.doc.items:
item_code = item.item_code or item.item_name
if item_code not in distinct_item_names:
distinct_item_names.append(item_code)
distinct_items.append(item)
return distinct_items
def get_table_column_headings(tax_accounts):
headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts]
headings = []
for head in headings_name:
if head == _("Item Name"):
headings.append('<th style="min-width: 120px;" class="text-left">' + (head or "") + "</th>")
else:
headings.append('<th style="min-width: 80px;" class="text-right">' + (head or "") + "</th>")
return headings
def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency):
rows = []
for item in distinct_items:
item_tax_record = item_tax.get(item.item_code or item.item_name)
if not item_tax_record:
continue
taxes = []
for head in tax_accounts:
if item_tax_record[head[0]]:
taxes.append("<td class='text-right'>(" + item_tax_record[head[0]][0] + ") "
+ item_tax_record[head[0]][1] + "</td>")
else:
taxes.append("<td></td>")
rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{
"item_name": item.item_name,
"taxable_amount": fmt_money(item.net_amount, item.precision("net_amount"), company_currency),
"taxes": "\n".join(taxes)
}))
return rows

View File

@ -0,0 +1,58 @@
from __future__ import unicode_literals
import frappe
import json
import unittest
from erpnext.controllers.item_variant import copy_attributes_to_variant, make_variant_item_code
# python 3 compatibility stuff
try:
unicode = unicode
except NameError:
# Python 3
basestring = (str, bytes)
else:
# Python 2
basestring = basestring
def create_variant_with_tables(item, args):
if isinstance(args, basestring):
args = json.loads(args)
template = frappe.get_doc("Item", item)
template.quality_parameters.append({
"specification": "Moisture",
"value": "&lt; 5%",
})
variant = frappe.new_doc("Item")
variant.variant_based_on = 'Item Attribute'
variant_attributes = []
for d in template.attributes:
variant_attributes.append({
"attribute": d.attribute,
"attribute_value": args.get(d.attribute)
})
variant.set("attributes", variant_attributes)
copy_attributes_to_variant(template, variant)
make_variant_item_code(template.item_code, template.item_name, variant)
return variant
def make_item_variant():
frappe.delete_doc_if_exists("Item", "_Test Variant Item-S", force=1)
variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Small"}')
variant.item_code = "_Test Variant Item-S"
variant.item_name = "_Test Variant Item-S"
variant.save()
return variant
class TestItemVariant(unittest.TestCase):
def test_tables_in_template_copied_to_variant(self):
variant = make_item_variant()
self.assertNotEqual(variant.get("quality_parameters"), [])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 173 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -640,8 +640,8 @@ attach them to the start of each source file to most effectively state
the exclusion of warranty; and each file should have at least the the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.</p> "copyright" line and a pointer to where the full notice is found.</p>
<pre><code> &lt;one line to give the program's name and a brief idea of what it does.&gt; <pre><code> &lt;one line="" to="" give="" the="" program's="" name="" and="" a="" brief="" idea="" of="" what="" it="" does.=""&gt;
Copyright (C) &lt;year&gt; &lt;name of author&gt; Copyright (C) &lt;year&gt; &lt;name of="" author=""&gt;
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -38,15 +38,13 @@ Hinweis: Stellen Sie sicher, dass im Abschnitt "Weitere Informationen" "Ist Erö
Vervollständigen Sie die Buchungssätze auf der Soll- und Haben-Seite. Vervollständigen Sie die Buchungssätze auf der Soll- und Haben-Seite.
![Eröffnungsbuchung]({{docs_base_url}}/assets/old_images/erpnext/opening-entry-1.png) <img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/opening-6.png">
Um einen Eröffnungsstand einzupflegen, erstellen Sie einen Buchungssatz für ein Konto oder eine Gruppe von Konten. Um einen Eröffnungsstand einzupflegen, erstellen Sie einen Buchungssatz für ein Konto oder eine Gruppe von Konten.
Beispiel: Wenn Sie die Kontenstände von drei Bankkonten einpflegen möchten, dann erstellen Sie Buchungssätze der folgenden Art und Weise: Beispiel: Wenn Sie die Kontenstände von drei Bankkonten einpflegen möchten, dann erstellen Sie Buchungssätze der folgenden Art und Weise:
![Eröffnungsbuchung]({{docs_base_url}}/assets/old_images/erpnext/image-temp-opening.png) <img class="screenshot" alt="Opening Account" src="{{docs_base_url}}/assets/img/accounts/opening-3.png">
![Eröffnungsbuchung]({{docs_base_url}}/assets/old_images/erpnext/opening-entry-2.png)
Um einen Ausgleich herzustellen, wird ein temporäres Konto für Vermögen und Verbindlichkeiten verwendet. Wenn Sie einen Anfangsbestand in einem Verbindlichkeitenkonto einpflegen, können Sie zum Ausgleich ein temporäres Vermögenskonto verwenden. Um einen Ausgleich herzustellen, wird ein temporäres Konto für Vermögen und Verbindlichkeiten verwendet. Wenn Sie einen Anfangsbestand in einem Verbindlichkeitenkonto einpflegen, können Sie zum Ausgleich ein temporäres Vermögenskonto verwenden.
@ -61,7 +59,8 @@ Sie können zwei Eröffnungsbuchungssätze erstellen:
Wenn Sie die Buchungen erstellt haben, schaut der Bericht zur Probebilanz in etwa wie folgt aus: Wenn Sie die Buchungen erstellt haben, schaut der Bericht zur Probebilanz in etwa wie folgt aus:
![Probebilanz]({{docs_base_url}}/assets/old_images/erpnext/trial-balance-1.png) <img class="screenshot" alt="Probebilanz" src="{{docs_base_url}}/assets/img/accounts/opening-4.png">
### Offene Rechnungen ### Offene Rechnungen

View File

@ -3,10 +3,9 @@
Dieses Diagramm stellt dar, wie ERPNext die Informationen und Vorgänge in Ihrem Unternehmen über Schlüsselfunktionen nachverfolgt. Dieses Diagramm gibt nicht alle Funktionalitäten von ERPNext wieder. Dieses Diagramm stellt dar, wie ERPNext die Informationen und Vorgänge in Ihrem Unternehmen über Schlüsselfunktionen nachverfolgt. Dieses Diagramm gibt nicht alle Funktionalitäten von ERPNext wieder.
![]({{docs_base_url}}/assets/old_images/erpnext/overview.png)
<img class="screenshot" alt="Hohe Auflösung" src="{{docs_base_url}}/assets/img/setup/overview.png">
[Hohe Auflösung]({{docs_base_url}}/assets/old_images/erpnext/overview.png)
_Anmerkung: Nicht alle Schritte sind zwingend erforderlich. ERPNext erlaubt es Ihnen nach eigenem Gutdünken Schritte auszulassen, wenn Sie den Prozess vereinfachen wollen._ _Anmerkung: Nicht alle Schritte sind zwingend erforderlich. ERPNext erlaubt es Ihnen nach eigenem Gutdünken Schritte auszulassen, wenn Sie den Prozess vereinfachen wollen._

View File

@ -11,7 +11,8 @@ Wenn Sie bei Ihrer Tätigkeit bestimmte Prozesse an eine Drittpartei, bei der Si
2. Erstellen Sie ein Lager für den Lieferanten, damit Sie die übergebenen Artikel nachverfolgen können (möglicherweise geben Sie ja Artikel im Wert einer Monatslieferung außer Haus). 2. Erstellen Sie ein Lager für den Lieferanten, damit Sie die übergebenen Artikel nachverfolgen können (möglicherweise geben Sie ja Artikel im Wert einer Monatslieferung außer Haus).
3. Stellen Sie für den bearbeiteten Artikel und der Artikelvorlage den Punkt "Ist Fremdvergabe" auf JA ein. 3. Stellen Sie für den bearbeiteten Artikel und der Artikelvorlage den Punkt "Ist Fremdvergabe" auf JA ein.
![Fremdvergabe]({{docs_base_url}}/assets/old_images/erpnext/subcontract.png) <img class="screenshot" alt="Fremdvergabe" src="{{docs_base_url}}/assets/img/manufacturing/subcontract.png">
**Schritt 1:** Erstellen Sie für den bearbeiteten Artikel eine Stückliste, die den unbearbeiteten Artikel als Unterartikel enthält. Beispiel: Wenn Sie einen Stift herstellen, wird der bearbeitete Stift mit der Stückliste benannt, wbei der Tintentank, der Knopf und andere Artikel, die in die Fertigung eingehen als Unterartikel verwaltet werden. **Schritt 1:** Erstellen Sie für den bearbeiteten Artikel eine Stückliste, die den unbearbeiteten Artikel als Unterartikel enthält. Beispiel: Wenn Sie einen Stift herstellen, wird der bearbeitete Stift mit der Stückliste benannt, wbei der Tintentank, der Knopf und andere Artikel, die in die Fertigung eingehen als Unterartikel verwaltet werden.

View File

@ -27,7 +27,7 @@ Sie sollten sich an eine spezielle Vorlage eines Tabellenblattes halten um den B
#### Schritt 2: Geben Sie Daten in die CSV-Datei ein. #### Schritt 2: Geben Sie Daten in die CSV-Datei ein.
![Lagerabgleichsdaten]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-data.png) <img class="screenshot" alt="Bestandsabgleich" src="{{docs_base_url}}/assets/img/setup/stock-reco-data.png">
Das CSV-Format beachtet Groß- und Kleinschreibung. Verändern Sie nicht die Kopfbezeichnungen, die in der Vorlage vordefiniert wurden. In den Spalten "Artikelnummer" und "Lager" geben Sie bitte die richtige Artikelnummer und das Lager ein, so wie es in ERPNext bezeichnet wird. Für die Menge geben Sie den Lagerbestand, den Sie für diesen Artikel erfassen wollen, in einem bestimmten Lager ein. Wenn Sie die Menge oder den wertmäßigen Betrag eines Artikels nicht ändern wollen, dann lassen Sie den Eintrag leer. Das CSV-Format beachtet Groß- und Kleinschreibung. Verändern Sie nicht die Kopfbezeichnungen, die in der Vorlage vordefiniert wurden. In den Spalten "Artikelnummer" und "Lager" geben Sie bitte die richtige Artikelnummer und das Lager ein, so wie es in ERPNext bezeichnet wird. Für die Menge geben Sie den Lagerbestand, den Sie für diesen Artikel erfassen wollen, in einem bestimmten Lager ein. Wenn Sie die Menge oder den wertmäßigen Betrag eines Artikels nicht ändern wollen, dann lassen Sie den Eintrag leer.
Anmerkung: Geben Sie keine "0" ein, wenn sie die Menge oder den wertmäßigen Betrag nicht ändern wollen. Sonst kalkuliert das System eine Menge von "0". Lassen Sie also das Feld leer! Anmerkung: Geben Sie keine "0" ein, wenn sie die Menge oder den wertmäßigen Betrag nicht ändern wollen. Sonst kalkuliert das System eine Menge von "0". Lassen Sie also das Feld leer!
@ -52,11 +52,12 @@ Notiz: Wenn Sie die bewerteten Beträge eines Artikels eingeben, können Sie zum
#### Schritt 4: Überprüfen Sie die Daten zum Bestandsabgleich #### Schritt 4: Überprüfen Sie die Daten zum Bestandsabgleich
![Bestandsabgleich Überprüfung]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-upload.png) <img class="screenshot" alt="Bestandsabgleich Überprüfung" src="{{docs_base_url}}/assets/img/setup/stock-reco-upload.gif">
### Bericht zum Lagerbuch ### Bericht zum Lagerbuch
![Bestandsabgleich Hauptbuch]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-ledger.png) <img class="screenshot" alt="Bestandsabgleich" src="{{docs_base_url}}/assets/img/setup/stock-reco-ledger.png">
##### So arbeitet der Bestandsabgleich ##### So arbeitet der Bestandsabgleich

View File

@ -7,7 +7,7 @@ Unten Sehen Sie ein Beispiel eines Worklflows.
Wenn ein Benutzer einen Urlaub beantragt, dann wird seine Anfrage an die Personalabteilung weiter geleitet. Die Personalabteilung, repräsentiert durch einen Mitarbeiter der Personalabteilung, wird diese Anfrage dann entweder genehmigen oder ablehnen. Wenn dieser Prozess abgeschlossen ist, dann bekommt der Vorgesetzte des Benutzers (der Urlaubsgenehmiger) eine Mitteilung, dass die Personalabteilung den Antrag genehmigt oder abgelehnt hat. Der Vorgesetzte, der die genehmigende Instanz ist, wird dann den Antrag entweder genehmigen oder ablehnen. Dementsprechend bekommt der Benutzer dann eine Genehmigung oder eine Ablehnung. Wenn ein Benutzer einen Urlaub beantragt, dann wird seine Anfrage an die Personalabteilung weiter geleitet. Die Personalabteilung, repräsentiert durch einen Mitarbeiter der Personalabteilung, wird diese Anfrage dann entweder genehmigen oder ablehnen. Wenn dieser Prozess abgeschlossen ist, dann bekommt der Vorgesetzte des Benutzers (der Urlaubsgenehmiger) eine Mitteilung, dass die Personalabteilung den Antrag genehmigt oder abgelehnt hat. Der Vorgesetzte, der die genehmigende Instanz ist, wird dann den Antrag entweder genehmigen oder ablehnen. Dementsprechend bekommt der Benutzer dann eine Genehmigung oder eine Ablehnung.
![Workflow]({{docs_base_url}}/assets/old_images/erpnext/workflow-leave-fl.jpg) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-leave-fl.jpg">
Um einen Workflow und Übergangsregeln zu erstellen, gehen Sie zu: Um einen Workflow und Übergangsregeln zu erstellen, gehen Sie zu:
@ -37,14 +37,14 @@ Gehen Sie in das Modul Personalwesen und klicken Sie auf Urlaubsantrag. Beantrag
Wenn ein Urlaubsantrag übertragen wird, steht der Status in der Ecke der rechten Seite auf "Beantragt". Wenn ein Urlaubsantrag übertragen wird, steht der Status in der Ecke der rechten Seite auf "Beantragt".
![Workflow Mitarbeiter LA]({{docs_base_url}}/assets/old_images/erpnext/workflow-employee-la.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-3.png">
Wenn sich ein Mitarbeiter der Personalabteilung anmeldet, dann kann er den Antrag genehmigen oder ablehnen. Wenn eine Genehmigung erfolgt, wechselt der Status in der rechten Ecke zu "Genehmigt". Es wird jedoch ein blaues Informationssymbol angezeigt, welches aussagt, dass der Urlaubsantrag noch anhängig ist. Wenn sich ein Mitarbeiter der Personalabteilung anmeldet, dann kann er den Antrag genehmigen oder ablehnen. Wenn eine Genehmigung erfolgt, wechselt der Status in der rechten Ecke zu "Genehmigt". Es wird jedoch ein blaues Informationssymbol angezeigt, welches aussagt, dass der Urlaubsantrag noch anhängig ist.
![Urlaubsgenehmiger]({{docs_base_url}}/assets/old_images/erpnext/workflow-hr-user-la.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-4.png">
Wenn der Urlaubsgenehmiger die Seite mit den Urlaubsanträgen öffnet, kann er den Status von "Genehmigt" auf "Abgelehnt" ändern. Wenn der Urlaubsgenehmiger die Seite mit den Urlaubsanträgen öffnet, kann er den Status von "Genehmigt" auf "Abgelehnt" ändern.
![Workflow Urlaubsgenehmiger]({{docs_base_url}}/assets/old_images/erpnext/workflow-leave-approver-la.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-5.png">
{next} {next}

View File

@ -6,7 +6,7 @@ functions. This diagram does not cover all the features of ERPNext.
![]({{docs_base_url}}/assets/old_images/erpnext/overview.png) ![]({{docs_base_url}}/assets/old_images/erpnext/overview.png)
[Full Resolution]({{docs_base_url}}/assets/old_images/erpnext/overview.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/overview.png">
_Note: Not all of the steps are mandatory. ERPNext allows you to freely skip _Note: Not all of the steps are mandatory. ERPNext allows you to freely skip
steps if you want to simplify the process._ steps if you want to simplify the process._

View File

@ -17,9 +17,15 @@ by:
* Select the Item to be produced. * Select the Item to be produced.
* The default BOM for that item will be fetched by the system. You can also change BOM. * The default BOM for that item will be fetched by the system. You can also change BOM.
* Enter the Qty to manufacture.
* If the selected BOM has operartion mentioned in it, the system shall fetch all operations from BOM. * If the selected BOM has operartion mentioned in it, the system shall fetch all operations from BOM.
* Mention the Planned Start Date (an Estimated Date at which you want the Production to begin.) * Mention the Planned Start Date (an Estimated Date at which you want the Production to begin.)
* Select Warehouses. Work-in-Progress Warehouse is where your Items will be transferred when you begin production and Target Warehouse is where you store finished Items before they are shipped. * Select Warehouses:
* Source Warehouses: The warehouse where you store your raw materials. Each required item can have separate source warehouse. Group warehouse also can be selected as source warehouse. On submission of Production Order, the raw mateirals will be reserved in these warehouses for production usage.
* Work-in-Progress Warehouse: The warehouse where your Items will be transferred when you begin production. Group Warehouse can also be selected as Work-in-Progress warehouse.
* Target Warehouse: The warehouse where you store finished Items before they are shipped.
* Scrap Warehouse: Scrap Items will be stored in this warehouse.
* Required Items: All the required items (raw materials) will be fetched from BOM and populated in this table. Here you can also change the default source warehouse for any item. And during the production, you can track transferred raw materials from this table.
> Note : You can save a Production Order without selecting the warehouses, but warehouses are mandatory for submitting a Production Order > Note : You can save a Production Order without selecting the warehouses, but warehouses are mandatory for submitting a Production Order

View File

@ -14,6 +14,13 @@ Go to the Company master and add the GSTIN to your default address.
<img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/gstin-company.gif"> <img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/gstin-company.gif">
**Include GSTIN number in the Address Template**
Open Address Template record for India, add GSTIN number and State Code there if not exists.
<img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/address-template-gstin.png">
### 2. Setting up HSN Codes ### 2. Setting up HSN Codes
According to the GST Law, your itemised invoices must contain the HSN Code related to that Item. ERPNext comes pre-installed with all 12,000+ HSN Codes so that you can easily select the relevant HSN Code in your Item According to the GST Law, your itemised invoices must contain the HSN Code related to that Item. ERPNext comes pre-installed with all 12,000+ HSN Codes so that you can easily select the relevant HSN Code in your Item
@ -54,6 +61,12 @@ For **Sales Invoice**,
<img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif"> <img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif">
### 6. Print GST Tax Invoice
To print Tax Invoice as per GSTN guidelines, please select **GST Tax Invoice** print format. This print format includes company address, GSTIN numbers, HSN/SAC Code and item-wise tax breakup. And while printing select correct value of Invoice Copy field, to mention whether it is for the Customer, Supplier or Transporter.
<img class="screenshot" alt="Sample GST Tax Invoice" src="{{docs_base_url}}/assets/img/regional/india/sample-gst-tax-invoice.png">
### Reports ### Reports
ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list. ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.

View File

@ -91,5 +91,5 @@ To setup Email Digests, go to:
#### Figure 4: Set up Email Digest #### Figure 4: Set up Email Digest
![Email Digest]({{docs_base_url}}/assets/old_images/erpnext/email-digest.png) <img class="screenshot" alt="Email Digest" src="{{docs_base_url}}/assets/img/setup/email/email-digest.png">

View File

@ -31,7 +31,7 @@ A predefined template of an spreadsheet file should be followed for importing it
#### Step 2: Enter Data in csv file. #### Step 2: Enter Data in csv file.
![Stock Reco Data]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-data.png) <img class="screenshot" alt="Stock Reconciliation" src="{{docs_base_url}}/assets/img/setup/stock-reco-data.png">
The csv format is case-sensitive. Do not edit the headers which are preset in the template. In the Item Code and Warehouse column, enter exact Item Code and Warehouse as created in your ERPNext account. For quatity, enter stock level you wish to set for that item, in a specific warehouse. The csv format is case-sensitive. Do not edit the headers which are preset in the template. In the Item Code and Warehouse column, enter exact Item Code and Warehouse as created in your ERPNext account. For quatity, enter stock level you wish to set for that item, in a specific warehouse.
@ -59,11 +59,12 @@ report. The report will show you all types of rates.
#### Step 4: Review the reconciliation data #### Step 4: Review the reconciliation data
![Stock Reco Review]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-upload.png) <img class="screenshot" alt="Stock Reconciliation" src="{{docs_base_url}}/assets/img/setup/stock-reco-upload.gif">
### Stock Ledger Report ### Stock Ledger Report
![Stock Reco Ledger]({{docs_base_url}}/assets/old_images/erpnext/stock-reco-ledger.png) <img class="screenshot" alt="Stock Reconciliation" src="{{docs_base_url}}/assets/img/setup//stock-reco-ledger.png">
**How Stock Reconciliation Works** **How Stock Reconciliation Works**

View File

@ -11,7 +11,7 @@ will get an indication that the HR department has Accepted or Rejected. The
Manager, who is the approving authority, will either Approve or Reject this Manager, who is the approving authority, will either Approve or Reject this
request. Accordingly,the user will get his Approved or Rejected status. request. Accordingly,the user will get his Approved or Rejected status.
![Workflow]({{docs_base_url}}/assets/old_images/erpnext/workflow-leave-fl.jpg) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-leave-fl.jpg">
To make this Workflow and transition rules go to : To make this Workflow and transition rules go to :
@ -46,15 +46,15 @@ workflow transition step that says from submitted you can cancel.
When a Leave Application is saved by Employee, the status of the document changes to "Applied" When a Leave Application is saved by Employee, the status of the document changes to "Applied"
![Workflow Employee LA]({{docs_base_url}}/assets/img/setup/workflow-3.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-3.png">
When the HR User logs in, he can either Approve or Reject. If approved the When the HR User logs in, he can either Approve or Reject. If approved the
status of the document changes to "Approved by HR". However, it is yet to be approved by Leave Approver. status of the document changes to "Approved by HR". However, it is yet to be approved by Leave Approver.
![Leave Approver]({{docs_base_url}}/assets/img/setup/workflow-4.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-4.png">
When the Leave Approver opens the Leave Application page, he can finally "Approve" or "Reject" the Leave Application. When the Leave Approver opens the Leave Application page, he can finally "Approve" or "Reject" the Leave Application.
![Workflow Leave Approver]({{docs_base_url}}/assets/img/setup/workflow-5.png) <img class="screenshot" alt="Workflow" src="{{docs_base_url}}/assets/img/setup/workflow-5.png">
{next} {next}

View File

@ -37,9 +37,9 @@ These numbers help to track individual units or batches of Items which you sell.
### Re Ordering ### Re Ordering
* **Re-order level** suggests the amount of stock balance in the Warehouse. ***Re-order level** suggests the amount of stock balance in the Warehouse.
* **Re-order Qty** suggests the amount of stock to be ordered to maintain minimum stock levels. ***Re-order Qty** suggests the amount of stock to be ordered to maintain minimum stock levels.
* **Minimum Order Qty** is the minimum quantity for which a Material Request / Purchase Order must be made. ***Minimum Order Qty** is the minimum quantity for which a Material Request / Purchase Order must be made.
### Item Tax ### Item Tax
@ -55,6 +55,8 @@ Inspection Criteria: If a Quality Inspection is prepared for this Item, then thi
### Purchase Details ### Purchase Details
<img alt="Item Purchase Details" class="screenshot" src="{{docs_base_url}}/assets/img/stock/item-purchase.png">
<img class="screenshot" alt="Purchase details" src="{{docs_base_url}}/assets/img/stock/item-purchase.png"> <img class="screenshot" alt="Purchase details" src="{{docs_base_url}}/assets/img/stock/item-purchase.png">
* **Lead time days:** Lead time days are the number of days required for the Item to reach the warehouse. * **Lead time days:** Lead time days are the number of days required for the Item to reach the warehouse.
@ -79,9 +81,13 @@ Inspection Criteria: If a Quality Inspection is prepared for this Item, then thi
* **Default Income Account:** Income account selected here will be fetched automatically in sales invoice for this item. * **Default Income Account:** Income account selected here will be fetched automatically in sales invoice for this item.
* **Cost Centre:** Cost center selected here will be fetched automatically in sales invoice for this item. <img class="screenshot" alt="Sales details" src="{{docs_base_url}}/assets/img/stock/item-sales.png)">
* **Customer Codes:** Track Item Code assigned by the Customers for this Item. This will help you in searching item while creating Sales Order based on the Item Code in the Customer's Purchase Order. <img class="screenshot" alt="Sales details" src="{{docs_base_url}}/assets/img/stock/item-sales.png">
***Cost Centre:** Cost center selected here will be fetched automatically in sales invoice for this item.
***Customer Codes:** Track Item Code assigned by the Customers for this Item. This will help you in searching item while creating Sales Order based on the Item Code in the Customer's Purchase Order.
<img class="screenshot" alt="Sales details" src="{{docs_base_url}}/assets/img/stock/item-sales.png)"> <img class="screenshot" alt="Sales details" src="{{docs_base_url}}/assets/img/stock/item-sales.png)">

View File

@ -0,0 +1,16 @@
Global-search.md
Global search is a word-processing operation in which a complete computer file or set of files is searched for every occurrence of a particular word or other sequence of characters.
We have made the Awesome Bar of ERPNext lot more powerful by adding Global Search feature.
Global Search helps users find information quickly. Its located in the upper right-hand corner in ERPNext.  Simply entering a few characters in the Search will show results from several different record types (Contact, Customer, Issues etc.) related to that keyword. You can also customise the fields based on which search will be shown.
### Using Awesome bar for Global Search.
<img alt="Global Search" class="screenshot" src="{{docs_base_url}}/assets/img/articles/Global Search .gif">
### Enable Global Search for fields in a Doctype.
<img alt="Global Search" class="screenshot" src="{{docs_base_url}}/assets/img/articles/Enable Global Search .gif">

View File

@ -5,12 +5,24 @@ frappe.provide("erpnext.bom");
frappe.ui.form.on("BOM", { frappe.ui.form.on("BOM", {
setup: function(frm) { setup: function(frm) {
frm.add_fetch('buying_price_list', 'currency', 'currency'); frm.add_fetch('buying_price_list', 'currency', 'currency')
frm.fields_dict["items"].grid.get_field("bom_no").get_query = function(doc, cdt, cdn){
frm.set_query("bom_no", "items", function() {
return { return {
filters: {'currency': frm.doc.currency} filters: {
'currency': frm.doc.currency,
'company': frm.doc.company
}
} }
} });
frm.set_query("source_warehouse", "items", function() {
return {
filters: {
'company': frm.doc.company,
}
}
});
}, },
onload_post_render: function(frm) { onload_post_render: function(frm) {

View File

@ -408,6 +408,7 @@ class BOM(WebsiteGenerator):
self.add_to_cur_exploded_items(frappe._dict({ self.add_to_cur_exploded_items(frappe._dict({
'item_code' : d.item_code, 'item_code' : d.item_code,
'item_name' : d.item_name, 'item_name' : d.item_name,
'source_warehouse': d.source_warehouse,
'description' : d.description, 'description' : d.description,
'image' : d.image, 'image' : d.image,
'stock_uom' : d.stock_uom, 'stock_uom' : d.stock_uom,
@ -427,7 +428,8 @@ class BOM(WebsiteGenerator):
def get_child_exploded_items(self, bom_no, stock_qty): def get_child_exploded_items(self, bom_no, stock_qty):
""" Add all items from Flat BOM of child BOM""" """ Add all items from Flat BOM of child BOM"""
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name, bom_item.description, child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name,
bom_item.description, bom_item.source_warehouse,
bom_item.stock_uom, bom_item.stock_qty, bom_item.rate, bom_item.stock_uom, bom_item.stock_qty, bom_item.rate,
bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit
from `tabBOM Explosion Item` bom_item, tabBOM bom from `tabBOM Explosion Item` bom_item, tabBOM bom
@ -437,9 +439,10 @@ class BOM(WebsiteGenerator):
self.add_to_cur_exploded_items(frappe._dict({ self.add_to_cur_exploded_items(frappe._dict({
'item_code' : d['item_code'], 'item_code' : d['item_code'],
'item_name' : d['item_name'], 'item_name' : d['item_name'],
'source_warehouse' : d['source_warehouse'],
'description' : d['description'], 'description' : d['description'],
'stock_uom' : d['stock_uom'], 'stock_uom' : d['stock_uom'],
'stock_qty' : d['qty_consumed_per_unit']*stock_qty, 'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
'rate' : flt(d['rate']), 'rate' : flt(d['rate']),
})) }))
@ -493,6 +496,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
item.default_warehouse, item.default_warehouse,
item.expense_account as expense_account, item.expense_account as expense_account,
item.buying_cost_center as cost_center item.buying_cost_center as cost_center
{select_columns}
from from
`tab{table}` bom_item, `tabBOM` bom, `tabItem` item `tab{table}` bom_item, `tabBOM` bom, `tabItem` item
where where
@ -501,18 +505,20 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
and bom_item.parent = bom.name and bom_item.parent = bom.name
and item.name = bom_item.item_code and item.name = bom_item.item_code
and is_stock_item = 1 and is_stock_item = 1
{conditions} {where_conditions}
group by item_code, stock_uom""" group by item_code, stock_uom"""
if fetch_exploded: if fetch_exploded:
query = query.format(table="BOM Explosion Item", query = query.format(table="BOM Explosion Item",
conditions="""and item.is_sub_contracted_item = 0""") where_conditions="""and item.is_sub_contracted_item = 0""",
select_columns = ", bom_item.source_warehouse")
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True) items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
elif fetch_scrap_items: elif fetch_scrap_items:
query = query.format(table="BOM Scrap Item", conditions="") query = query.format(table="BOM Scrap Item", where_conditions="", select_columns="")
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True) items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
else: else:
query = query.format(table="BOM Item", conditions="") query = query.format(table="BOM Item", where_conditions="",
select_columns = ", bom_item.source_warehouse")
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True) items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
for item in items: for item in items:

View File

@ -8,7 +8,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 1.0, "stock_qty": 1.0,
"rate": 5000.0, "rate": 5000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
}, },
{ {
"amount": 2000.0, "amount": 2000.0,
@ -17,7 +18,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 2.0, "stock_qty": 2.0,
"rate": 1000.0, "rate": 1000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
} }
], ],
"docstatus": 1, "docstatus": 1,
@ -48,7 +50,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 1.0, "stock_qty": 1.0,
"rate": 5000.0, "rate": 5000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
}, },
{ {
"amount": 2000.0, "amount": 2000.0,
@ -57,7 +60,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 2.0, "stock_qty": 2.0,
"rate": 1000.0, "rate": 1000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
} }
], ],
"docstatus": 1, "docstatus": 1,
@ -86,7 +90,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 1.0, "stock_qty": 1.0,
"rate": 5000.0, "rate": 5000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
}, },
{ {
"amount": 2000.0, "amount": 2000.0,
@ -96,7 +101,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 3.0, "stock_qty": 3.0,
"rate": 1000.0, "rate": 1000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
} }
], ],
"docstatus": 1, "docstatus": 1,
@ -126,7 +132,8 @@
"parentfield": "items", "parentfield": "items",
"stock_qty": 2.0, "stock_qty": 2.0,
"rate": 3000.0, "rate": 3000.0,
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"source_warehouse": "_Test Warehouse - _TC"
} }
], ],
"docstatus": 1, "docstatus": 1,

View File

@ -7,9 +7,9 @@
"beta": 0, "beta": 0,
"creation": "2013-03-07 11:42:57", "creation": "2013-03-07 11:42:57",
"custom": 0, "custom": 0,
"default_print_format": "Standard",
"docstatus": 0, "docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
@ -104,6 +104,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "source_warehouse",
"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 Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"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_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -481,7 +512,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-02 19:29:34.498719", "modified": "2017-07-04 17:51:18.151002",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "BOM Explosion Item", "name": "BOM Explosion Item",

View File

@ -22,7 +22,7 @@
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 1,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
@ -113,7 +113,7 @@
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 1,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
@ -136,6 +136,37 @@
"unique": 0, "unique": 0,
"width": "150px" "width": "150px"
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "source_warehouse",
"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 Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -729,7 +760,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-05-23 15:59:37.946963", "modified": "2017-07-04 17:42:37.218408",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "BOM Item", "name": "BOM Item",

View File

@ -327,7 +327,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-05-23 16:04:32.442287", "modified": "2017-07-04 16:04:32.442287",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "BOM Scrap Item", "name": "BOM Scrap Item",

View File

@ -7,7 +7,72 @@ frappe.ui.form.on("Production Order", {
'Timesheet': 'Make Timesheet', 'Timesheet': 'Make Timesheet',
'Stock Entry': 'Make Stock Entry', 'Stock Entry': 'Make Stock Entry',
} }
// Set query for warehouses
frm.set_query("wip_warehouse", function(doc) {
return {
filters: {
'company': frm.doc.company,
}
}
});
frm.set_query("source_warehouse", "required_items", function() {
return {
filters: {
'company': frm.doc.company,
}
}
});
frm.set_query("fg_warehouse", function() {
return {
filters: {
'company': frm.doc.company,
'is_group': 0
}
}
});
frm.set_query("scrap_warehouse", function() {
return {
filters: {
'company': frm.doc.company,
'is_group': 0
}
}
});
// Set query for BOM
frm.set_query("bom_no", function() {
if (frm.doc.production_item) {
return{
query: "erpnext.controllers.queries.bom",
filters: {item: cstr(frm.doc.production_item)}
}
} else msgprint(__("Please enter Production Item first"));
});
// Set query for FG Item
frm.set_query("production_item", function() {
return {
query: "erpnext.controllers.queries.item_query",
filters:{
'is_stock_item': 1,
}
}
});
// Set query for FG Item
frm.set_query("project", function() {
return{
filters:[
['Project', 'status', 'not in', 'Completed, Cancelled']
]
}
});
}, },
onload: function(frm) { onload: function(frm) {
if (!frm.doc.status) if (!frm.doc.status)
frm.doc.status = 'Draft'; frm.doc.status = 'Draft';
@ -28,9 +93,8 @@ frappe.ui.form.on("Production Order", {
function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" }) function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" })
erpnext.production_order.set_custom_buttons(frm); erpnext.production_order.set_custom_buttons(frm);
erpnext.production_order.setup_company_filter(frm);
erpnext.production_order.setup_bom_filter(frm);
}, },
refresh: function(frm) { refresh: function(frm) {
erpnext.toggle_naming_series(); erpnext.toggle_naming_series();
erpnext.production_order.set_custom_buttons(frm); erpnext.production_order.set_custom_buttons(frm);
@ -53,6 +117,7 @@ frappe.ui.form.on("Production Order", {
}) })
} }
}, },
show_progress: function(frm) { show_progress: function(frm) {
var bars = []; var bars = [];
var message = ''; var message = '';
@ -85,10 +150,83 @@ frappe.ui.form.on("Production Order", {
} }
} }
frm.dashboard.add_progress(__('Status'), bars, message); frm.dashboard.add_progress(__('Status'), bars, message);
},
production_item: function(frm) {
frappe.call({
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
args: {
item: frm.doc.production_item,
project: frm.doc.project
},
callback: function(r) {
if(r.message) {
erpnext.in_production_item_onchange = true;
$.each(["description", "stock_uom", "project", "bom_no"], function(i, field) {
frm.set_value(field, r.message[field]);
});
if(r.message["set_scrap_wh_mandatory"]){
frm.toggle_reqd("scrap_warehouse", true);
}
erpnext.in_production_item_onchange = false;
}
}
});
},
project: function(frm) {
if(!erpnext.in_production_item_onchange) {
frm.trigger("production_item");
}
},
bom_no: function(frm) {
return frm.call({
doc: frm.doc,
method: "get_items_and_operations_from_bom",
callback: function(r) {
if(r.message["set_scrap_wh_mandatory"]){
frm.toggle_reqd("scrap_warehouse", true);
}
}
});
},
use_multi_level_bom: function(frm) {
if(frm.doc.bom_no) {
frm.trigger("bom_no");
}
},
qty: function(frm) {
frm.trigger('bom_no');
},
before_submit: function(frm) {
frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
} }
}); });
frappe.ui.form.on("Production Order Item", {
source_warehouse: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if(row.source_warehouse) {
frappe.call({
"method": "erpnext.stock.utils.get_latest_stock_qty",
args: {
item_code: row.item_code,
warehouse: row.source_warehouse
},
callback: function (r) {
frappe.model.set_value(row.doctype, row.name,
"available_qty_at_source_warehouse", r.message);
}
})
}
}
})
frappe.ui.form.on("Production Order Operation", { frappe.ui.form.on("Production Order Operation", {
workstation: function(frm, cdt, cdn) { workstation: function(frm, cdt, cdn) {
@ -119,38 +257,45 @@ erpnext.production_order = {
var doc = frm.doc; var doc = frm.doc;
if (doc.docstatus === 1) { if (doc.docstatus === 1) {
if (doc.status != 'Stopped' && doc.status != 'Completed') { if (doc.status != 'Stopped' && doc.status != 'Completed') {
frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Production Order'], __("Status")); frm.add_custom_button(__('Stop'), function() {
erpnext.production_order.stop_production_order(frm, "Stopped");
}, __("Status"));
} else if (doc.status == 'Stopped') { } else if (doc.status == 'Stopped') {
frm.add_custom_button(__('Re-open'), cur_frm.cscript['Unstop Production Order'], __("Status")); frm.add_custom_button(__('Re-open'), function() {
erpnext.production_order.stop_production_order(frm, "Resumed");
}, __("Status"));
} }
if(!frm.doc.skip_transfer){ if(!frm.doc.skip_transfer){
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) && frm.doc.status != 'Stopped') { if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty))
&& frm.doc.status != 'Stopped') {
frm.has_start_btn = true; frm.has_start_btn = true;
var btn = frm.add_custom_button(__('Start'), var start_btn = frm.add_custom_button(__('Start'), function() {
cur_frm.cscript['Transfer Raw Materials']); erpnext.production_order.make_se(frm, 'Material Transfer for Manufacture');
btn.addClass('btn-primary'); });
} start_btn.addClass('btn-primary');
}
} }
if(!frm.doc.skip_transfer){ if(!frm.doc.skip_transfer){
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing)) && frm.doc.status != 'Stopped') { if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))
&& frm.doc.status != 'Stopped') {
frm.has_finish_btn = true; frm.has_finish_btn = true;
var btn = frm.add_custom_button(__('Finish'), var finish_btn = frm.add_custom_button(__('Finish'), function() {
cur_frm.cscript['Update Finished Goods']); erpnext.production_order.make_se(frm, 'Manufacture');
});
if(doc.material_transferred_for_manufacturing==doc.qty) { if(doc.material_transferred_for_manufacturing==doc.qty) {
// all materials transferred for manufacturing, // all materials transferred for manufacturing, make this primary
// make this primary finish_btn.addClass('btn-primary');
btn.addClass('btn-primary');
} }
} }
} else { } else {
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') { if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
frm.has_finish_btn = true; frm.has_finish_btn = true;
var btn = frm.add_custom_button(__('Finish'), var finish_btn = frm.add_custom_button(__('Finish'),
cur_frm.cscript['Update Finished Goods']); cur_frm.cscript['Update Finished Goods']);
btn.addClass('btn-primary'); finish_btn.addClass('btn-primary');
} }
} }
} }
@ -162,8 +307,8 @@ erpnext.production_order = {
doc.planned_operating_cost = 0.0; doc.planned_operating_cost = 0.0;
for(var i=0;i<op.length;i++) { for(var i=0;i<op.length;i++) {
var planned_operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2); var planned_operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
frappe.model.set_value('Production Order Operation',op[i].name, "planned_operating_cost", planned_operating_cost); frappe.model.set_value('Production Order Operation', op[i].name,
"planned_operating_cost", planned_operating_cost);
doc.planned_operating_cost += planned_operating_cost; doc.planned_operating_cost += planned_operating_cost;
} }
refresh_field('planned_operating_cost'); refresh_field('planned_operating_cost');
@ -176,37 +321,10 @@ erpnext.production_order = {
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost)) frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
}, },
setup_company_filter: function(frm) {
var company_filter = function(doc) {
return {
filters: {
'company': frm.doc.company,
'is_group': 0
}
}
}
frm.fields_dict.source_warehouse.get_query = company_filter;
frm.fields_dict.fg_warehouse.get_query = company_filter;
frm.fields_dict.wip_warehouse.get_query = company_filter;
},
setup_bom_filter: function(frm) {
frm.set_query("bom_no", function(doc) {
if (doc.production_item) {
return{
query: "erpnext.controllers.queries.bom",
filters: {item: cstr(doc.production_item)}
}
} else frappe.msgprint(__("Please enter Production Item first"));
});
},
set_default_warehouse: function(frm) { set_default_warehouse: function(frm) {
if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) { if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) {
frappe.call({ frappe.call({
method: "erpnext.manufacturing.doctype.production_order.production_order.get_default_warehouse", method: "erpnext.manufacturing.doctype.production_order.production_order.get_default_warehouse",
callback: function(r) { callback: function(r) {
if(!r.exe) { if(!r.exe) {
frm.set_value("wip_warehouse", r.message.wip_warehouse); frm.set_value("wip_warehouse", r.message.wip_warehouse);
@ -215,45 +333,15 @@ erpnext.production_order = {
} }
}); });
} }
}
}
$.extend(cur_frm.cscript, {
before_submit: function() {
cur_frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
}, },
production_item: function(doc) { make_se: function(frm, purpose) {
frappe.call({ if(!frm.doc.skip_transfer){
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
args: {
item: doc.production_item,
project: doc.project
},
callback: function(r) {
$.each(["description", "stock_uom", "project", "bom_no"], function(i, field) {
cur_frm.set_value(field, r.message[field]);
});
if(r.message["set_scrap_wh_mandatory"]){
cur_frm.toggle_reqd("scrap_warehouse", true);
}
}
});
},
project: function(doc) {
cur_frm.cscript.production_item(doc)
},
make_se: function(purpose) {
var me = this;
if(!this.frm.doc.skip_transfer){
var max = (purpose === "Manufacture") ? var max = (purpose === "Manufacture") ?
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) : flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing); flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
} else { } else {
var max = flt(this.frm.doc.qty) - flt(this.frm.doc.produced_qty); var max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
} }
frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty", frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
@ -266,7 +354,7 @@ $.extend(cur_frm.cscript, {
frappe.call({ frappe.call({
method:"erpnext.manufacturing.doctype.production_order.production_order.make_stock_entry", method:"erpnext.manufacturing.doctype.production_order.production_order.make_stock_entry",
args: { args: {
"production_order_id": me.frm.doc.name, "production_order_id": frm.doc.name,
"purpose": purpose, "purpose": purpose,
"qty": data.qty "qty": data.qty
}, },
@ -277,59 +365,20 @@ $.extend(cur_frm.cscript, {
}); });
}, __("Select Quantity"), __("Make")); }, __("Select Quantity"), __("Make"));
}, },
bom_no: function() { stop_production_order: function(frm, status) {
return this.frm.call({ frappe.call({
doc: this.frm.doc, method: "erpnext.manufacturing.doctype.production_order.production_order.stop_unstop",
method: "set_production_order_operations", args: {
production_order: frm.doc.name,
status: status
},
callback: function(r) { callback: function(r) {
if(r.message["set_scrap_wh_mandatory"]){ if(r.message) {
cur_frm.toggle_reqd("scrap_warehouse", true); frm.set_value("status", r.message);
frm.reload_doc();
} }
} }
}); })
},
use_multi_level_bom: function() {
if(this.frm.doc.bom_no) {
this.frm.trigger("bom_no");
}
},
qty: function() {
frappe.ui.form.trigger("Production Order", 'bom_no')
},
});
cur_frm.cscript['Stop Production Order'] = function() {
$c_obj(cur_frm.doc, 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();});
}
cur_frm.cscript['Unstop Production Order'] = function() {
$c_obj(cur_frm.doc, 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
}
cur_frm.cscript['Transfer Raw Materials'] = function() {
cur_frm.cscript.make_se('Material Transfer for Manufacture');
}
cur_frm.cscript['Update Finished Goods'] = function() {
cur_frm.cscript.make_se('Manufacture');
}
cur_frm.fields_dict['production_item'].get_query = function(doc) {
return {
query: "erpnext.controllers.queries.item_query",
filters:{
'is_stock_item': 1,
}
}
}
cur_frm.fields_dict['project'].get_query = function(doc, dt, dn) {
return{
filters:[
['Project', 'status', 'not in', 'Completed, Cancelled']
]
} }
} }

View File

@ -95,7 +95,7 @@
"no_copy": 1, "no_copy": 1,
"oldfieldname": "status", "oldfieldname": "status",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nNot Started\nStopped\nUnstopped\nIn Process\nCompleted\nCancelled", "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
@ -139,38 +139,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "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,
"oldfieldname": "project",
"oldfieldtype": "Link",
"options": "Project",
"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_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -266,37 +234,6 @@
"unique": 0, "unique": 0,
"width": "50%" "width": "50%"
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "sales_order",
"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": "Sales Order",
"length": 0,
"no_copy": 0,
"options": "Sales Order",
"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_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -329,37 +266,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"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_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -427,6 +333,100 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "sales_order",
"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": "Sales Order",
"length": 0,
"no_copy": 0,
"options": "Sales Order",
"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_bulk_edit": 0,
"allow_on_submit": 0,
"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,
"oldfieldname": "project",
"oldfieldtype": "Link",
"options": "Project",
"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_bulk_edit": 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_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -457,38 +457,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "source_warehouse",
"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 Warehouse (for reserving Items)",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -519,34 +487,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -579,6 +519,34 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -616,7 +584,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "time", "fieldname": "required_items_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
@ -625,10 +593,9 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Time", "label": "Required Items",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "fa fa-time",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@ -647,9 +614,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "", "fieldname": "required_items",
"fieldname": "expected_delivery_date", "fieldtype": "Table",
"fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
@ -657,10 +623,43 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Expected Delivery Date", "label": "Required Items",
"length": 0,
"no_copy": 1,
"options": "Production Order Item",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "time",
"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": "Time",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "fa fa-time",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
@ -708,7 +707,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "planned_end_date", "fieldname": "actual_start_date",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
@ -717,9 +716,9 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Planned End Date", "label": "Actual Start Date",
"length": 0, "length": 0,
"no_copy": 1, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@ -767,7 +766,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "actual_start_date", "fieldname": "planned_end_date",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
@ -776,9 +775,9 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Actual Start Date", "label": "Planned End Date",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 1,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@ -821,6 +820,36 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "expected_delivery_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": "Expected Delivery Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -1070,67 +1099,6 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "required_items_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Required Items",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "required_items",
"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": "Required Items",
"length": 0,
"no_copy": 1,
"options": "Production Order Item",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,

View File

@ -3,24 +3,21 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
import json import json
from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
from frappe import _ from frappe import _
from frappe.utils import time_diff_in_seconds from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
from frappe.model.document import Document from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from erpnext.stock.doctype.item.item import validate_end_of_life from erpnext.stock.doctype.item.item import validate_end_of_life
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
from erpnext.projects.doctype.timesheet.timesheet import OverlapError from erpnext.projects.doctype.timesheet.timesheet import OverlapError
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
from erpnext.stock.utils import get_bin
from frappe.utils.csvutils import getlink from frappe.utils.csvutils import getlink
from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
from erpnext.utilities.transaction_base import validate_uom_is_integer
class OverProductionError(frappe.ValidationError): pass class OverProductionError(frappe.ValidationError): pass
class StockOverProductionError(frappe.ValidationError): pass class StockOverProductionError(frappe.ValidationError): pass
@ -38,15 +35,19 @@ class ProductionOrder(Document):
validate_bom_no(self.production_item, self.bom_no) validate_bom_no(self.production_item, self.bom_no)
self.validate_sales_order() self.validate_sales_order()
self.validate_warehouse() self.validate_warehouse_belongs_to_company()
self.calculate_operating_cost() self.calculate_operating_cost()
self.validate_qty() self.validate_qty()
self.validate_operation_time() self.validate_operation_time()
self.status = self.get_status() self.status = self.get_status()
from erpnext.utilities.transaction_base import validate_uom_is_integer
validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"]) validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
if not self.get("required_items"):
self.set_required_items()
else:
self.set_available_qty()
def validate_sales_order(self): def validate_sales_order(self):
if self.sales_order: if self.sales_order:
so = frappe.db.sql("""select name, delivery_date, project from `tabSales Order` so = frappe.db.sql("""select name, delivery_date, project from `tabSales Order`
@ -64,11 +65,14 @@ class ProductionOrder(Document):
else: else:
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order)) frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
def validate_warehouse(self): def validate_warehouse_belongs_to_company(self):
from erpnext.stock.utils import validate_warehouse_company warehouses = [self.fg_warehouse, self.wip_warehouse]
for d in self.get("required_items"):
if d.source_warehouse not in warehouses:
warehouses.append(d.source_warehouse)
for w in [self.source_warehouse, self.fg_warehouse, self.wip_warehouse]: for wh in warehouses:
validate_warehouse_company(w, self.company) validate_warehouse_company(wh, self.company)
def calculate_operating_cost(self): def calculate_operating_cost(self):
self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0 self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0
@ -79,7 +83,8 @@ class ProductionOrder(Document):
self.planned_operating_cost += flt(d.planned_operating_cost) self.planned_operating_cost += flt(d.planned_operating_cost)
self.actual_operating_cost += flt(d.actual_operating_cost) self.actual_operating_cost += flt(d.actual_operating_cost)
variable_cost = self.actual_operating_cost if self.actual_operating_cost else self.planned_operating_cost variable_cost = self.actual_operating_cost if self.actual_operating_cost \
else self.planned_operating_cost
self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost) self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
def validate_production_order_against_so(self): def validate_production_order_against_so(self):
@ -101,22 +106,16 @@ class ProductionOrder(Document):
# total qty in SO # total qty in SO
so_qty = flt(so_item_qty) + flt(dnpi_qty) so_qty = flt(so_item_qty) + flt(dnpi_qty)
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage")) allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
"over_production_allowance_percentage"))
if total_qty > so_qty + (allowance_percentage/100 * so_qty): if total_qty > so_qty + (allowance_percentage/100 * so_qty):
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item, frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}")
so_qty), OverProductionError) .format(self.production_item, so_qty), OverProductionError)
def stop_unstop(self, status):
""" Called from client side on Stop/Unstop event"""
status = self.update_status(status)
self.update_planned_qty()
frappe.msgprint(_("Production Order status is {0}").format(status))
self.notify_update()
def update_status(self, status=None): def update_status(self, status=None):
'''Update status of production order if unknown''' '''Update status of production order if unknown'''
if not status: if status != "Stopped":
status = self.get_status(status) status = self.get_status(status)
if status != self.status: if status != self.status:
@ -167,7 +166,6 @@ class ProductionOrder(Document):
self.db_set(fieldname, qty) self.db_set(fieldname, qty)
def before_submit(self): def before_submit(self):
self.set_required_items()
self.make_time_logs() self.make_time_logs()
def on_submit(self): def on_submit(self):
@ -184,10 +182,10 @@ class ProductionOrder(Document):
self.validate_cancel() self.validate_cancel()
frappe.db.set(self,'status', 'Cancelled') frappe.db.set(self,'status', 'Cancelled')
self.clear_required_items()
self.delete_timesheet() self.delete_timesheet()
self.update_completed_qty_in_material_request() self.update_completed_qty_in_material_request()
self.update_planned_qty() self.update_planned_qty()
self.update_reserved_qty_for_production()
def validate_cancel(self): def validate_cancel(self):
if self.status == "Stopped": if self.status == "Stopped":
@ -214,12 +212,11 @@ class ProductionOrder(Document):
def set_production_order_operations(self): def set_production_order_operations(self):
"""Fetch operations from BOM and set in 'Production Order'""" """Fetch operations from BOM and set in 'Production Order'"""
self.set('operations', [])
if not self.bom_no \ if not self.bom_no \
or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")): or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")):
return return
self.set('operations', [])
if self.use_multi_level_bom: if self.use_multi_level_bom:
bom_list = frappe.get_doc("BOM", self.bom_no).traverse_tree() bom_list = frappe.get_doc("BOM", self.bom_no).traverse_tree()
@ -240,8 +237,6 @@ class ProductionOrder(Document):
self.set('operations', operations) self.set('operations', operations)
self.calculate_time() self.calculate_time()
return check_if_scrap_warehouse_mandatory(self.bom_no)
def calculate_time(self): def calculate_time(self):
bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity") bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
@ -403,62 +398,60 @@ class ProductionOrder(Document):
update bin reserved_qty_for_production update bin reserved_qty_for_production
called from Stock Entry for production, after submit, cancel called from Stock Entry for production, after submit, cancel
''' '''
if self.docstatus==1 and self.source_warehouse: if self.docstatus==1:
if self.material_transferred_for_manufacturing == self.produced_qty: # calculate transferred qty based on submitted stock entries
# clear required items table and save document self.update_transaferred_qty_for_required_items()
self.clear_required_items()
else:
# calculate transferred qty based on submitted
# stock entries
self.update_transaferred_qty_for_required_items()
# update in bin # update in bin
self.update_reserved_qty_for_production() self.update_reserved_qty_for_production()
def clear_required_items(self):
'''Remove the required_items table and update the bins'''
items = [d.item_code for d in self.required_items]
self.required_items = []
self.update_child_table('required_items')
# completed, update reserved qty in bin
self.update_reserved_qty_for_production(items)
def update_reserved_qty_for_production(self, items=None): def update_reserved_qty_for_production(self, items=None):
'''update reserved_qty_for_production in bins''' '''update reserved_qty_for_production in bins'''
if not self.source_warehouse: for d in self.required_items:
return if d.source_warehouse:
stock_bin = get_bin(d.item_code, d.source_warehouse)
if not items: stock_bin.update_reserved_qty_for_production()
items = [d.item_code for d in self.required_items]
def get_items_and_operations_from_bom(self):
for item in items: self.set_required_items()
stock_bin = get_bin(item, self.source_warehouse) self.set_production_order_operations()
stock_bin.update_reserved_qty_for_production()
return check_if_scrap_warehouse_mandatory(self.bom_no)
def set_available_qty(self):
for d in self.get("required_items"):
if d.source_warehouse:
d.available_qty_at_source_warehouse = get_latest_stock_qty(d.item_code, d.source_warehouse)
if self.wip_warehouse:
d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse)
def set_required_items(self): def set_required_items(self):
'''set required_items for production to keep track of reserved qty''' '''set required_items for production to keep track of reserved qty'''
if self.source_warehouse: self.required_items = []
if self.bom_no and self.qty:
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty, item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty,
fetch_exploded = self.use_multi_level_bom) fetch_exploded = self.use_multi_level_bom)
for item in item_dict.values(): for item in item_dict.values():
self.append('required_items', {'item_code': item.item_code, self.append('required_items', {
'required_qty': item.qty}) 'item_code': item.item_code,
'required_qty': item.qty,
#print frappe.as_json(self.required_items) 'source_warehouse': item.source_warehouse or item.default_warehouse
})
self.set_available_qty()
def update_transaferred_qty_for_required_items(self): def update_transaferred_qty_for_required_items(self):
'''update transferred qty from submitted stock entries for that item against '''update transferred qty from submitted stock entries for that item against
the production order''' the production order'''
for d in self.required_items: for d in self.required_items:
transferred_qty = frappe.db.sql('''select count(qty) transferred_qty = frappe.db.sql('''select sum(qty)
from `tabStock Entry` entry, `tabStock Entry Detail` detail from `tabStock Entry` entry, `tabStock Entry Detail` detail
where where
entry.production_order = %s entry.production_order = %s
entry.purpose = "Material Transfer for Manufacture" and entry.purpose = "Material Transfer for Manufacture"
and entry.docstatus = 1 and entry.docstatus = 1
and detail.parent = entry.name and detail.parent = entry.name
and detail.item_code = %s''', (self.name, d.item_code))[0][0] and detail.item_code = %s''', (self.name, d.item_code))[0][0]
@ -496,10 +489,12 @@ def get_item_details(item, project = None):
if not res["bom_no"]: if not res["bom_no"]:
if project: if project:
frappe.throw(_("Default BOM for {0} not found for Project {1}").format(item, project)) res = get_item_details(item)
frappe.throw(_("Default BOM for {0} not found").format(item)) frappe.msgprint(_("Default BOM not found for Item {0} and Project {1}").format(item, project))
else:
frappe.throw(_("Default BOM for {0} not found").format(item))
res['project'] = frappe.db.get_value('BOM', res['bom_no'], 'project') res['project'] = project or frappe.db.get_value('BOM', res['bom_no'], 'project')
res.update(check_if_scrap_warehouse_mandatory(res["bom_no"])) res.update(check_if_scrap_warehouse_mandatory(res["bom_no"]))
return res return res
@ -507,16 +502,21 @@ def get_item_details(item, project = None):
@frappe.whitelist() @frappe.whitelist()
def check_if_scrap_warehouse_mandatory(bom_no): def check_if_scrap_warehouse_mandatory(bom_no):
res = {"set_scrap_wh_mandatory": False } res = {"set_scrap_wh_mandatory": False }
bom = frappe.get_doc("BOM", bom_no) if bom_no:
bom = frappe.get_doc("BOM", bom_no)
if len(bom.scrap_items) > 0: if len(bom.scrap_items) > 0:
res["set_scrap_wh_mandatory"] = True res["set_scrap_wh_mandatory"] = True
return res return res
@frappe.whitelist() @frappe.whitelist()
def make_stock_entry(production_order_id, purpose, qty=None): def make_stock_entry(production_order_id, purpose, qty=None):
production_order = frappe.get_doc("Production Order", production_order_id) production_order = frappe.get_doc("Production Order", production_order_id)
if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group"):
wip_warehouse = production_order.wip_warehouse
else:
wip_warehouse = None
stock_entry = frappe.new_doc("Stock Entry") stock_entry = frappe.new_doc("Stock Entry")
stock_entry.purpose = purpose stock_entry.purpose = purpose
@ -528,12 +528,10 @@ def make_stock_entry(production_order_id, purpose, qty=None):
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty)) stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
if purpose=="Material Transfer for Manufacture": if purpose=="Material Transfer for Manufacture":
if production_order.source_warehouse: stock_entry.to_warehouse = wip_warehouse
stock_entry.from_warehouse = production_order.source_warehouse
stock_entry.to_warehouse = production_order.wip_warehouse
stock_entry.project = production_order.project stock_entry.project = production_order.project
else: else:
stock_entry.from_warehouse = production_order.wip_warehouse stock_entry.from_warehouse = wip_warehouse
stock_entry.to_warehouse = production_order.fg_warehouse stock_entry.to_warehouse = production_order.fg_warehouse
additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty) additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
stock_entry.project = production_order.project stock_entry.project = production_order.project
@ -601,3 +599,18 @@ def make_new_timesheet(source_name, target_doc=None):
frappe.throw(_("Already completed")) frappe.throw(_("Already completed"))
return ts return ts
@frappe.whitelist()
def stop_unstop(production_order, status):
""" Called from client side on Stop/Unstop event"""
if not frappe.has_permission("Production Order", "write"):
frappe.throw(_("Not permitted"), frappe.PermissionError)
pro_order = frappe.get_doc("Production Order", production_order)
pro_order.update_status(status)
pro_order.update_planned_qty()
frappe.msgprint(_("Production Order has been {0}").format(status))
pro_order.notify_update()
return pro_order.status

View File

@ -8,7 +8,7 @@ import frappe
from frappe.utils import flt, time_diff_in_hours, now, add_days, cint from frappe.utils import flt, time_diff_in_hours, now, add_days, cint
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.manufacturing.doctype.production_order.production_order \ from erpnext.manufacturing.doctype.production_order.production_order \
import make_stock_entry, ItemHasVariantError import make_stock_entry, ItemHasVariantError, stop_unstop
from erpnext.stock.doctype.stock_entry import test_stock_entry from erpnext.stock.doctype.stock_entry import test_stock_entry
from erpnext.stock.doctype.item.test_item import get_total_projected_qty from erpnext.stock.doctype.item.test_item import get_total_projected_qty
from erpnext.stock.utils import get_bin from erpnext.stock.utils import get_bin
@ -228,10 +228,46 @@ class TestProductionOrder(unittest.TestCase):
cint(bin1_on_start_production.reserved_qty_for_production)) cint(bin1_on_start_production.reserved_qty_for_production))
self.assertEqual(cint(bin1_on_end_production.projected_qty), self.assertEqual(cint(bin1_on_end_production.projected_qty),
cint(bin1_on_end_production.projected_qty)) cint(bin1_on_end_production.projected_qty))
def test_reserved_qty_for_stopped_production(self):
test_stock_entry.make_stock_entry(item_code="_Test Item",
target= self.warehouse, qty=100, basic_rate=100)
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
target= self.warehouse, qty=100, basic_rate=100)
# required_items removed # 0 0 0
self.pro_order.reload()
self.assertEqual(len(self.pro_order.required_items), 0) self.test_reserved_qty_for_production_submit()
#2 0 -2
s = frappe.get_doc(make_stock_entry(self.pro_order.name,
"Material Transfer for Manufacture", 1))
s.submit()
#1 -1 0
bin1_on_start_production = get_bin(self.item, self.warehouse)
# reserved_qty_for_producion updated
self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production) + 1,
cint(bin1_on_start_production.reserved_qty_for_production))
# projected qty will now be 2 less (becuase of item movement)
self.assertEqual(cint(self.bin1_at_start.projected_qty),
cint(bin1_on_start_production.projected_qty) + 2)
# STOP
stop_unstop(self.pro_order.name, "Stopped")
bin1_on_stop_production = get_bin(self.item, self.warehouse)
# no change in reserved / projected
self.assertEqual(cint(bin1_on_stop_production.reserved_qty_for_production),
cint(self.bin1_at_start.reserved_qty_for_production))
self.assertEqual(cint(bin1_on_stop_production.projected_qty) + 1,
cint(self.bin1_at_start.projected_qty))
def test_scrap_material_qty(self): def test_scrap_material_qty(self):
prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2) prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2)
@ -286,10 +322,11 @@ def make_prod_order_test_record(**args):
pro_order.company = args.company or "_Test Company" pro_order.company = args.company or "_Test Company"
pro_order.stock_uom = args.stock_uom or "_Test UOM" pro_order.stock_uom = args.stock_uom or "_Test UOM"
pro_order.use_multi_level_bom=0 pro_order.use_multi_level_bom=0
pro_order.set_production_order_operations() pro_order.get_items_and_operations_from_bom()
if args.source_warehouse: if args.source_warehouse:
pro_order.source_warehouse = args.source_warehouse for item in pro_order.get("required_items"):
item.source_warehouse = args.source_warehouse
if args.planned_start_date: if args.planned_start_date:
pro_order.planned_start_date = args.planned_start_date pro_order.planned_start_date = args.planned_start_date

View File

@ -13,6 +13,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -43,6 +44,157 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "source_warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Source Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"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_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": "item_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": "Item Name",
"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": 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": "description",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"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": "qty_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Qty",
"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, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -72,6 +224,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -99,6 +252,95 @@
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "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_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "available_qty_at_source_warehouse",
"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": "Available Qty at Source Warehouse",
"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": 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": "available_qty_at_wip_warehouse",
"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": "Available Qty at WIP Warehouse",
"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": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@ -111,7 +353,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-03-28 14:18:36.342161", "modified": "2017-05-15 17:37:20.212361",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order Item", "name": "Production Order Item",

View File

@ -13,6 +13,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -42,6 +43,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -74,6 +76,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -85,7 +88,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 1, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "BOM", "label": "BOM",
"length": 0, "length": 0,
@ -104,6 +107,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -135,6 +139,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -163,6 +168,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -193,6 +199,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -224,6 +231,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -256,6 +264,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -285,6 +294,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -314,6 +324,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -343,6 +354,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -371,6 +383,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -403,6 +416,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -434,6 +448,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -464,6 +479,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -493,6 +509,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -522,6 +539,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -552,6 +570,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -580,6 +599,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -610,6 +630,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -651,7 +672,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-03-27 15:56:29.010336", "modified": "2017-05-29 18:02:04.252419",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order Operation", "name": "Production Order Operation",

View File

@ -410,4 +410,7 @@ erpnext.patches.v8_0.save_system_settings
erpnext.patches.v8_1.delete_deprecated_reports erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v8_1.setup_gst_india #2017-06-27 erpnext.patches.v8_1.setup_gst_india #2017-06-27
execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code') execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
erpnext.patches.v8_1.gst_fixes #2017-07-06
erpnext.patches.v8_0.update_production_orders
erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no

View File

@ -73,7 +73,7 @@ def validate_parent_account_for_warehouse(company=None):
if not company: if not company:
return return
if cint(erpnext.is_perpetual_inventory_enabled(company)): if cint(erpnext.is_perpetual_inventory_enabled(company.name)):
parent_account = frappe.db.sql("""select name from tabAccount parent_account = frappe.db.sql("""select name from tabAccount
where account_type='Stock' and company=%s and is_group=1 where account_type='Stock' and company=%s and is_group=1
and (warehouse is null or warehouse = '')""", company.name) and (warehouse is null or warehouse = '')""", company.name)

View File

@ -0,0 +1,44 @@
# 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():
# reload schema
for doctype in ("Production Order", "Production Order Item", "Production Order Operation",
"BOM Item", "BOM Explosion Item", "BOM"):
frappe.reload_doctype(doctype)
# fetch all draft and submitted production orders
fields = ["name"]
if "source_warehouse" in frappe.db.get_table_columns("Production Order"):
fields.append("source_warehouse")
pro_orders = frappe.get_all("Production Order", filters={"docstatus": ["!=", 2]}, fields=fields)
for p in pro_orders:
pro_order = frappe.get_doc("Production Order", p.name)
# set required items table
pro_order.set_required_items()
for item in pro_order.get("required_items"):
# set source warehouse based on parent
if not item.source_warehouse and "source_warehouse" in fields:
item.source_warehouse = pro_order.get("source_warehouse")
item.db_update()
if pro_order.docstatus == 1:
# update transferred qty based on Stock Entry, it also updates db
pro_order.update_transaferred_qty_for_required_items()
# Set status where it was 'Unstopped', as it is deprecated
if pro_order.status == "Unstopped":
status = pro_order.get_status()
pro_order.db_set("status", status)
elif pro_order.status == "Stopped":
pro_order.update_reserved_qty_for_production()

View File

@ -0,0 +1,58 @@
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from erpnext.regional.india.setup import update_address_template
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
update_existing_custom_fields()
add_custom_fields()
update_address_template()
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
def update_existing_custom_fields():
frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
where fieldname='gst_hsn_code' and label='GST HSN Code'
""")
frappe.db.sql("""update `tabCustom Field` set print_hide = 1
where fieldname in ('customer_gstin', 'supplier_gstin', 'company_gstin')
""")
frappe.db.sql("""update `tabCustom Field` set insert_after = 'address_display'
where fieldname in ('customer_gstin', 'supplier_gstin')
""")
frappe.db.sql("""update `tabCustom Field` set insert_after = 'company_address_display'
where fieldname = 'company_gstin'
""")
frappe.db.sql("""update `tabCustom Field` set insert_after = 'description'
where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
""")
def add_custom_fields():
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
custom_fields = {
'Address': [
dict(fieldname='gst_state_number', label='GST State Number',
fieldtype='Int', insert_after='gst_state'),
],
'Sales Invoice': [
dict(fieldname='invoice_copy', label='Invoice Copy',
fieldtype='Select', insert_after='project', print_hide=1,
options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'),
],
'Sales Order Item': [hsn_sac_field],
'Delivery Note Item': [hsn_sac_field],
'Purchase Order Item': [hsn_sac_field],
'Purchase Receipt Item': [hsn_sac_field]
}
for doctype, fields in custom_fields.items():
for df in fields:
create_custom_field(doctype, df)

View File

@ -0,0 +1,18 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype("Serial No")
frappe.db.sql("""
update
`tabSerial No`
set
sales_invoice = NULL
where
sales_invoice in (select return_against from
`tabSales Invoice` where docstatus =1 and is_return=1)
and sales_invoice is not null and sales_invoice !='' """)

View File

@ -215,7 +215,7 @@ if(!erpnext.taxes.flags[cur_frm.cscript.tax_table]) {
erpnext.taxes.set_conditional_mandatory_rate_or_amount(open_form); erpnext.taxes.set_conditional_mandatory_rate_or_amount(open_form);
} else { } else {
// apply in current row // apply in current row
erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.get_field('taxes').grid.get_grid_row(cdn)); erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.get_field('taxes').grid.get_row(cdn));
} }
}); });

View File

@ -634,5 +634,92 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
} }
this.calculate_outstanding_amount(false) this.calculate_outstanding_amount(false)
},
show_item_wise_taxes: function() {
if(this.frm.fields_dict.other_charges_calculation) {
this.frm.toggle_display("other_charges_calculation", this.frm.doc.other_charges_calculation);
}
},
set_item_wise_tax_breakup: function() {
if(this.frm.fields_dict.other_charges_calculation) {
var html = this.get_item_wise_taxes_html();
// console.log(html);
this.frm.set_value("other_charges_calculation", html);
this.show_item_wise_taxes();
}
},
get_item_wise_taxes_html: function() {
var item_tax = {};
var tax_accounts = [];
var company_currency = this.get_company_currency();
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
var tax_amount_precision = precision("tax_amount", tax);
var tax_rate_precision = precision("rate", tax);
$.each(JSON.parse(tax.item_wise_tax_detail || '{}'),
function(item_code, tax_data) {
if(!item_tax[item_code]) item_tax[item_code] = {};
if($.isArray(tax_data)) {
var tax_rate = "";
if(tax_data[0] != null) {
tax_rate = (tax.charge_type === "Actual") ?
format_currency(flt(tax_data[0], tax_amount_precision),
company_currency, tax_amount_precision) :
(flt(tax_data[0], tax_rate_precision) + "%");
}
var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision),
company_currency, tax_amount_precision);
item_tax[item_code][tax.name] = [tax_rate, tax_amount];
} else {
item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", ""];
}
});
tax_accounts.push([tax.name, tax.account_head]);
});
var headings = $.map([__("Item Name"), __("Taxable Amount")].concat($.map(tax_accounts,
function(head) { return head[1]; })), function(head) {
if(head==__("Item Name")) {
return '<th style="min-width: 100px;" class="text-left">' + (head || "") + "</th>";
} else {
return '<th style="min-width: 80px;" class="text-right">' + (head || "") + "</th>";
}
}
).join("\n");
var distinct_item_names = [];
var distinct_items = [];
$.each(this.frm.doc["items"] || [], function(i, item) {
if(distinct_item_names.indexOf(item.item_code || item.item_name)===-1) {
distinct_item_names.push(item.item_code || item.item_name);
distinct_items.push(item);
}
});
var rows = $.map(distinct_items, function(item) {
var item_tax_record = item_tax[item.item_code || item.item_name];
if(!item_tax_record) { return null; }
return repl("<tr><td>%(item_name)s</td><td class='text-right'>%(taxable_amount)s</td>%(taxes)s</tr>", {
item_name: item.item_name,
taxable_amount: format_currency(item.net_amount,
company_currency, precision("net_amount", item)),
taxes: $.map(tax_accounts, function(head) {
return item_tax_record[head[0]] ?
"<td class='text-right'>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
"<td></td>";
}).join("\n")
});
}).join("\n");
if(!rows) return "";
return '<div class="tax-break-up" style="overflow-x: auto;">\
<table class="table table-bordered table-hover">\
<thead><tr>' + headings + '</tr></thead> \
<tbody>' + rows + '</tbody> \
</table></div>';
} }
}) })

View File

@ -374,6 +374,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
validate: function() { validate: function() {
this.calculate_taxes_and_totals(false); this.calculate_taxes_and_totals(false);
this.set_item_wise_tax_breakup();
}, },
company: function() { company: function() {
@ -936,69 +937,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}); });
}, },
get_item_wise_taxes_html: function() {
var item_tax = {};
var tax_accounts = [];
var company_currency = this.get_company_currency();
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
var tax_amount_precision = precision("tax_amount", tax);
var tax_rate_precision = precision("rate", tax);
$.each(JSON.parse(tax.item_wise_tax_detail || '{}'),
function(item_code, tax_data) {
if(!item_tax[item_code]) item_tax[item_code] = {};
if($.isArray(tax_data)) {
var tax_rate = "";
if(tax_data[0] != null) {
tax_rate = (tax.charge_type === "Actual") ?
format_currency(flt(tax_data[0], tax_amount_precision), company_currency, tax_amount_precision) :
(flt(tax_data[0], tax_rate_precision) + "%");
}
var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision), company_currency,
tax_amount_precision);
item_tax[item_code][tax.name] = [tax_rate, tax_amount];
} else {
item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", ""];
}
});
tax_accounts.push([tax.name, tax.account_head]);
});
var headings = $.map([__("Item Name")].concat($.map(tax_accounts, function(head) { return head[1]; })),
function(head) { return '<th style="min-width: 100px;">' + (head || "") + "</th>" }).join("\n");
var distinct_item_names = [];
var distinct_items = [];
$.each(this.frm.doc["items"] || [], function(i, item) {
if(distinct_item_names.indexOf(item.item_code || item.item_name)===-1) {
distinct_item_names.push(item.item_code || item.item_name);
distinct_items.push(item);
}
});
var rows = $.map(distinct_items, function(item) {
var item_tax_record = item_tax[item.item_code || item.item_name];
if(!item_tax_record) { return null; }
return repl("<tr><td>%(item_name)s</td>%(taxes)s</tr>", {
item_name: item.item_name,
taxes: $.map(tax_accounts, function(head) {
return item_tax_record[head[0]] ?
"<td>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
"<td></td>";
}).join("\n")
});
}).join("\n");
if(!rows) return "";
return '<p><a class="h6 text-muted" href="#" onclick="$(\'.tax-break-up\').toggleClass(\'hide\'); return false;">'
+ __("Show tax break-up") + '</a></p>\
<div class="tax-break-up hide" style="overflow-x: auto;"><table class="table table-bordered table-hover">\
<thead><tr>' + headings + '</tr></thead> \
<tbody>' + rows + '</tbody> \
</table></div>';
},
validate_company_and_party: function() { validate_company_and_party: function() {
var me = this; var me = this;
var valid = true; var valid = true;
@ -1046,18 +984,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} }
}, },
show_item_wise_taxes: function() {
if(this.frm.fields_dict.other_charges_calculation) {
var html = this.get_item_wise_taxes_html();
if (html) {
this.frm.toggle_display("other_charges_calculation", true);
$(this.frm.fields_dict.other_charges_calculation.wrapper).html(html);
} else {
this.frm.toggle_display("other_charges_calculation", false);
}
}
},
is_recurring: function() { is_recurring: function() {
// set default values for recurring documents // set default values for recurring documents
if(this.frm.doc.is_recurring && this.frm.doc.__islocal) { if(this.frm.doc.is_recurring && this.frm.doc.__islocal) {

View File

@ -1,4 +1,4 @@
frappe.provide("erpnext.wiz"); frappe.provide("erpnext.setup");
frappe.pages['setup-wizard'].on_page_load = function(wrapper) { frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
if(frappe.sys_defaults.company) { if(frappe.sys_defaults.company) {
@ -7,459 +7,398 @@ frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
} }
}; };
function load_erpnext_slides() { var erpnext_slides = [
$.extend(erpnext.wiz, { {
select_domain: { // Domain
domains: ["all"], name: 'domain',
title: __('Select your Domain'), domains: ["all"],
fields: [ title: __('Select your Domain'),
{fieldname:'domain', label: __('Domain'), fieldtype:'Select', fields: [
options: [ {
{"label": __("Distribution"), "value": "Distribution"}, fieldname: 'domain', label: __('Domain'), fieldtype: 'Select',
{"label": __("Education"), "value": "Education"}, options: [
{"label": __("Manufacturing"), "value": "Manufacturing"}, { "label": __("Distribution"), "value": "Distribution" },
{"label": __("Retail"), "value": "Retail"}, { "label": __("Education"), "value": "Education" },
{"label": __("Services"), "value": "Services"} { "label": __("Manufacturing"), "value": "Manufacturing" },
], reqd:1}, { "label": __("Retail"), "value": "Retail" },
], { "label": __("Services"), "value": "Services" }
help: __('Select the nature of your business.'), ], reqd: 1
onload: function(slide) {
slide.get_input("domain").on("change", function() {
frappe.wiz.domain = $(this).val();
frappe.wizard.refresh_slides();
});
}, },
css_class: "single-column" ],
help: __('Select the nature of your business.'),
onload: function (slide) {
slide.get_input("domain").on("change", function () {
frappe.setup.domain = $(this).val();
frappe.wizard.refresh_slides();
});
}, },
org: { },
domains: ["all"],
title: __("The Organization"),
icon: "fa fa-building",
fields: [
{fieldname:'company_name',
label: frappe.wiz.domain==='Education' ?
__('Institute Name') : __('Company Name'),
fieldtype:'Data', reqd:1},
{fieldname:'company_abbr',
label: frappe.wiz.domain==='Education' ?
__('Institute Abbreviation') : __('Company Abbreviation'),
fieldtype:'Data'},
{fieldname:'company_tagline',
label: __('What does it do?'),
fieldtype:'Data',
placeholder: frappe.wiz.domain==='Education' ?
__('e.g. "Primary School" or "University"') :
__('e.g. "Build tools for builders"'),
reqd:1},
{fieldname:'bank_account', label: __('Bank Name'), fieldtype:'Data', reqd:1},
{fieldname:'chart_of_accounts', label: __('Chart of Accounts'),
options: "", fieldtype: 'Select'},
// TODO remove this {
{fieldtype: "Section Break"}, // Brand
{fieldname:'fy_start_date', label:__('Financial Year Start Date'), fieldtype:'Date', name: 'brand',
description: __('Your financial year begins on'), reqd:1}, domains: ["all"],
{fieldname:'fy_end_date', label:__('Financial Year End Date'), fieldtype:'Date', icon: "fa fa-bookmark",
description: __('Your financial year ends on'), reqd:1}, title: __("The Brand"),
], help: __('Upload your letter head and logo. (you can edit them later).'),
help: (frappe.wiz.domain==='Education' ? fields: [
__('The name of the institute for which you are setting up this system.'): {
__('The name of your company for which you are setting up this system.')), fieldtype: "Attach Image", fieldname: "attach_logo",
label: __("Attach Logo"),
description: __("100px by 100px"),
is_private: 0
},
{
fieldname: 'company_name',
label: frappe.setup.domain === 'Education' ?
__('Institute Name') : __('Company Name'),
fieldtype: 'Data', reqd: 1
},
{
fieldname: 'company_abbr',
label: frappe.setup.domain === 'Education' ?
__('Institute Abbreviation') : __('Company Abbreviation'),
fieldtype: 'Data'
}
],
onload: function(slide) {
this.bind_events(slide);
},
bind_events: function (slide) {
slide.get_input("company_name").on("change", function () {
var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join("");
slide.get_field("company_abbr").set_input(abbr.slice(0, 5).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
onload: function(slide) { slide.get_input("company_abbr").on("change", function () {
erpnext.wiz.org.load_chart_of_accounts(slide); if (slide.get_input("company_abbr").val().length > 5) {
erpnext.wiz.org.bind_events(slide); frappe.msgprint("Company Abbreviation cannot have more than 5 characters");
erpnext.wiz.org.set_fy_dates(slide); slide.get_field("company_abbr").set_input("");
}
});
}
},
{
// Organisation
name: 'organisation',
domains: ["all"],
title: __("Your Organization"),
icon: "fa fa-building",
help: (frappe.setup.domain === 'Education' ?
__('The name of the institute for which you are setting up this system.') :
__('The name of your company for which you are setting up this system.')),
fields: [
{
fieldname: 'company_tagline',
label: __('What does it do?'),
fieldtype: 'Data',
placeholder: frappe.setup.domain === 'Education' ?
__('e.g. "Primary School" or "University"') :
__('e.g. "Build tools for builders"'),
reqd: 1
},
{ fieldname: 'bank_account', label: __('Bank Name'), fieldtype: 'Data', reqd: 1 },
{
fieldname: 'chart_of_accounts', label: __('Chart of Accounts'),
options: "", fieldtype: 'Select'
}, },
validate: function() { { fieldtype: "Section Break", label: "Financial Year" },
// validate fiscal year start and end dates { fieldname: 'fy_start_date', label: __('Start Date'), fieldtype: 'Date', reqd: 1 },
if (this.values.fy_start_date=='Invalid date' || this.values.fy_end_date=='Invalid date') { { fieldtype: "Column Break" },
frappe.msgprint(__("Please enter valid Financial Year Start and End Dates")); { fieldname: 'fy_end_date', label: __('End Date'), fieldtype: 'Date', reqd: 1 },
return false; ],
onload: function (slide) {
this.load_chart_of_accounts(slide);
this.bind_events(slide);
this.set_fy_dates(slide);
},
validate: function () {
// validate fiscal year start and end dates
if (this.values.fy_start_date == 'Invalid date' || this.values.fy_end_date == 'Invalid date') {
frappe.msgprint(__("Please enter valid Financial Year Start and End Dates"));
return false;
}
if ((this.values.company_name || "").toLowerCase() == "company") {
frappe.msgprint(__("Company Name cannot be Company"));
return false;
}
return true;
},
set_fy_dates: function (slide) {
var country = frappe.wizard.values.country;
if (country) {
var fy = erpnext.setup.fiscal_years[country];
var current_year = moment(new Date()).year();
var next_year = current_year + 1;
if (!fy) {
fy = ["01-01", "12-31"];
next_year = current_year;
} }
if ((this.values.company_name || "").toLowerCase() == "company") { var year_start_date = current_year + "-" + fy[0];
frappe.msgprint(__("Company Name cannot be Company")); if (year_start_date > frappe.datetime.get_today()) {
return false; next_year = current_year;
current_year -= 1;
} }
slide.get_field("fy_start_date").set_value(current_year + '-' + fy[0]);
slide.get_field("fy_end_date").set_value(next_year + '-' + fy[1]);
}
return true; },
},
css_class: "single-column",
set_fy_dates: function(slide) { load_chart_of_accounts: function (slide) {
var country = frappe.wizard.values.country; var country = frappe.wizard.values.country;
if(country) { if (country) {
var fy = erpnext.wiz.fiscal_years[country]; frappe.call({
var current_year = moment(new Date()).year(); method: "erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts.get_charts_for_country",
var next_year = current_year + 1; args: { "country": country },
if(!fy) { callback: function (r) {
fy = ["01-01", "12-31"]; if (r.message) {
next_year = current_year; slide.get_input("chart_of_accounts").empty()
} .add_options(r.message);
var year_start_date = current_year + "-" + fy[0];
if(year_start_date > frappe.datetime.get_today()) {
next_year = current_year
current_year -= 1;
}
slide.get_field("fy_start_date").set_input(current_year + "-" + fy[0]);
slide.get_field("fy_end_date").set_input(next_year + "-" + fy[1]);
}
}, if (r.message.length === 1) {
var field = slide.get_field("chart_of_accounts");
load_chart_of_accounts: function(slide) { field.set_value(r.message[0]);
var country = frappe.wizard.values.country; field.df.hidden = 1;
field.refresh();
if(country) {
frappe.call({
method: "erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts.get_charts_for_country",
args: {"country": country},
callback: function(r) {
if(r.message) {
slide.get_input("chart_of_accounts").empty()
.add_options(r.message);
if (r.message.length===1) {
var field = slide.get_field("chart_of_accounts");
field.set_value(r.message[0]);
field.df.hidden = 1;
field.refresh();
}
} }
} }
})
}
},
bind_events: function(slide) {
slide.get_input("company_name").on("change", function() {
var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join("");
slide.get_field("company_abbr").set_input(abbr.slice(0, 5).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
slide.get_input("company_abbr").on("change", function() {
if(slide.get_input("company_abbr").val().length > 5) {
frappe.msgprint("Company Abbreviation cannot have more than 5 characters");
slide.get_field("company_abbr").set_input("");
} }
}); })
// TODO remove this
slide.get_input("fy_start_date").on("change", function() {
var year_end_date =
frappe.datetime.add_days(frappe.datetime.add_months(
frappe.datetime.user_to_obj(slide.get_input("fy_start_date").val()), 12), -1);
slide.get_input("fy_end_date").val(frappe.datetime.obj_to_user(year_end_date));
});
} }
}, },
branding: { bind_events: function (slide) {
domains: ["all"], slide.get_input("fy_start_date").on("change", function () {
icon: "fa fa-bookmark", var start_date = slide.form.fields_dict.fy_start_date.get_value();
title: __("The Brand"), var year_end_date =
help: __('Upload your letter head and logo. (you can edit them later).'), frappe.datetime.add_days(frappe.datetime.add_months(start_date, 12), -1);
fields: [ slide.form.fields_dict.fy_end_date.set_value(year_end_date);
{fieldtype:"Attach Image", fieldname:"attach_letterhead", });
label: __("Attach Letterhead"), }
description: __("Keep it web friendly 900px (w) by 100px (h)"), },
is_private: 0
},
{fieldtype: "Column Break"},
{fieldtype:"Attach Image", fieldname:"attach_logo",
label:__("Attach Logo"),
description: __("100px by 100px"),
is_private: 0
},
],
css_class: "two-column"
},
users: {
domains: ["all"],
icon: "fa fa-money",
title: __("Add Users"),
help: __("Add users to your organization, other than yourself"),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<5; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"user_fullname_"+ i,
label:__("Full Name")},
{fieldtype:"Data", fieldname:"user_email_" + i,
label:__("Email Address"), placeholder:__("user@example.com"),
options: "Email"},
{fieldtype:"Column Break"},
{fieldtype: "Check", fieldname: "user_sales_" + i,
label:__("Sales"), "default": 1,
hidden: frappe.wiz.domain==='Education' ? 1 : 0},
{fieldtype: "Check", fieldname: "user_purchaser_" + i,
label:__("Purchaser"), "default": 1,
hidden: frappe.wiz.domain==='Education' ? 1 : 0},
{fieldtype: "Check", fieldname: "user_accountant_" + i,
label:__("Accountant"), "default": 1,
hidden: frappe.wiz.domain==='Education' ? 1 : 0},
]);
}
},
css_class: "two-column"
},
taxes: {
domains: ['manufacturing', 'services', 'retail', 'distribution'],
icon: "fa fa-money",
title: __("Add Taxes"),
help: __("List your tax heads (e.g. VAT, Customs etc; they should have unique names) and their standard rates. This will create a standard template, which you can edit and add more later."),
"fields": [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<4; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"tax_"+ i, label:__("Tax") + " " + i,
placeholder:__("e.g. VAT") + " " + i},
{fieldtype:"Column Break"},
{fieldtype:"Float", fieldname:"tax_rate_" + i, label:__("Rate (%)"), placeholder:__("e.g. 5")},
]);
}
},
css_class: "two-column"
},
customers: {
domains: ['manufacturing', 'services', 'retail', 'distribution'],
icon: "fa fa-group",
title: __("Your Customers"),
help: __("List a few of your customers. They could be organizations or individuals."),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<6; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"customer_" + i, label:__("Customer") + " " + i,
placeholder:__("Customer Name")},
{fieldtype:"Column Break"},
{fieldtype:"Data", fieldname:"customer_contact_" + i,
label:__("Contact Name") + " " + i, placeholder:__("Contact Name")}
])
}
slide.fields[1].reqd = 1;
},
css_class: "two-column"
},
suppliers: {
domains: ['manufacturing', 'services', 'retail', 'distribution'],
icon: "fa fa-group",
title: __("Your Suppliers"),
help: __("List a few of your suppliers. They could be organizations or individuals."),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<6; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"supplier_" + i, label:__("Supplier")+" " + i,
placeholder:__("Supplier Name")},
{fieldtype:"Column Break"},
{fieldtype:"Data", fieldname:"supplier_contact_" + i,
label:__("Contact Name") + " " + i, placeholder:__("Contact Name")},
])
}
slide.fields[1].reqd = 1;
},
css_class: "two-column"
},
items: {
domains: ['manufacturing', 'services', 'retail', 'distribution'],
icon: "fa fa-barcode",
title: __("Your Products or Services"),
help: __("List your products or services that you buy or sell. Make sure to check the Item Group, Unit of Measure and other properties when you start."),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<6; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"item_" + i, label:__("Item") + " " + i,
placeholder:__("A Product or Service")},
{fieldtype:"Select", label:__("Group"), fieldname:"item_group_" + i,
options:[__("Products"), __("Services"),
__("Raw Material"), __("Consumable"), __("Sub Assemblies")],
"default": __("Products")},
{fieldtype:"Select", fieldname:"item_uom_" + i, label:__("UOM"),
options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"),
__("Hour"), __("Minute"), __("Litre"), __("Meter"), __("Gram")],
"default": __("Unit")},
{fieldtype: "Check", fieldname: "is_sales_item_" + i, label:__("We sell this Item"), default: 1},
{fieldtype: "Check", fieldname: "is_purchase_item_" + i, label:__("We buy this Item")},
{fieldtype:"Column Break"},
{fieldtype:"Currency", fieldname:"item_price_" + i, label:__("Rate")},
{fieldtype:"Attach Image", fieldname:"item_img_" + i, label:__("Attach Image"), is_private: 0},
])
}
slide.fields[1].reqd = 1;
// dummy data
slide.fields.push({fieldtype: "Section Break"});
slide.fields.push({fieldtype: "Check", fieldname: "add_sample_data",
label: __("Add a few sample records"), "default": 1});
slide.fields.push({fieldtype: "Check", fieldname: "setup_website",
label: __("Setup a simple website for my organization"), "default": 1});
},
css_class: "two-column"
},
program: {
domains: ["education"],
title: __("Program"),
help: __("Example: Masters in Computer Science"),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<6; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"program_" + i, label:__("Program") + " " + i, placeholder: __("Program Name")},
])
}
slide.fields[1].reqd = 1;
},
css_class: "single-column"
},
course: {
domains: ["education"],
title: __("Course"),
help: __("Example: Basic Mathematics"),
fields: [],
before_load: function(slide) {
slide.fields = [];
for(var i=1; i<6; i++) {
slide.fields = slide.fields.concat([
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"course_" + i, label:__("Course") + " " + i, placeholder: __("Course Name")},
])
}
slide.fields[1].reqd = 1;
},
css_class: "single-column"
},
instructor: { {
domains: ["education"], // Taxes
title: __("Instructor"), name: 'taxes',
help: __("People who teach at your organisation"), domains: ['manufacturing', 'services', 'retail', 'distribution'],
fields: [], icon: "fa fa-money",
before_load: function(slide) { title: __("Add Taxes"),
slide.fields = []; help: __("List your tax heads (e.g. VAT, Customs etc; they should have unique names) and their standard rates. This will create a standard template, which you can edit and add more later."),
for(var i=1; i<6; i++) { add_more: 1,
slide.fields = slide.fields.concat([ max_count: 4,
{fieldtype:"Section Break", show_section_border: true}, fields: [
{fieldtype:"Data", fieldname:"instructor_" + i, label:__("Instructor") + " " + i, placeholder: __("Instructor Name")}, {fieldtype:"Section Break"},
]) {fieldtype:"Data", fieldname:"tax", label:__("Tax"),
} placeholder:__("e.g. VAT")},
slide.fields[1].reqd = 1; {fieldtype:"Column Break"},
}, {fieldtype:"Float", fieldname:"tax_rate", label:__("Rate (%)"), placeholder:__("e.g. 5")}
css_class: "single-column" ]
}, },
room: { {
domains: ["education"], // Customers
title: __("Room"), name: 'customers',
help: __("Classrooms/ Laboratories etc where lectures can be scheduled."), domains: ['manufacturing', 'services', 'retail', 'distribution'],
fields: [], icon: "fa fa-group",
before_load: function(slide) { title: __("Add Customers"),
slide.fields = []; help: __("List a few of your customers. They could be organizations or individuals."),
for(var i=1; i<4; i++) { add_more: 1,
slide.fields = slide.fields.concat([ max_count: 6,
{fieldtype:"Section Break", show_section_border: true}, fields: [
{fieldtype:"Data", fieldname:"room_" + i, label:__("Room") + " " + i}, {fieldtype:"Section Break"},
{fieldtype:"Column Break"}, {fieldtype:"Data", fieldname:"customer", label:__("Customer"),
{fieldtype:"Int", fieldname:"room_capacity_" + i, label:__("Room") + " " + i + " Capacity"}, placeholder:__("Customer Name")},
]) {fieldtype:"Column Break"},
} {fieldtype:"Data", fieldname:"customer_contact",
slide.fields[1].reqd = 1; label:__("Contact Name"), placeholder:__("Contact Name")}
}, ],
css_class: "two-column" },
},
});
// Source: https://en.wikipedia.org/wiki/Fiscal_year {
// default 1st Jan - 31st Dec // Suppliers
name: 'suppliers',
domains: ['manufacturing', 'services', 'retail', 'distribution'],
icon: "fa fa-group",
title: __("Your Suppliers"),
help: __("List a few of your suppliers. They could be organizations or individuals."),
add_more: 1,
max_count: 6,
fields: [
{fieldtype:"Section Break"},
{fieldtype:"Data", fieldname:"supplier", label:__("Supplier"),
placeholder:__("Supplier Name")},
{fieldtype:"Column Break"},
{fieldtype:"Data", fieldname:"supplier_contact",
label:__("Contact Name"), placeholder:__("Contact Name")},
]
},
erpnext.wiz.fiscal_years = { {
"Afghanistan": ["12-20", "12-21"], // Products
"Australia": ["07-01", "06-30"], name: 'products',
"Bangladesh": ["07-01", "06-30"], domains: ['manufacturing', 'services', 'retail', 'distribution'],
"Canada": ["04-01", "03-31"], icon: "fa fa-barcode",
"Costa Rica": ["10-01", "09-30"], title: __("Your Products or Services"),
"Egypt": ["07-01", "06-30"], help: __("List your products or services that you buy or sell. Make sure to check the Item Group, Unit of Measure and other properties when you start."),
"Hong Kong": ["04-01", "03-31"], add_more: 1,
"India": ["04-01", "03-31"], max_count: 6,
"Iran": ["06-23", "06-22"], fields: [
"Italy": ["07-01", "06-30"], {fieldtype:"Section Break", show_section_border: true},
"Myanmar": ["04-01", "03-31"], {fieldtype:"Data", fieldname:"item", label:__("Item"),
"New Zealand": ["04-01", "03-31"], placeholder:__("A Product or Service")},
"Pakistan": ["07-01", "06-30"], {fieldtype:"Select", label:__("Group"), fieldname:"item_group",
"Singapore": ["04-01", "03-31"], options:[__("Products"), __("Services"),
"South Africa": ["03-01", "02-28"], __("Raw Material"), __("Consumable"), __("Sub Assemblies")],
"Thailand": ["10-01", "09-30"], "default": __("Products")},
"United Kingdom": ["04-01", "03-31"], {fieldtype:"Select", fieldname:"item_uom", label:__("UOM"),
}; options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"),
} __("Hour"), __("Minute"), __("Litre"), __("Meter"), __("Gram")],
"default": __("Unit")},
{fieldtype: "Check", fieldname: "is_sales_item", label:__("We sell this Item"), default: 1},
{fieldtype: "Check", fieldname: "is_purchase_item", label:__("We buy this Item")},
{fieldtype:"Column Break"},
{fieldtype:"Currency", fieldname:"item_price", label:__("Rate")},
{fieldtype:"Attach Image", fieldname:"item_img", label:__("Attach Image"), is_private: 0},
],
get_item_count: function() {
return this.item_count;
}
},
frappe.wiz.on("before_load", function() { {
load_erpnext_slides(); // Program
name: 'program',
domains: ["education"],
title: __("Program"),
help: __("Example: Masters in Computer Science"),
add_more: 1,
max_count: 6,
fields: [
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"program", label:__("Program"), placeholder: __("Program Name")},
],
},
frappe.wiz.add_slide(erpnext.wiz.select_domain); {
frappe.wiz.add_slide(erpnext.wiz.org); // Course
frappe.wiz.add_slide(erpnext.wiz.branding); name: 'course',
domains: ["education"],
title: __("Course"),
help: __("Example: Basic Mathematics"),
add_more: 1,
max_count: 6,
fields: [
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"course", label:__("Course"), placeholder: __("Course Name")},
]
},
if (!(frappe.boot.limits && frappe.boot.limits.users===1)) { {
frappe.wiz.add_slide(erpnext.wiz.users); // Instructor
name: 'instructor',
domains: ["education"],
title: __("Instructor"),
help: __("People who teach at your organisation"),
add_more: 1,
max_count: 6,
fields: [
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"instructor", label:__("Instructor"), placeholder: __("Instructor Name")},
]
},
{
// Room
name: 'room',
domains: ["education"],
title: __("Room"),
help: __("Classrooms/ Laboratories etc where lectures can be scheduled."),
add_more: 1,
max_count: 4,
fields: [
{fieldtype:"Section Break", show_section_border: true},
{fieldtype:"Data", fieldname:"room", label:__("Room")},
{fieldtype:"Column Break"},
{fieldtype:"Int", fieldname:"room_capacity", label:__("Room") + " Capacity"},
]
},
{
// last slide: Bootstrap
name: 'bootstrap',
domains: ["all"],
title: __("Bootstrap"),
fields: [{fieldtype: "Section Break"},
{fieldtype: "Check", fieldname: "add_sample_data",
label: __("Add a few sample records"), "default": 1},
{fieldtype: "Check", fieldname: "setup_website",
label: __("Setup a simple website for my organization"), "default": 1}
]
} }
];
frappe.wiz.add_slide(erpnext.wiz.taxes); // Source: https://en.wikipedia.org/wiki/Fiscal_year
frappe.wiz.add_slide(erpnext.wiz.customers); // default 1st Jan - 31st Dec
frappe.wiz.add_slide(erpnext.wiz.suppliers);
frappe.wiz.add_slide(erpnext.wiz.items);
frappe.wiz.add_slide(erpnext.wiz.program);
frappe.wiz.add_slide(erpnext.wiz.course);
frappe.wiz.add_slide(erpnext.wiz.instructor);
frappe.wiz.add_slide(erpnext.wiz.room);
if(frappe.wizard && frappe.wizard.domain && frappe.wizard.domain !== 'Education') { erpnext.setup.fiscal_years = {
frappe.wiz.welcome_page = "#welcome-to-erpnext"; "Afghanistan": ["12-20", "12-21"],
"Australia": ["07-01", "06-30"],
"Bangladesh": ["07-01", "06-30"],
"Canada": ["04-01", "03-31"],
"Costa Rica": ["10-01", "09-30"],
"Egypt": ["07-01", "06-30"],
"Hong Kong": ["04-01", "03-31"],
"India": ["04-01", "03-31"],
"Iran": ["06-23", "06-22"],
"Italy": ["07-01", "06-30"],
"Myanmar": ["04-01", "03-31"],
"New Zealand": ["04-01", "03-31"],
"Pakistan": ["07-01", "06-30"],
"Singapore": ["04-01", "03-31"],
"South Africa": ["03-01", "02-28"],
"Thailand": ["10-01", "09-30"],
"United Kingdom": ["04-01", "03-31"],
};
frappe.setup.on("before_load", function () {
erpnext_slides.map(frappe.setup.add_slide);
// change header brand
let $brand = $('header .setup-wizard-brand');
if($brand.find('.erpnext-icon').length === 0) {
$brand.find('.frappe-icon').hide();
$brand.append(`<span>
<img src="/assets/erpnext/images/erp-icon.svg" class="brand-icon erpnext-icon"
style="width:36px;"><span class="brand-name">ERPNext</span></span>`);
} }
}); });
var test_values_edu = { var test_values_edu = {
"language":"english", "language": "english",
"domain":"Education", "domain": "Education",
"country":"India", "country": "India",
"timezone":"Asia/Kolkata", "timezone": "Asia/Kolkata",
"currency":"INR", "currency": "INR",
"first_name":"Tester", "first_name": "Tester",
"email":"test@example.com", "email": "test@example.com",
"password":"test", "password": "test",
"company_name":"Hogwarts", "company_name": "Hogwarts",
"company_abbr":"HS", "company_abbr": "HS",
"company_tagline":"School for magicians", "company_tagline": "School for magicians",
"bank_account":"Gringotts Wizarding Bank", "bank_account": "Gringotts Wizarding Bank",
"fy_start_date":"2016-04-01", "fy_start_date": "2016-04-01",
"fy_end_date":"2017-03-31" "fy_end_date": "2017-03-31"
} }

View File

@ -1,8 +1,9 @@
{{ address_line1 }}<br>{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}{{ city }}<br> {{ address_line1 }}<br>{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}{{ city }}<br>
{% if state %}{{ state }}<br>{% endif -%} {% if gst_state %}{{ gst_state }}{% endif -%},
{% if pincode %}{{ pincode }}<br>{% endif -%} {% if gst_state_number %}State Code: {{ gst_state_number }}<br>{% endif -%}
{% if pincode %}PIN: {{ pincode }}<br>{% endif -%}
{{ country }}<br> {{ country }}<br>
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
{% if phone %}Phone: {{ phone }}<br>{% endif -%} {% if phone %}Phone: {{ phone }}<br>{% endif -%}
{% if fax %}Fax: {{ fax }}<br>{% endif -%} {% if fax %}Fax: {{ fax }}<br>{% endif -%}
{% if email_id %}Email: {{ email_id }}<br>{% endif -%} {% if email_id %}Email: {{ email_id }}<br>{% endif -%}
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}

View File

@ -14,6 +14,7 @@ def setup(company=None, patch=True):
add_custom_roles_for_reports() add_custom_roles_for_reports()
add_hsn_codes() add_hsn_codes()
update_address_template() update_address_template()
add_print_formats()
if not patch: if not patch:
make_fixtures() make_fixtures()
@ -69,50 +70,57 @@ def add_permissions():
add_permission(doctype, 'Accounts Manager', 0) add_permission(doctype, 'Accounts Manager', 0)
add_permission(doctype, 'All', 0) add_permission(doctype, 'All', 0)
def add_print_formats():
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
def make_custom_fields(): def make_custom_fields():
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
custom_fields = { custom_fields = {
'Address': [ 'Address': [
dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data', dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data',
insert_after='fax'), insert_after='fax'),
dict(fieldname='gst_state', label='GST State', fieldtype='Select', dict(fieldname='gst_state', label='GST State', fieldtype='Select',
options='\n'.join(states), insert_after='gstin') options='\n'.join(states), insert_after='gstin'),
dict(fieldname='gst_state_number', label='GST State Number',
fieldtype='Int', insert_after='gst_state'),
], ],
'Purchase Invoice': [ 'Purchase Invoice': [
dict(fieldname='supplier_gstin', label='Supplier GSTIN', dict(fieldname='supplier_gstin', label='Supplier GSTIN',
fieldtype='Data', insert_after='supplier_address', fieldtype='Data', insert_after='supplier_address',
options='supplier_address.gstin'), options='supplier_address.gstin', print_hide=1),
dict(fieldname='company_gstin', label='Company GSTIN', dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='shipping_address', fieldtype='Data', insert_after='shipping_address',
options='shipping_address.gstin'), options='shipping_address.gstin', print_hide=1),
], ],
'Sales Invoice': [ 'Sales Invoice': [
dict(fieldname='customer_gstin', label='Customer GSTIN', dict(fieldname='customer_gstin', label='Customer GSTIN',
fieldtype='Data', insert_after='shipping_address', fieldtype='Data', insert_after='shipping_address',
options='shipping_address_name.gstin'), options='shipping_address_name.gstin', print_hide=1),
dict(fieldname='company_gstin', label='Company GSTIN', dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='company_address', fieldtype='Data', insert_after='company_address',
options='company_address.gstin'), options='company_address.gstin', print_hide=1),
dict(fieldname='invoice_copy', label='Invoice Copy',
fieldtype='Select', insert_after='project', print_hide=1,
options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER')
], ],
'Item': [ 'Item': [
dict(fieldname='gst_hsn_code', label='GST HSN Code', dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Link', options='GST HSN Code', insert_after='item_group'), fieldtype='Link', options='GST HSN Code', insert_after='item_group'),
], ],
'Sales Invoice Item': [ 'Sales Order Item': [hsn_sac_field],
dict(fieldname='gst_hsn_code', label='GST HSN Code', 'Delivery Note Item': [hsn_sac_field],
fieldtype='Data', options='item_code.gst_hsn_code', 'Sales Invoice Item': [hsn_sac_field],
insert_after='income_account'), 'Purchase Order Item': [hsn_sac_field],
], 'Purchase Receipt Item': [hsn_sac_field],
'Purchase Invoice Item': [ 'Purchase Invoice Item': [hsn_sac_field]
dict(fieldname='gst_hsn_code', label='GST HSN Code',
fieldtype='Data', options='item_code.gst_hsn_code',
insert_after='expense_account'),
]
} }
for doctype, fields in custom_fields.items(): for doctype, fields in custom_fields.items():
for df in fields: for df in fields:
create_custom_field(doctype, df) create_custom_field(doctype, df)
def make_fixtures(): def make_fixtures():
docs = [ docs = [
{'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'}, {'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'},

View File

@ -7,6 +7,7 @@ def validate_gstin_for_india(doc, method):
return return
if doc.gstin: if doc.gstin:
doc.gstin = doc.gstin.upper()
if doc.gstin != "NA": if doc.gstin != "NA":
p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}") p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
if not p.match(doc.gstin): if not p.match(doc.gstin):
@ -16,7 +17,8 @@ def validate_gstin_for_india(doc, method):
if doc.state in states: if doc.state in states:
doc.gst_state = doc.state doc.gst_state = doc.state
if doc.gst_state: if doc.gst_state:
state_number = state_numbers[doc.gst_state] doc.gst_state_number = state_numbers[doc.gst_state]
if state_number != doc.gstin[:2]: if doc.gst_state_number != doc.gstin[:2]:
frappe.throw(_("First 2 digits of GSTIN should match with State number {0}").format(state_number)) frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
.format(doc.gst_state_number))

View File

@ -0,0 +1,22 @@
{
"align_labels_left": 0,
"creation": "2017-07-04 16:26:21.120187",
"custom_format": 0,
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div class=\\\"print-heading\\\">\\n\\t<h2>\\n\\t\\tSALES INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-right\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small><i>({{ doc.invoice_copy }})</i></small>\\n\\t{% endif -%}\\n</h2>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"<hr>\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Item-wise Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]",
"idx": 0,
"line_breaks": 0,
"modified": "2017-07-06 13:45:55.033384",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Tax Invoice",
"owner": "Administrator",
"print_format_builder": 1,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@ -114,13 +114,17 @@ def get_student_guardians(student):
return guardians return guardians
@frappe.whitelist() @frappe.whitelist()
def get_student_group_students(student_group): def get_student_group_students(student_group, include_inactive=0):
"""Returns List of student, student_name in Student Group. """Returns List of student, student_name in Student Group.
:param student_group: Student Group. :param student_group: Student Group.
""" """
students = frappe.get_list("Student Group Student", fields=["student", "student_name"] , if include_inactive:
filters={"parent": student_group, "active": 1}, order_by= "group_roll_number") students = frappe.get_list("Student Group Student", fields=["student", "student_name"] ,
filters={"parent": student_group}, order_by= "group_roll_number")
else:
students = frappe.get_list("Student Group Student", fields=["student", "student_name"] ,
filters={"parent": student_group, "active": 1}, order_by= "group_roll_number")
return students return students
@frappe.whitelist() @frappe.whitelist()

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"autoname": "field:title", "autoname": "field:title",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -23,6 +25,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Academic Year", "label": "Academic Year",
@ -42,6 +45,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -52,6 +56,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Term Name", "label": "Term Name",
@ -70,6 +75,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -80,6 +86,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Term Start Date", "label": "Term Start Date",
@ -98,6 +105,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -108,6 +116,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Term End Date", "label": "Term End Date",
@ -126,6 +135,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -136,6 +146,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Title", "label": "Title",
@ -154,17 +165,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-11-07 05:45:48.577744", "modified": "2017-06-30 08:21:45.897056",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Academic Term", "name": "Academic Term",
@ -181,7 +192,6 @@
"export": 1, "export": 1,
"if_owner": 0, "if_owner": 0,
"import": 0, "import": 0,
"is_custom": 0,
"permlevel": 0, "permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
@ -196,8 +206,11 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "name", "sort_field": "name",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "title", "title_field": "title",
"track_changes": 0,
"track_seen": 0 "track_seen": 0
} }

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 0, "allow_rename": 0,
"autoname": "field:academic_year_name", "autoname": "field:academic_year_name",
@ -12,16 +13,20 @@
"editable_grid": 0, "editable_grid": 0,
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0,
"fieldname": "academic_year_name", "fieldname": "academic_year_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0,
"label": "Academic Year Name", "label": "Academic Year Name",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@ -30,6 +35,7 @@
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
@ -37,16 +43,20 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0,
"fieldname": "year_start_date", "fieldname": "year_start_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Year Start Date", "label": "Year Start Date",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@ -55,6 +65,7 @@
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
@ -62,16 +73,20 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0,
"fieldname": "year_end_date", "fieldname": "year_end_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Year End Date", "label": "Year End Date",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@ -80,6 +95,7 @@
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
@ -87,17 +103,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-07-25 05:24:23.090530", "modified": "2017-06-30 08:21:46.121105",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Academic Year", "name": "Academic Year",
@ -128,8 +144,11 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "", "title_field": "",
"track_changes": 0,
"track_seen": 0 "track_seen": 0
} }

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 0, "allow_rename": 0,
"autoname": "field:assessment_criteria", "autoname": "field:assessment_criteria",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -22,7 +24,9 @@
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_list_view": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Criteria", "label": "Assessment Criteria",
"length": 0, "length": 0,
@ -40,6 +44,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
@ -49,6 +54,8 @@
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Criteria Group", "label": "Assessment Criteria Group",
@ -68,17 +75,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-03 05:53:39.248759", "modified": "2017-06-30 08:21:46.211641",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Criteria", "name": "Assessment Criteria",
@ -109,6 +116,8 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 0, "track_changes": 0,

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"autoname": "field:assessment_criteria_group", "autoname": "field:assessment_criteria_group",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -23,7 +25,8 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_list_view": 0, "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Criteria Group", "label": "Assessment Criteria Group",
"length": 0, "length": 0,
@ -41,17 +44,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-01 17:39:12.453618", "modified": "2017-06-30 08:21:46.323964",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Criteria Group", "name": "Assessment Criteria Group",
@ -82,6 +85,8 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 0, "track_changes": 0,

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"autoname": "field:assessment_group_name", "autoname": "field:assessment_group_name",
@ -12,6 +13,7 @@
"editable_grid": 1, "editable_grid": 1,
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -23,7 +25,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Group Name", "label": "Assessment Group Name",
"length": 0, "length": 0,
@ -41,6 +43,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -70,6 +73,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -98,6 +102,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -109,7 +114,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Parent Assessment Group", "label": "Parent Assessment Group",
"length": 0, "length": 0,
@ -128,6 +133,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -157,6 +163,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -186,6 +193,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -216,17 +224,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-24 15:18:54.725368", "modified": "2017-06-30 08:21:46.411222",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Group", "name": "Assessment Group",
@ -257,6 +265,7 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -633,7 +633,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-05 23:40:30.434741", "modified": "2017-06-30 08:21:46.535547",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Plan", "name": "Assessment Plan",
@ -664,6 +664,7 @@
"quick_entry": 0, "quick_entry": 0,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -11,6 +11,7 @@ class AssessmentPlan(Document):
def validate(self): def validate(self):
self.validate_overlap() self.validate_overlap()
self.validate_max_score() self.validate_max_score()
self.validate_assessment_criteria()
def validate_overlap(self): def validate_overlap(self):
"""Validates overlap for Student Group, Instructor, Room""" """Validates overlap for Student Group, Instructor, Room"""
@ -37,3 +38,13 @@ class AssessmentPlan(Document):
max_score += d.maximum_score max_score += d.maximum_score
if self.maximum_assessment_score != max_score: if self.maximum_assessment_score != max_score:
frappe.throw(_("Sum of Scores of Assessment Criteria needs to be {0}.".format(self.maximum_assessment_score))) frappe.throw(_("Sum of Scores of Assessment Criteria needs to be {0}.".format(self.maximum_assessment_score)))
def validate_assessment_criteria(self):
assessment_criteria_list = frappe.db.sql_list(''' select apc.assessment_criteria
from `tabAssessment Plan` ap , `tabAssessment Plan Criteria` apc
where ap.name = apc.parent and ap.course=%s and ap.student_group=%s and ap.assessment_group=%s
and ap.name != %s''', (self.course, self.student_group, self.assessment_group, self.name))
for d in self.assessment_criteria:
if d.assessment_criteria in assessment_criteria_list:
frappe.throw(_("You have already assessed for the assessment criteria {}.")
.format(frappe.bold(d.assessment_criteria)))

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
"autoname": "", "autoname": "",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -23,6 +25,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Criteria", "label": "Assessment Criteria",
@ -42,6 +45,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -52,6 +56,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "", "label": "",
@ -70,6 +75,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -80,6 +86,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Maximum Score", "label": "Maximum Score",
@ -98,17 +105,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-01 17:11:47.164623", "modified": "2017-06-30 08:21:46.732666",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Plan Criteria", "name": "Assessment Plan Criteria",
@ -118,6 +125,8 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 0, "track_changes": 0,

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
"autoname": "RES.######", "autoname": "RES.######",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -43,6 +45,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -72,6 +75,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -100,6 +104,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -130,6 +135,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -160,6 +166,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -188,6 +195,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -219,6 +227,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -247,6 +256,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -276,6 +286,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -305,6 +316,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -333,6 +345,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -362,6 +375,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -390,6 +404,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -419,6 +434,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -448,17 +464,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 1, "is_submittable": 1,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-21 08:03:46.054604", "modified": "2017-06-30 08:21:46.875594",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Result", "name": "Assessment Result",
@ -489,6 +505,7 @@
"quick_entry": 0, "quick_entry": 0,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 1, "show_name_in_global_search": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
"autoname": "", "autoname": "",
@ -13,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -23,6 +25,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Criteria", "label": "Assessment Criteria",
@ -42,6 +45,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -52,6 +56,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Maximum Score", "label": "Maximum Score",
@ -70,6 +75,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -80,6 +86,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "", "label": "",
@ -98,6 +105,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -108,6 +116,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Score", "label": "Score",
@ -126,6 +135,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -136,6 +146,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Grade", "label": "Grade",
@ -154,17 +165,17 @@
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 0, "idx": 0,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"in_dialog": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-01 18:33:06.006040", "modified": "2017-06-30 08:21:47.068704",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Result Detail", "name": "Assessment Result Detail",
@ -174,6 +185,8 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 0, "track_changes": 0,

View File

@ -26,7 +26,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Assessment Plan", "label": "Assessment Plan",
"length": 0, "length": 0,
@ -86,7 +86,7 @@
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Student Group", "label": "Student Group",
"length": 0, "length": 0,
@ -175,7 +175,7 @@
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-05-02 15:12:30.953036", "modified": "2017-06-30 08:21:47.184562",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Result Tool", "name": "Assessment Result Tool",
@ -206,6 +206,7 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -14,6 +14,7 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -43,6 +44,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -73,6 +75,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -102,6 +105,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -130,6 +134,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -159,6 +164,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -188,6 +194,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -216,6 +223,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -245,6 +253,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -274,6 +283,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -304,6 +314,7 @@
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@ -345,7 +356,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-04-12 20:44:42.048564", "modified": "2017-06-30 08:21:47.260549",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Course", "name": "Course",
@ -396,6 +407,7 @@
"quick_entry": 0, "quick_entry": 0,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"search_fields": "course_name", "search_fields": "course_name",
"show_name_in_global_search": 1, "show_name_in_global_search": 1,
"sort_field": "modified", "sort_field": "modified",

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