Merge pull request #7014 from rohitwaghchaure/rename_autoname_field
patch for rename autoname field
diff --git a/erpnext/accounts/doctype/asset/asset.js b/erpnext/accounts/doctype/asset/asset.js
index 8ff4b83..664ed4d 100644
--- a/erpnext/accounts/doctype/asset/asset.js
+++ b/erpnext/accounts/doctype/asset/asset.js
@@ -28,6 +28,7 @@
refresh: function(frm) {
frappe.ui.form.trigger("Asset", "is_existing_asset");
frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1);
+ frm.events.make_schedules_editable(frm);
if (frm.doc.docstatus==1) {
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
@@ -141,6 +142,22 @@
frm.toggle_enable("supplier", frm.doc.is_existing_asset);
frm.toggle_reqd("next_depreciation_date", !frm.doc.is_existing_asset);
},
+
+ opening_accumulated_depreciation: function(frm) {
+ erpnext.asset.set_accululated_depreciation(frm);
+ },
+
+ depreciation_method: function(frm) {
+ frm.events.make_schedules_editable(frm);
+ },
+
+ make_schedules_editable: function(frm) {
+ var is_editable = frm.doc.depreciation_method==="Manual" ? true : false;
+ frm.toggle_enable("schedules", is_editable);
+ frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable);
+ frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable);
+ }
+
});
frappe.ui.form.on('Depreciation Schedule', {
@@ -159,9 +176,25 @@
}
})
}
+ },
+
+ depreciation_amount: function(frm, cdt, cdn) {
+ erpnext.asset.set_accululated_depreciation(frm);
}
+
})
+erpnext.asset.set_accululated_depreciation = function(frm) {
+ if(frm.doc.depreciation_method != "Manual") return;
+
+ accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation);
+ $.each(frm.doc.schedules || [], function(i, row) {
+ accumulated_depreciation += flt(row.depreciation_amount);
+ frappe.model.set_value(row.doctype, row.name,
+ "accumulated_depreciation_amount", accumulated_depreciation);
+ })
+}
+
erpnext.asset.make_purchase_invoice = function(frm) {
frappe.call({
args: {
diff --git a/erpnext/accounts/doctype/asset/asset.json b/erpnext/accounts/doctype/asset/asset.json
index d3a88fb..95d9b48 100644
--- a/erpnext/accounts/doctype/asset/asset.json
+++ b/erpnext/accounts/doctype/asset/asset.json
@@ -516,7 +516,7 @@
"columns": 0,
"fieldname": "value_after_depreciation",
"fieldtype": "Currency",
- "hidden": 0,
+ "hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
@@ -580,7 +580,7 @@
"label": "Depreciation Method",
"length": 0,
"no_copy": 0,
- "options": "\nStraight Line\nDouble Declining Balance",
+ "options": "\nStraight Line\nDouble Declining Balance\nManual",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -750,7 +750,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -797,7 +797,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-11-03 14:58:53.710357",
+ "modified": "2016-11-18 15:59:19.774500",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset",
diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py
index da73218..9caac07 100644
--- a/erpnext/accounts/doctype/asset/asset.py
+++ b/erpnext/accounts/doctype/asset/asset.py
@@ -18,6 +18,7 @@
self.set_missing_values()
self.validate_asset_values()
self.make_depreciation_schedule()
+ self.set_accumulated_depreciation()
self.validate_expected_value_after_useful_life()
# Validate depreciation related accounts
get_depreciation_accounts(self)
@@ -48,7 +49,7 @@
for field, value in item_details.items():
if not self.get(field):
self.set(field, value)
-
+
self.value_after_depreciation = (flt(self.gross_purchase_amount) -
flt(self.opening_accumulated_depreciation))
@@ -87,9 +88,10 @@
frappe.throw(_("Please set Next Depreciation Date"))
def make_depreciation_schedule(self):
- self.schedules = []
+ if self.depreciation_method != 'Manual':
+ self.schedules = []
+
if not self.get("schedules") and self.next_depreciation_date:
- accumulated_depreciation = flt(self.opening_accumulated_depreciation)
value_after_depreciation = flt(self.value_after_depreciation)
number_of_pending_depreciations = cint(self.total_number_of_depreciations) - \
@@ -100,18 +102,21 @@
n * cint(self.frequency_of_depreciation))
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
-
- accumulated_depreciation += flt(depreciation_amount)
value_after_depreciation -= flt(depreciation_amount)
self.append("schedules", {
"schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "accumulated_depreciation_amount": accumulated_depreciation
+ "depreciation_amount": depreciation_amount
})
+
+ def set_accumulated_depreciation(self):
+ accumulated_depreciation = flt(self.opening_accumulated_depreciation)
+ for d in self.get("schedules"):
+ accumulated_depreciation += flt(d.depreciation_amount)
+ d.accumulated_depreciation_amount = accumulated_depreciation
def get_depreciation_amount(self, depreciable_value):
- if self.depreciation_method == "Straight Line":
+ if self.depreciation_method in ("Straight Line", "Manual"):
depreciation_amount = (flt(self.value_after_depreciation) -
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked))
@@ -126,16 +131,15 @@
return depreciation_amount
def validate_expected_value_after_useful_life(self):
- if self.depreciation_method == "Double Declining Balance":
- accumulated_depreciation_after_full_schedule = \
- max([d.accumulated_depreciation_amount for d in self.get("schedules")])
-
- asset_value_after_full_schedule = (flt(self.gross_purchase_amount) -
- flt(accumulated_depreciation_after_full_schedule))
-
- if self.expected_value_after_useful_life < asset_value_after_full_schedule:
- frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
- .format(asset_value_after_full_schedule))
+ accumulated_depreciation_after_full_schedule = \
+ max([d.accumulated_depreciation_amount for d in self.get("schedules")])
+
+ asset_value_after_full_schedule = (flt(self.gross_purchase_amount) -
+ flt(accumulated_depreciation_after_full_schedule))
+
+ if self.expected_value_after_useful_life < asset_value_after_full_schedule:
+ frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
+ .format(asset_value_after_full_schedule))
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
diff --git a/erpnext/accounts/doctype/asset/test_asset.py b/erpnext/accounts/doctype/asset/test_asset.py
index b409ec3..51496b9 100644
--- a/erpnext/accounts/doctype/asset/test_asset.py
+++ b/erpnext/accounts/doctype/asset/test_asset.py
@@ -119,6 +119,30 @@
for d in asset.get("schedules")]
self.assertEqual(schedules, expected_schedules)
+
+ def test_schedule_for_manual_method(self):
+ asset = frappe.get_doc("Asset", "Macbook Pro 1")
+ asset.depreciation_method = "Manual"
+ asset.schedules = []
+ for schedule_date, amount in [["2020-12-31", 40000], ["2021-06-30", 30000], ["2021-10-31", 20000]]:
+ asset.append("schedules", {
+ "schedule_date": schedule_date,
+ "depreciation_amount": amount
+ })
+ asset.save()
+
+ self.assertEqual(asset.status, "Draft")
+
+ expected_schedules = [
+ ["2020-12-31", 40000, 40000],
+ ["2021-06-30", 30000, 70000],
+ ["2021-10-31", 20000, 90000]
+ ]
+
+ schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
+ for d in asset.get("schedules")]
+
+ self.assertEqual(schedules, expected_schedules)
def test_depreciation(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")
diff --git a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
index 57c14b7..1fadf5e 100644
--- a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
+++ b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
@@ -10,11 +10,13 @@
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
+ "engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "schedule_date",
"fieldtype": "Date",
"hidden": 0,
@@ -29,7 +31,8 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -40,6 +43,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "depreciation_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -55,7 +59,8 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -66,6 +71,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -80,6 +86,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
+ "remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -90,6 +97,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "accumulated_depreciation_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -106,8 +114,9 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
+ "remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -116,6 +125,8 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.docstatus==1",
"fieldname": "journal_entry",
"fieldtype": "Link",
"hidden": 0,
@@ -132,6 +143,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
+ "remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -142,7 +154,8 @@
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
- "depends_on": "eval:(!doc.journal_entry && doc.schedule_date <= get_today())",
+ "columns": 0,
+ "depends_on": "eval:(doc.docstatus==1 && !doc.journal_entry && doc.schedule_date <= get_today())",
"fieldname": "make_depreciation_entry",
"fieldtype": "Button",
"hidden": 0,
@@ -158,6 +171,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
+ "remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -175,7 +189,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-07-11 03:27:59.603924",
+ "modified": "2016-11-18 16:42:19.543657",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Depreciation Schedule",
diff --git a/erpnext/accounts/doctype/pos_customer_group/__init__.py b/erpnext/accounts/doctype/pos_customer_group/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/__init__.py
diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
new file mode 100644
index 0000000..4f6a675
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
@@ -0,0 +1,66 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-11-16 15:27:16.413449",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "customer_group",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Customer Group",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Customer Group",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-11-16 15:27:25.730507",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Customer Group",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py
new file mode 100644
index 0000000..85c1c9f
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class POSCustomerGroup(Document):
+ pass
diff --git a/erpnext/accounts/doctype/pos_item_group/__init__.py b/erpnext/accounts/doctype/pos_item_group/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/__init__.py
diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.json b/erpnext/accounts/doctype/pos_item_group/pos_item_group.json
new file mode 100644
index 0000000..b278765
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.json
@@ -0,0 +1,66 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-11-16 15:26:47.706713",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Item Group",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Item Group",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-11-16 15:27:32.263630",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Item Group",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py
new file mode 100644
index 0000000..ceaa57b
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class POSItemGroup(Document):
+ pass
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index c1aa0c3..bbbab73 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -26,6 +26,30 @@
});
});
+frappe.ui.form.on("POS Profile", {
+ setup: function(frm) {
+ frm.trigger("get_query_for_groups")
+ },
+
+ get_query_for_groups: function(frm) {
+ frm.fields_dict['item_groups'].grid.get_field('item_group').get_query = function(frm, cdt, cdn) {
+ return{
+ filters: {
+ 'is_group': 0
+ }
+ }
+ }
+
+ frm.fields_dict['customer_groups'].grid.get_field('customer_group').get_query = function(frm, cdt, cdn) {
+ return{
+ filters: {
+ 'is_group': 0
+ }
+ }
+ }
+ }
+})
+
// Income Account
// --------------------------------
cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) {
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index f450121..e6cfd74 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -380,6 +380,114 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "section_break_14",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "item_groups",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Item Groups",
+ "length": 0,
+ "no_copy": 0,
+ "options": "POS Item Group",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "customer_groups",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Customer Groups",
+ "length": 0,
+ "no_copy": 0,
+ "options": "POS Customer Group",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "section_break_16",
"fieldtype": "Section Break",
"hidden": 0,
@@ -548,34 +656,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "customer_group",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "label": "Customer Group",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Group",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
@@ -951,8 +1031,8 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-11-03 15:53:33.820428",
- "modified_by": "Administrator",
+ "modified": "2016-11-17 00:20:51.377850",
+ "modified_by": "rohit@erpnext.com",
"module": "Accounts",
"name": "POS Profile",
"owner": "Administrator",
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 5f4d5bc..ef497bf 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -13,6 +13,7 @@
def validate(self):
self.check_for_duplicate()
self.validate_all_link_fields()
+ self.validate_duplicate_groups()
def check_for_duplicate(self):
res = frappe.db.sql("""select name, user from `tabPOS Profile`
@@ -37,6 +38,16 @@
"company": self.company, "name": link_dn}):
frappe.throw(_("{0} does not belong to Company {1}").format(link_dn, self.company))
+ def validate_duplicate_groups(self):
+ item_groups = [d.item_group for d in self.item_groups]
+ customer_groups = [d.customer_group for d in self.customer_groups]
+
+ if len(item_groups) != len(set(item_groups)):
+ frappe.throw(_("Duplicate item group found in the item group table"), title = "Duplicate Item Group")
+
+ if len(customer_groups) != len(set(customer_groups)):
+ frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
+
def before_save(self):
set_account_for_mode_of_payment(self)
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 62274a3..9c6a114 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -5,8 +5,47 @@
import frappe
import unittest
-
-# test_records = frappe.get_test_records('POS Profile')
+from erpnext.stock.get_item_details import get_pos_profile
+from erpnext.accounts.doctype.sales_invoice.pos import get_items_list, get_customers_list
class TestPOSProfile(unittest.TestCase):
- pass
+ def test_pos_profile(self):
+ make_pos_profile()
+
+ pos_profile = get_pos_profile("_Test Company") or {}
+ if pos_profile:
+ doc = frappe.get_doc("POS Profile", pos_profile.get("name"))
+ doc.append('item_groups', {'item_group': '_Test Item Group'})
+ doc.append('customer_groups', {'customer_group': '_Test Customer Group'})
+ doc.save()
+
+ items = get_items_list(doc)
+ customers = get_customers_list(doc)
+
+ products_count = frappe.db.sql(""" select count(name) from tabItem where item_group = '_Test Item Group'""", as_list=1)
+ customers_count = frappe.db.sql(""" select count(name) from tabCustomer where customer_group = '_Test Customer Group'""")
+
+ self.assertEquals(len(items), products_count[0][0])
+ self.assertEquals(len(customers), customers_count[0][0])
+
+ frappe.db.sql("delete from `tabPOS Profile`")
+
+def make_pos_profile():
+ pos_profile = frappe.get_doc({
+ "company": "_Test Company",
+ "cost_center": "_Test Cost Center - _TC",
+ "currency": "INR",
+ "doctype": "POS Profile",
+ "expense_account": "_Test Account Cost for Goods Sold - _TC",
+ "income_account": "Sales - _TC",
+ "name": "_Test POS Profile",
+ "naming_series": "_T-POS Profile-",
+ "selling_price_list": "_Test Price List",
+ "territory": "_Test Territory",
+ "warehouse": "_Test Warehouse - _TC",
+ "write_off_account": "_Test Write Off - _TC",
+ "write_off_cost_center": "_Test Write Off Cost Center - _TC"
+ })
+
+ if not frappe.db.exists("POS Profile", "_Test POS Profile"):
+ pos_profile.insert()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 1d1a122..e5c86dc 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -30,10 +30,16 @@
return {
'doc': doc,
'default_customer': pos_profile.get('customer'),
- 'items': get_items(doc, pos_profile),
- 'customers': get_customers(pos_profile, doc, company_data.default_currency),
- 'pricing_rules': get_pricing_rules(doc),
+ 'items': get_items_list(pos_profile),
+ 'customers': get_customers_list(pos_profile),
+ 'serial_no_data': get_serial_no_data(pos_profile, doc.company),
+ 'batch_no_data': get_batch_no_data(),
+ 'tax_data': get_item_tax_data(),
+ 'price_list_data': get_price_list_data(doc.selling_price_list),
+ 'bin_data': get_bin_data(pos_profile),
+ 'pricing_rules': get_pricing_rule_data(doc),
'print_template': print_template,
+ 'pos_profile': pos_profile,
'meta': {
'invoice': frappe.get_meta('Sales Invoice'),
'items': frappe.get_meta('Sales Invoice Item'),
@@ -104,63 +110,116 @@
for tax in taxes:
doc.append('taxes', tax)
-def get_items(doc, pos_profile):
- item_list = []
- for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0, 'is_sales_item': 1}):
- item_doc = frappe.get_doc('Item', item.name)
- if item_doc.taxes:
- item.taxes = json.dumps(dict(([d.tax_type, d.tax_rate] for d in
- item_doc.get("taxes"))))
+def get_items_list(pos_profile):
+ cond = "1=1"
+ item_groups = []
+ if pos_profile.get('item_groups'):
+ # Get items based on the item groups defined in the POS profile
- item.price_list_rate = frappe.db.get_value('Item Price', {'item_code': item.name,
- 'price_list': doc.selling_price_list}, 'price_list_rate') or 0
- item.default_warehouse = pos_profile.get('warehouse') or \
- get_item_warehouse_for_company(doc.company, item.default_warehouse) or None
- item.expense_account = pos_profile.get('expense_account') or item.expense_account
- item.income_account = pos_profile.get('income_account') or item_doc.income_account
- item.cost_center = pos_profile.get('cost_center') or item_doc.selling_cost_center
- item.actual_qty = frappe.db.get_value('Bin', {'item_code': item.name,
- 'warehouse': item.default_warehouse}, 'actual_qty') or 0
- item.serial_nos = get_serial_nos(item, pos_profile, doc.company)
- item.batch_nos = frappe.db.sql_list("""select name from `tabBatch` where ifnull(expiry_date, '4000-10-10') > curdate()
- and item = %(item_code)s""", {'item_code': item.item_code})
+ cond = "item_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('item_groups'))))
+ item_groups = [d.item_group for d in pos_profile.get('item_groups')]
- item_list.append(item)
+ return frappe.db.sql("""
+ select
+ name, item_code, item_name, description, item_group, expense_account, has_batch_no,
+ has_serial_no, expense_account, selling_cost_center, stock_uom, image, default_warehouse
+ from
+ tabItem
+ where
+ disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
+ """.format(cond=cond), tuple(item_groups), as_dict=1)
- return item_list
+def get_customers_list(pos_profile):
+ cond = "1=1"
+ customer_groups = []
+ if pos_profile.get('customer_groups'):
+ # Get customers based on the customer groups defined in the POS profile
-def get_item_warehouse_for_company(company, warehouse):
- if frappe.db.get_value('Warehouse', warehouse, 'company') != company:
- warehouse = None
- return warehouse
+ cond = "customer_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('customer_groups'))))
+ customer_groups = [d.customer_group for d in pos_profile.get('customer_groups')]
-def get_serial_nos(item, pos_profile, company):
+ return frappe.db.sql(""" select name, customer_name, customer_group,
+ territory from tabCustomer where disabled = 0
+ and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
+
+def get_serial_no_data(pos_profile, company):
+ # get itemwise serial no data
+ # example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
+ # where Nokia Lumia 1020 is item code, SN0001 is serial no and Pune is warehouse
+
cond = "1=1"
if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
- serial_nos = frappe.db.sql("""select name, warehouse from `tabSerial No` where {0}
- and item_code = %(item_code)s and company = %(company)s
- """.format(cond), {'item_code': item.item_code, 'company': company}, as_dict=1)
+ serial_nos = frappe.db.sql("""select name, warehouse, item_code from `tabSerial No` where {0}
+ and company = %(company)s """.format(cond), {'company': company}, as_dict=1)
- serial_no_list = {}
- for serial_no in serial_nos:
- serial_no_list[serial_no.name] = serial_no.warehouse
+ itemwise_serial_no = {}
+ for sn in serial_nos:
+ if sn.item_code not in itemwise_serial_no:
+ itemwise_serial_no.setdefault(sn.item_code, {})
+ itemwise_serial_no[sn.item_code][sn.name] = sn.warehouse
- return serial_no_list
+ return itemwise_serial_no
-def get_customers(pos_profile, doc, company_currency):
- filters = {'disabled': 0}
- customer_list = []
- customers = frappe.get_all("Customer", fields=["*"], filters = filters)
+def get_batch_no_data():
+ # get itemwise batch no data
+ # exmaple: {'LED-GRE': [Batch001, Batch002]}
+ # where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
- for customer in customers:
- customer_currency = get_party_account_currency('Customer', customer.name, doc.company) or doc.currency
- if customer_currency == doc.currency or customer_currency == company_currency:
- customer_list.append(customer)
- return customer_list
+ itemwise_batch = {}
+ batches = frappe.db.sql("""select name, item from `tabBatch`
+ where ifnull(expiry_date, '4000-10-10') >= curdate()""", as_dict=1)
-def get_pricing_rules(doc):
+ for batch in batches:
+ if batch.item not in itemwise_batch:
+ itemwise_batch.setdefault(batch.item, [])
+ itemwise_batch[batch.item].append(batch.name)
+
+ return itemwise_batch
+
+def get_item_tax_data():
+ # get default tax of an item
+ # example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
+
+ itemwise_tax = {}
+ taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
+
+ for tax in taxes:
+ if tax.parent not in itemwise_tax:
+ itemwise_tax.setdefault(tax.parent, {})
+ itemwise_tax[tax.parent][tax.tax_type] = tax.tax_rate
+
+ return itemwise_tax
+
+def get_price_list_data(selling_price_list):
+ itemwise_price_list = {}
+ price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
+ item_code from `tabItem Price` ip where price_list = %(price_list)s""",
+ {'price_list': selling_price_list}, as_dict=1)
+
+ for item in price_lists:
+ itemwise_price_list[item.item_code] = item.price_list_rate
+
+ return itemwise_price_list
+
+def get_bin_data(pos_profile):
+ itemwise_bin_data = {}
+ cond = "1=1"
+ if pos_profile.get('warehouse'):
+ cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
+
+ bin_data = frappe.db.sql(""" select item_code, warehouse, actual_qty from `tabBin`
+ where actual_qty > 0 and {cond}""".format(cond=cond), as_dict=1)
+
+ for bins in bin_data:
+ if bins.item_code not in itemwise_bin_data:
+ itemwise_bin_data.setdefault(bins.item_code, {})
+ itemwise_bin_data[bins.item_code][bins.warehouse] = bins.actual_qty
+
+ return itemwise_bin_data
+
+def get_pricing_rule_data(doc):
pricing_rules = ""
if doc.ignore_pricing_rule == 0:
pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 511eeaa..c4f275a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -7,6 +7,7 @@
from frappe.utils import nowdate, add_days, flt, nowdate
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
@@ -467,7 +468,7 @@
def test_pos_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
- self.make_pos_profile()
+ make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -486,7 +487,7 @@
def test_pos_change_amount(self):
set_perpetual_inventory()
- self.make_pos_profile()
+ make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -508,7 +509,7 @@
set_perpetual_inventory()
- self.make_pos_profile()
+ make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -572,26 +573,6 @@
frappe.db.sql("delete from `tabPOS Profile`")
- def make_pos_profile(self):
- pos_profile = frappe.get_doc({
- "company": "_Test Company",
- "cost_center": "_Test Cost Center - _TC",
- "currency": "INR",
- "doctype": "POS Profile",
- "expense_account": "_Test Account Cost for Goods Sold - _TC",
- "income_account": "Sales - _TC",
- "name": "_Test POS Profile",
- "naming_series": "_T-POS Profile-",
- "selling_price_list": "_Test Price List",
- "territory": "_Test Territory",
- "warehouse": "_Test Warehouse - _TC",
- "write_off_account": "_Test Write Off - _TC",
- "write_off_cost_center": "_Test Write Off Cost Center - _TC"
- })
-
- if not frappe.db.exists("POS Profile", "_Test POS Profile"):
- pos_profile.insert()
-
def test_sales_invoice_gl_entry_with_perpetual_inventory_no_item_code(self):
set_perpetual_inventory()
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 32e9b3a..26bf3ea 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -25,7 +25,6 @@
this.set_indicator();
this.onload();
this.make_menu_list();
- this.set_interval_for_si_sync();
this.si_docs = this.get_doc_from_localstorage();
},
@@ -73,8 +72,6 @@
this.get_data_from_server(function(){
me.create_new();
});
-
- this.check_internet_connection();
},
make_menu_list: function(){
@@ -204,13 +201,10 @@
freeze: true,
freeze_message: __("Master data syncing, it might take some time"),
callback: function(r){
- window.items = r.message.items;
- window.customers = r.message.customers;
- window.pricing_rules = r.message.pricing_rules;
- window.meta = r.message.meta;
- window.print_template = r.message.print_template;
- me.default_customer = r.message.default_customer || null;
+ me.init_master_data(r)
localStorage.setItem('doc', JSON.stringify(r.message.doc));
+ me.set_interval_for_si_sync();
+ me.check_internet_connection();
if(callback){
callback();
}
@@ -218,6 +212,22 @@
})
},
+ init_master_data: function(r){
+ var me = this;
+ this.meta = r.message.meta;
+ this.item_data = r.message.items;
+ this.customers = r.message.customers;
+ this.serial_no_data = r.message.serial_no_data;
+ this.batch_no_data = r.message.batch_no_data;
+ this.tax_data = r.message.tax_data;
+ this.price_list_data = r.message.price_list_data;
+ this.bin_data = r.message.bin_data;
+ this.pricing_rules = r.message.pricing_rules;
+ this.print_template = r.message.print_template;
+ this.pos_profile_data = r.message.pos_profile;
+ this.default_customer = r.message.default_customer || null;
+ },
+
save_previous_entry : function(){
if(this.frm.doc.items.length > 0){
this.create_invoice()
@@ -233,20 +243,19 @@
},
load_data: function(load_doc){
- this.items = window.items;
- this.customers = window.customers;
- this.pricing_rules = window.pricing_rules;
+ var me = this;
+ this.items = this.item_data;
if(load_doc) {
this.frm.doc = JSON.parse(localStorage.getItem('doc'));
}
- $.each(window.meta, function(i, data){
+ $.each(this.meta, function(i, data){
frappe.meta.sync(data)
})
this.print_template = frappe.render_template("print_template",
- {content: window.print_template, title:"POS",
+ {content: this.print_template, title:"POS",
base_url: frappe.urllib.get_base_url(), print_css: frappe.boot.print_css})
},
@@ -387,12 +396,12 @@
var $wrap = me.wrapper.find(".item-list");
me.wrapper.find(".item-list").empty();
- if (this.items) {
+ if (this.items.length > 0) {
$.each(this.items, function(index, obj) {
if(index < 30){
$(frappe.render_template("pos_item", {
item_code: obj.name,
- item_price: format_currency(obj.price_list_rate, me.frm.doc.currency),
+ item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
item_name: obj.name===obj.item_name ? "" : obj.item_name,
item_image: obj.image ? "url('" + obj.image + "')" : null,
color: frappe.get_palette(obj.item_name),
@@ -400,6 +409,8 @@
})).tooltip().appendTo($wrap);
}
});
+ } else {
+ $("<h4>Searching record not found.</h4>").appendTo($wrap)
}
if(this.items.length == 1
@@ -426,7 +437,7 @@
this.item_batch_no = {};
if(item_code){
- return $.grep(window.items, function(item){
+ return $.grep(this.item_data, function(item){
if(item.item_code == item_code ){
return true
}
@@ -439,14 +450,15 @@
search_status = true
if(key){
- return $.grep(window.items, function(item){
+ return $.grep(this.item_data, function(item){
if(search_status){
- if(in_list(item.batch_nos, me.search.$input.val())){
+ if(in_list(me.batch_no_data[item.item_code], me.search.$input.val())){
search_status = false;
return me.item_batch_no[item.item_code] = me.search.$input.val()
- } else if(in_list(Object.keys(item.serial_nos), me.search.$input.val())) {
+ } else if( me.serial_no_data[item.item_code]
+ && in_list(Object.keys(me.serial_no_data[item.item_code]), me.search.$input.val())) {
search_status = false;
- me.item_serial_no[item.item_code] = [me.search.$input.val(), item.serial_nos[me.search.$input.val()]]
+ me.item_serial_no[item.item_code] = [me.search.$input.val(), me.serial_no_data[item.item_code][me.search.$input.val()]]
return true
} else if(item.barcode == me.search.$input.val()) {
search_status = false;
@@ -458,7 +470,7 @@
}
})
}else{
- return window.items;
+ return this.item_data;
}
},
@@ -611,18 +623,18 @@
this.child.description = this.items[0].description;
this.child.qty = 1;
this.child.item_group = this.items[0].item_group;
- this.child.cost_center = this.items[0].cost_center;
- this.child.income_account = this.items[0].income_account;
+ this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center;
+ this.child.income_account = this.pos_profile_data['income_account'] || this.items[0].income_account;
this.child.warehouse = (this.item_serial_no[this.child.item_code]
- ? this.item_serial_no[this.child.item_code][1] : this.items[0].default_warehouse);
- this.child.price_list_rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
- this.child.rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
- this.child.actual_qty = this.items[0].actual_qty;
+ ? this.item_serial_no[this.child.item_code][1] : (this.pos_profile_data['warehouse'] || this.items[0].default_warehouse) );
+ this.child.price_list_rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
+ this.child.rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
+ this.child.actual_qty = me.get_actual_qty(this.items[0]);
this.child.amount = flt(this.child.qty) * flt(this.child.rate);
this.child.batch_no = this.item_batch_no[this.child.item_code];
this.child.serial_no = (this.item_serial_no[this.child.item_code]
? this.item_serial_no[this.child.item_code][0] : '');
- this.child.item_tax_rate = this.items[0].taxes;
+ this.child.item_tax_rate = JSON.stringify(this.tax_data[this.child.item_code]);
},
update_paid_amount_status: function(update_paid_amount){
@@ -668,7 +680,7 @@
item_code: d.item_code,
item_name: (d.item_name===d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
qty: d.qty,
- actual_qty: d.actual_qty,
+ actual_qty: me.actual_qty,
projected_qty: d.projected_qty,
rate: format_number(d.rate, me.frm.doc.currency),
amount: format_currency(d.amount, me.frm.doc.currency)
@@ -1064,8 +1076,18 @@
},
validate_warehouse: function(){
- if(!this.items[0].default_warehouse){
+ if(!this.items[0].default_warehouse && !this.pos_profile_data['warehouse']){
frappe.throw(__("Default warehouse is required for selected item"))
}
+ },
+
+ get_actual_qty: function(item) {
+ this.actual_qty = 0.0;
+ var warehouse = this.pos_profile_data['warehouse'] || item.default_warehouse;
+ if(warehouse && this.bin_data[item.item_code]) {
+ this.actual_qty = this.bin_data[item.item_code][warehouse] || 0;
+ }
+
+ return this.actual_qty
}
})
\ No newline at end of file
diff --git a/erpnext/docs/assets/img/buying/add_taxes_to_doc.png b/erpnext/docs/assets/img/buying/add_taxes_to_doc.png
new file mode 100644
index 0000000..3e1480d
--- /dev/null
+++ b/erpnext/docs/assets/img/buying/add_taxes_to_doc.png
Binary files differ
diff --git a/erpnext/docs/assets/img/buying/buying_flow.png b/erpnext/docs/assets/img/buying/buying_flow.png
new file mode 100644
index 0000000..7b3f256
--- /dev/null
+++ b/erpnext/docs/assets/img/buying/buying_flow.png
Binary files differ
diff --git a/erpnext/docs/assets/img/buying/show_tax_breakup.png b/erpnext/docs/assets/img/buying/show_tax_breakup.png
new file mode 100644
index 0000000..7348d51
--- /dev/null
+++ b/erpnext/docs/assets/img/buying/show_tax_breakup.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/buying/purchase-order.md b/erpnext/docs/user/manual/en/buying/purchase-order.md
index e7f2429..89bb6d9 100644
--- a/erpnext/docs/user/manual/en/buying/purchase-order.md
+++ b/erpnext/docs/user/manual/en/buying/purchase-order.md
@@ -7,7 +7,7 @@
#### Purchase Order Flow Chart
-![Purchase Order]({{docs_base_url}}/assets/old_images/erpnext/purchase-order-f.jpg)
+![Purchase Order]({{docs_base_url}}/assets/img/buying/buying_flow.png)
In ERPNext, you can also make a Purchase Order directly by going to:
@@ -39,6 +39,12 @@
government is only the difference between what you collect from your Customer
and what you pay to your Supplier. This is called Value Added Tax (VAT).
+#### Add Taxes in Purchase Order
+<img class="screenshot" alt="Purchase Order" src="{{docs_base_url}}/assets/img/buying/add_taxes_to_doc.png">
+
+#### Show Tax break-up
+<img class="screenshot" alt="Purchase Order" src="{{docs_base_url}}/assets/img/buying/show_tax_breakup.png">
+
For example you buy Items worth X and sell them for 1.3X. So your Customer
pays 1.3 times the tax you pay your Supplier. Since you have already paid tax
to your Supplier for X, what you owe your government is only the tax on 0.3X.
@@ -49,7 +55,7 @@
effect. Please contact your accountant if you need more help or post a query
on our forums!
-
+
#### Purchase UOM and Stock UOM Conversion
@@ -82,5 +88,5 @@
__Step 6:__ Save and Submit the Form.
-
+
{next}
diff --git a/erpnext/docs/user/manual/en/buying/supplier-quotation.md b/erpnext/docs/user/manual/en/buying/supplier-quotation.md
index 0f1d51a..868a297 100644
--- a/erpnext/docs/user/manual/en/buying/supplier-quotation.md
+++ b/erpnext/docs/user/manual/en/buying/supplier-quotation.md
@@ -8,7 +8,7 @@
#### Supplier Quotation Flow-Chart
-![Supplier Quotation]({{docs_base_url}}/assets/old_images/erpnext/supplier-quotation-f.jpg)
+![Supplier Quotation]({{docs_base_url}}/assets/img/buying/buying_flow.png)
You can also make a Supplier Quotation directly from:
@@ -23,11 +23,22 @@
many cases, especially if you have centralized buying, you may want to record
all the quotes so that
- * You can easily compare prices in the future
+ * You can easily compare prices in the future
* Audit whether all Suppliers were given the opportunity to quote.
Supplier Quotations are not necessary for most small businesses. Always
evaluate the cost of collecting information to the value it really provides!
You could only do this for high value items.
+#### Taxes
+If your Supplier is going to charge you additional taxes or charge like a shipping or insurance charge, you can add it here. It will help you to accurately track your costs. Also, if some of these charges add to the value of the product you will have to mention them in the Taxes table. You can also use templates for your taxes. For more information on setting up your taxes see the Purchase Taxes and Charges Template.
+
+You can select relevant tax by going to "Taxes and Charges" section and adding an entry to the table as shown below,
+
+<img class="screenshot" alt="Supplier Quotation" src="{{docs_base_url}}/assets/img/buying/add_taxes_to_doc.png">
+
+Besides, in case of multiple items you can keep track of taxes on each by clicking "Show tax break-up"
+
+<img class="screenshot" alt="Supplier Quotation" src="{{docs_base_url}}/assets/img/buying/show_tax_breakup.png">
+
{next}
diff --git a/erpnext/manufacturing/doctype/workstation/workstation.js b/erpnext/manufacturing/doctype/workstation/workstation.js
index 153d7e5..ba8e30c 100644
--- a/erpnext/manufacturing/doctype/workstation/workstation.js
+++ b/erpnext/manufacturing/doctype/workstation/workstation.js
@@ -1,17 +1,19 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-
-
-//--------- ONLOAD -------------
-cur_frm.cscript.onload = function(doc, cdt, cdn) {
- frappe.call({
- type:"GET",
- method:"erpnext.manufacturing.doctype.workstation.workstation.get_default_holiday_list",
- callback: function(r) {
- if(!r.exe && r.message){
- cur_frm.set_value("holiday_list", r.message);
- }
+frappe.ui.form.on("Workstation", {
+ onload: function(frm) {
+ if(frm.is_new())
+ {
+ frappe.call({
+ type:"GET",
+ method:"erpnext.manufacturing.doctype.workstation.workstation.get_default_holiday_list",
+ callback: function(r) {
+ if(!r.exe && r.message){
+ cur_frm.set_value("holiday_list", r.message);
+ }
+ }
+ })
}
- })
-}
+ }
+})
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/fix_duplicate_icons.py b/erpnext/patches/v7_0/fix_duplicate_icons.py
index 3e762f7..f6d227d 100644
--- a/erpnext/patches/v7_0/fix_duplicate_icons.py
+++ b/erpnext/patches/v7_0/fix_duplicate_icons.py
@@ -6,6 +6,8 @@
def execute():
'''hide new style icons if old ones are set'''
+ frappe.reload_doc('desk', 'doctype', 'desktop_icon')
+
reload_doctypes_for_schools_icons()
sync_desktop_icons()