Merge branch 'develop' of https://github.com/frappe/erpnext into so-on-hold

This commit is contained in:
Mangesh-Khairnar
2019-03-25 18:51:13 +05:30
361 changed files with 25568 additions and 7571 deletions

View File

@@ -6,7 +6,6 @@
</p> </p>
[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext) [![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext) [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
[![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop) [![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop)

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides from erpnext.hooks import regional_overrides
from frappe.utils import getdate from frappe.utils import getdate
__version__ = '11.1.13' __version__ = '11.1.16'
def get_default_company(user=None): def get_default_company(user=None):
'''Get default company for user''' '''Get default company for user'''

View File

@@ -632,6 +632,39 @@
"set_only_once": 0, "set_only_once": 0,
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
"fieldname": "include_in_gross",
"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": "Include in gross",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@@ -645,7 +678,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2019-01-07 16:52:02.557837", "modified": "2019-03-04 14:42:07.208893",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Account", "name": "Account",

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cint, cstr from frappe.utils import cint, cstr
from frappe import throw, _ from frappe import throw, _
from frappe.utils.nestedset import NestedSet from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of
class RootNotEditable(frappe.ValidationError): pass class RootNotEditable(frappe.ValidationError): pass
class BalanceMismatchError(frappe.ValidationError): pass class BalanceMismatchError(frappe.ValidationError): pass
@@ -41,6 +41,7 @@ class Account(NestedSet):
self.validate_frozen_accounts_modifier() self.validate_frozen_accounts_modifier()
self.validate_balance_must_be_debit_or_credit() self.validate_balance_must_be_debit_or_credit()
self.validate_account_currency() self.validate_account_currency()
self.validate_root_company_and_sync_account_to_children()
def validate_parent(self): def validate_parent(self):
"""Fetch Parent Details and validate parent account""" """Fetch Parent Details and validate parent account"""
@@ -90,6 +91,34 @@ class Account(NestedSet):
if not self.parent_account and not self.is_group: if not self.parent_account and not self.is_group:
frappe.throw(_("Root Account must be a group")) frappe.throw(_("Root Account must be a group"))
def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
return
ancestors = get_root_company(self.company)
if ancestors:
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
descendants = get_descendants_of('Company', self.company)
if not descendants: return
acc_name_map = {}
acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
for d in frappe.db.get_values('Account',
{"company": ["in", descendants], "account_name": acc_name},
["company", "name"], as_dict=True):
acc_name_map[d["company"]] = d["name"]
for company in descendants:
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True
doc.update({"company": company, "account_currency": None,
"parent": acc_name_map[company], "parent_account": acc_name_map[company]})
doc.save()
frappe.msgprint(_("Account {0} is added in the child company {1}")
.format(doc.name, company))
def validate_group_or_ledger(self): def validate_group_or_ledger(self):
if self.get("__islocal"): if self.get("__islocal"):
return return
@@ -250,3 +279,9 @@ def merge_account(old, new, is_group, root_type, company):
frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1) frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1)
return new return new
@frappe.whitelist()
def get_root_company(company):
# return the topmost company in the hierarchy
ancestors = get_ancestors_of('Company', company, "lft asc")
return [ancestors[0]] if ancestors else []

View File

@@ -4,13 +4,38 @@ frappe.treeview_settings["Account"] = {
breadcrumbs: "Accounts", breadcrumbs: "Accounts",
title: __("Chart Of Accounts"), title: __("Chart Of Accounts"),
get_tree_root: false, get_tree_root: false,
filters: [{ filters: [
fieldname: "company", {
fieldtype:"Select", fieldname: "company",
options: erpnext.utils.get_tree_options("company"), fieldtype:"Select",
label: __("Company"), options: erpnext.utils.get_tree_options("company"),
default: erpnext.utils.get_tree_default("company") label: __("Company"),
}], default: erpnext.utils.get_tree_default("company"),
on_change: function() {
var me = frappe.treeview_settings['Account'].treeview;
var company = me.page.fields_dict.company.get_value();
frappe.call({
method: "erpnext.accounts.doctype.account.account.get_root_company",
args: {
company: company,
},
callback: function(r) {
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
}
}
});
}
},
{
fieldname: "root_company",
fieldtype:"Data",
label: __("Root Company"),
hidden: true,
disable_onchange: true
}
],
root_label: "Accounts", root_label: "Accounts",
get_tree_nodes: 'erpnext.accounts.utils.get_children', get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_ac', add_tree_node: 'erpnext.accounts.utils.add_ac',
@@ -42,8 +67,8 @@ frappe.treeview_settings["Account"] = {
], ],
ignore_fields:["parent_account"], ignore_fields:["parent_account"],
onload: function(treeview) { onload: function(treeview) {
frappe.treeview_settings['Account'].page = {}; frappe.treeview_settings['Account'].treeview = {};
$.extend(frappe.treeview_settings['Account'].page, treeview.page); $.extend(frappe.treeview_settings['Account'].treeview, treeview);
function get_company() { function get_company() {
return treeview.page.fields_dict.company.get_value(); return treeview.page.fields_dict.company.get_value();
} }
@@ -78,6 +103,18 @@ frappe.treeview_settings["Account"] = {
} }
}, },
post_render: function(treeview) {
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(__("New"), function() {
let root_company = treeview.page.fields_dict.root_company.get_value();
if(root_company) {
frappe.throw(__("Please add the account to root level Company - ") + root_company);
} else {
treeview.new_node();
}
}, "octicon octicon-plus");
},
onrender: function(node) { onrender: function(node) {
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr"; var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
@@ -93,6 +130,19 @@ frappe.treeview_settings["Account"] = {
} }
}, },
toolbar: [ toolbar: [
{
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1 &&
!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() &&
node.expandable && !node.hide_add;
},
click: function() {
var me = frappe.treeview_settings['Account'].treeview;
me.new_node();
},
btnClass: "hidden-xs"
},
{ {
condition: function(node) { condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1 return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
@@ -103,7 +153,7 @@ frappe.treeview_settings["Account"] = {
"account": node.label, "account": node.label,
"from_date": frappe.sys_defaults.year_start_date, "from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date, "to_date": frappe.sys_defaults.year_end_date,
"company": frappe.treeview_settings['Account'].page.fields_dict.company.get_value() "company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
}; };
frappe.set_route("query-report", "General Ledger"); frappe.set_route("query-report", "General Ledger");
}, },

View File

@@ -9,8 +9,8 @@ from unidecode import unidecode
from six import iteritems from six import iteritems
from frappe.utils.nestedset import rebuild_tree from frappe.utils.nestedset import rebuild_tree
def create_charts(company, chart_template=None, existing_company=None): def create_charts(company, chart_template=None, existing_company=None, custom_chart=None):
chart = get_chart(chart_template, existing_company) chart = custom_chart or get_chart(chart_template, existing_company)
if chart: if chart:
accounts = [] accounts = []
@@ -40,7 +40,7 @@ def create_charts(company, chart_template=None, existing_company=None):
"report_type": report_type, "report_type": report_type,
"account_number": account_number, "account_number": account_number,
"account_type": child.get("account_type"), "account_type": child.get("account_type"),
"account_currency": frappe.db.get_value('Company', company, "default_currency"), "account_currency": child.get('account_currency') or frappe.db.get_value('Company', company, "default_currency"),
"tax_rate": child.get("tax_rate") "tax_rate": child.get("tax_rate")
}) })
@@ -207,9 +207,9 @@ def validate_bank_account(coa, bank_account):
return (bank_account in accounts) return (bank_account in accounts)
@frappe.whitelist() @frappe.whitelist()
def build_tree_from_json(chart_template): def build_tree_from_json(chart_template, chart_data=None):
''' get chart template from its folder and parse the json to be rendered as tree ''' ''' get chart template from its folder and parse the json to be rendered as tree '''
chart = get_chart(chart_template) chart = chart_data or get_chart(chart_template)
# if no template selected, return as it is # if no template selected, return as it is
if not chart: if not chart:

View File

@@ -97,6 +97,19 @@ class TestAccount(unittest.TestCase):
self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\ self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\
"Softwares - _TC", doc.is_group, doc.root_type, doc.company) "Softwares - _TC", doc.is_group, doc.root_type, doc.company)
def test_account_sync(self):
del frappe.local.flags["ignore_root_company_validation"]
acc = frappe.new_doc("Account")
acc.account_name = "Test Sync Account"
acc.parent_account = "Temporary Accounts - _TC3"
acc.company = "_Test Company 3"
acc.insert()
acc_tc_4 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 4"})
acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 5"})
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
def _make_test_records(verbose): def _make_test_records(verbose):
from frappe.test_runner import make_test_objects from frappe.test_runner import make_test_objects
@@ -129,6 +142,8 @@ def _make_test_records(verbose):
["_Test Write Off", "Indirect Expenses", 0, None, None], ["_Test Write Off", "Indirect Expenses", 0, None, None],
["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None], ["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None],
["_Test Account Sales", "Direct Income", 0, None, None],
# related to Account Inventory Integration # related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets", 0, None, None], ["_Test Account Stock In Hand", "Current Assets", 0, None, None],

View File

@@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 1, "allow_rename": 1,
@@ -290,7 +291,7 @@
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "IBAN", "label": "IBAN",
"length": 25, "length": 30,
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
@@ -669,7 +670,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-07-20 13:55:36.996465", "modified": "2019-03-05 17:56:05.103238",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Bank Account", "name": "Bank Account",

View File

@@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 0, "allow_rename": 0,
@@ -19,6 +20,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Cost Center", "default": "Cost Center",
"fetch_if_empty": 0,
"fieldname": "budget_against", "fieldname": "budget_against",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -52,6 +54,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -86,6 +89,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.budget_against == 'Cost Center'", "depends_on": "eval:doc.budget_against == 'Cost Center'",
"fetch_if_empty": 0,
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -120,6 +124,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.budget_against == 'Project'", "depends_on": "eval:doc.budget_against == 'Project'",
"fetch_if_empty": 0,
"fieldname": "project", "fieldname": "project",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -153,6 +158,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "fiscal_year", "fieldname": "fiscal_year",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -186,6 +192,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3", "fieldname": "column_break_3",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -218,6 +225,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)", "depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)",
"fetch_if_empty": 0,
"fieldname": "monthly_distribution", "fieldname": "monthly_distribution",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -251,6 +259,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from", "fieldname": "amended_from",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -283,6 +292,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_6", "fieldname": "section_break_6",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -315,6 +325,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_material_request", "fieldname": "applicable_on_material_request",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -343,12 +354,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Stop", "default": "Stop",
"depends_on": "eval:doc.applicable_on_material_request == 1", "depends_on": "eval:doc.applicable_on_material_request == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_mr", "fieldname": "action_if_annual_budget_exceeded_on_mr",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -378,12 +390,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Warn", "default": "Warn",
"depends_on": "eval:doc.applicable_on_material_request == 1", "depends_on": "eval:doc.applicable_on_material_request == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr", "fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -417,6 +430,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_13", "fieldname": "column_break_13",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -448,6 +462,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_purchase_order", "fieldname": "applicable_on_purchase_order",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -476,12 +491,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Stop", "default": "Stop",
"depends_on": "eval:doc.applicable_on_purchase_order == 1", "depends_on": "eval:doc.applicable_on_purchase_order == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_po", "fieldname": "action_if_annual_budget_exceeded_on_po",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -511,12 +527,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Warn", "default": "Warn",
"depends_on": "eval:doc.applicable_on_purchase_order == 1", "depends_on": "eval:doc.applicable_on_purchase_order == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po", "fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -550,6 +567,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_16", "fieldname": "section_break_16",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -581,6 +599,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_booking_actual_expenses", "fieldname": "applicable_on_booking_actual_expenses",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -609,12 +628,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Stop", "default": "Stop",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1", "depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded", "fieldname": "action_if_annual_budget_exceeded",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -644,12 +664,13 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 1,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Warn", "default": "Warn",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1", "depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded", "fieldname": "action_if_accumulated_monthly_budget_exceeded",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -683,6 +704,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_21", "fieldname": "section_break_21",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -715,6 +737,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "", "depends_on": "",
"fetch_if_empty": 0,
"fieldname": "accounts", "fieldname": "accounts",
"fieldtype": "Table", "fieldtype": "Table",
"hidden": 0, "hidden": 0,
@@ -752,7 +775,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-09-12 11:02:41.825923", "modified": "2019-03-22 12:06:02.323099",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Budget", "name": "Budget",

View File

@@ -0,0 +1,138 @@
frappe.ui.form.on('Chart of Accounts Importer', {
onload: function (frm) {
frm.set_value("company", "");
frm.set_value("import_file", "");
},
refresh: function (frm) {
// disable default save
frm.disable_save();
// make company mandatory
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
// Show import button when file is successfully attached
if (frm.page && frm.page.show_import_button) {
create_import_button(frm);
}
// show download template button when company is properly selected
if(frm.doc.company) {
// download the csv template file
frm.add_custom_button(__("Download template"), function () {
let get_template_url = 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template';
open_url_post(frappe.request.url, { cmd: get_template_url, doctype: frm.doc.doctype });
});
} else {
frm.set_value("import_file", "");
}
},
import_file: function (frm) {
if (!frm.doc.import_file) {
frm.page.set_indicator("");
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
} else {
generate_tree_preview(frm);
validate_csv_data(frm);
}
},
company: function (frm) {
// validate that no Gl Entry record for the company exists.
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
args: {
company: frm.doc.company
},
callback: function(r) {
if(r.message===false) {
frm.set_value("company", "");
frappe.throw(__("Transactions against the company already exist! "));
} else {
frm.trigger("refresh");
}
}
});
}
});
var validate_csv_data = function(frm) {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_accounts",
args: {file_name: frm.doc.import_file},
callback: function(r) {
if(r.message && r.message[0]===true) {
frm.page["show_import_button"] = true;
frm.page["total_accounts"] = r.message[1];
frm.trigger("refresh");
} else {
frm.page.set_indicator(__('Resolve error and upload again.'), 'orange');
frappe.throw(__(r.message));
}
}
});
};
var create_import_button = function(frm) {
frm.page.set_primary_action(__("Start Import"), function () {
setup_progress_bar(frm);
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
company: frm.doc.company
},
freeze: true,
callback: function(r) {
if(!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successfull'), 'blue');
frappe.hide_progress();
create_reset_button(frm);
}
}
});
}).addClass('btn btn-primary');
};
var create_reset_button = function(frm) {
frm.page.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
}).addClass('btn btn-primary');
};
var generate_tree_preview = function(frm) {
let parent = __('All Accounts');
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
// generate tree structure based on the csv data
new frappe.ui.Tree({
parent: $(frm.fields_dict['chart_tree'].wrapper),
label: parent,
expandable: true,
method: 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: 'Chart of Accounts Importer'
},
onclick: function(node) {
parent = node.value;
}
});
};
var setup_progress_bar = function(frm) {
frm.page["seconds_elapsed"] = 0;
frm.page["execution_time"] = (frm.page["total_accounts"] > 100) ? 100 : frm.page["total_accounts"];
frm.page["interval"] = setInterval(function() {
frm.page["seconds_elapsed"] += 1;
frappe.show_progress(__('Creating Accounts'), frm.page["seconds_elapsed"], frm.page["execution_time"]);
}, 250);
};

View File

@@ -0,0 +1,226 @@
{
"allow_copy": 1,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-02-01 12:24:34.761380",
"custom": 0,
"description": "Import Chart of Accounts from a csv file",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "import_file_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,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "import_file",
"fieldtype": "Attach",
"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": "Attach custom Chart of Accounts file",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "chart_preview",
"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": "Chart Preview",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "chart_tree",
"fieldtype": "HTML",
"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": "Chart Tree",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 1,
"hide_toolbar": 1,
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2019-02-04 23:10:30.136807",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Chart of Accounts Importer",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,199 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe, csv
from frappe import _
from frappe.utils import cstr
from frappe.model.document import Document
from frappe.utils.csvutils import UnicodeWriter
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts, build_tree_from_json
class ChartofAccountsImporter(Document):
pass
@frappe.whitelist()
def validate_company(company):
if frappe.db.get_all('GL Entry', {"company": company}, "name", limit=1):
return False
@frappe.whitelist()
def import_coa(file_name, company):
# delete existing data for accounts
unset_existing_data(company)
# create accounts
forest = build_forest(generate_data_from_csv(file_name))
create_charts(company, custom_chart=forest)
# trigger on_update for company to reset default accounts
set_default_accounts(company)
def generate_data_from_csv(file_name, as_dict=False):
''' read csv file and return the generated nested tree '''
file_doc = frappe.get_doc('File', {"file_url": file_name})
file_path = file_doc.get_full_path()
data = []
with open(file_path, 'r') as in_file:
csv_reader = list(csv.reader(in_file))
headers = csv_reader[1][1:]
del csv_reader[0:2] # delete top row and headers row
for row in csv_reader:
if as_dict:
data.append({frappe.scrub(header): row[index+1] for index, header in enumerate(headers)})
else:
if not row[2]: row[2] = row[1]
data.append(row[1:])
# convert csv data
return data
@frappe.whitelist()
def get_coa(doctype, parent, is_root=False, file_name=None):
''' called by tree view (to fetch node's children) '''
parent = None if parent==_('All Accounts') else parent
forest = build_forest(generate_data_from_csv(file_name))
accounts = build_tree_from_json("", chart_data=forest) # returns alist of dict in a tree render-able form
# filter out to show data for the selected node only
accounts = [d for d in accounts if d['parent_account']==parent]
return accounts
def build_forest(data):
'''
converts list of list into a nested tree
if a = [[1,1], [1,2], [3,2], [4,4], [5,4]]
tree = {
1: {
2: {
3: {}
}
},
4: {
5: {}
}
}
'''
# set the value of nested dictionary
def set_nested(d, path, value):
reduce(lambda d, k: d.setdefault(k, {}), path[:-1], d)[path[-1]] = value
return d
# returns the path of any node in list format
def return_parent(data, child):
for row in data:
account_name, parent_account = row[0:2]
if parent_account == account_name == child:
return [parent_account]
elif account_name == child:
return [child] + return_parent(data, parent_account)
charts_map, paths = {}, []
for i in data:
account_name, _, account_number, is_group, account_type, root_type = i
charts_map[account_name] = {}
if is_group: charts_map[account_name]["is_group"] = is_group
if account_type: charts_map[account_name]["account_type"] = account_type
if root_type: charts_map[account_name]["root_type"] = root_type
if account_number: charts_map[account_name]["account_number"] = account_number
path = return_parent(data, account_name)[::-1]
paths.append(path) # List of path is created
out = {}
for path in paths:
for n, account_name in enumerate(path):
set_nested(out, path[:n+1], charts_map[account_name]) # setting the value of nested dictionary.
return out
@frappe.whitelist()
def download_template():
data = frappe._dict(frappe.local.form_dict)
fields = ["Account Name", "Parent Account", "Account Number", "Is Group", "Account Type", "Root Type"]
writer = UnicodeWriter()
writer.writerow([_('Chart of Accounts Template')])
writer.writerow([_("Column Labels : ")] + fields)
writer.writerow([_("Start entering data from here : ")])
# download csv file
frappe.response['result'] = cstr(writer.getvalue())
frappe.response['type'] = 'csv'
frappe.response['doctype'] = data.get('doctype')
@frappe.whitelist()
def validate_accounts(file_name):
accounts = generate_data_from_csv(file_name, as_dict=True)
accounts_dict = {}
for account in accounts:
accounts_dict.setdefault(account["account_name"], account)
if account["parent_account"] and accounts_dict[account["parent_account"]]:
accounts_dict[account["parent_account"]]["is_group"] = 1
message = validate_root(accounts_dict)
if message: return message
message = validate_account_types(accounts_dict)
if message: return message
return [True, len(accounts)]
def validate_root(accounts):
roots = [accounts[d] for d in accounts if not accounts[d].get('parent_account')]
if len(roots) < 4:
return _("Number of root accounts cannot be less than 4")
for account in roots:
if not account.get("root_type"):
return _("Please enter Root Type for - {0}").format(account.get("account_name"))
elif account.get("root_type") not in ("Asset", "Liability", "Expense", "Income", "Equity"):
return _('Root Type for "{0}" must be one of the Asset, Liability, Income, Expense and Equity').format(account.get("account_name"))
def validate_account_types(accounts):
account_types_for_ledger = ["Cost of Goods Sold", "Depreciation", "Fixed Asset", "Payable", "Receivable", "Stock Adjustment"]
account_types = [accounts[d]["account_type"] for d in accounts if not accounts[d]['is_group']]
missing = list(set(account_types_for_ledger) - set(account_types))
if missing:
return _("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing))
account_types_for_group = ["Bank", "Cash", "Stock"]
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group']]
missing = list(set(account_types_for_group) - set(account_groups))
if missing:
return _("Please identify/create Account (Group) for type - {0}").format(' , '.join(missing))
def unset_existing_data(company):
linked = frappe.db.sql('''select fieldname from tabDocField
where fieldtype="Link" and options="Account" and parent="Company"''', as_dict=True)
# remove accounts data from company
update_values = {d.fieldname: '' for d in linked}
frappe.db.set_value('Company', company, update_values, update_values)
# remove accounts data from various doctypes
for doctype in ["Account", "Party Account", "Mode of Payment Account", "Tax Withholding Account",
"Sales Taxes and Charges Template", "Purchase Taxes and Charges Template"]:
frappe.db.sql('''delete from `tab{0}` where `company`="%s"''' # nosec
.format(doctype) % (company))
def set_default_accounts(company):
from erpnext.setup.doctype.company.company import install_country_fixtures
company = frappe.get_doc('Company', company)
company.update({
"default_receivable_account": frappe.db.get_value("Account",
{"company": company.name, "account_type": "Receivable", "is_group": 0}),
"default_payable_account": frappe.db.get_value("Account",
{"company": company.name, "account_type": "Payable", "is_group": 0})
})
company.save()
install_country_fixtures(company.name)
company.create_default_tax_template()

View File

@@ -2,15 +2,15 @@
// rename this file from _test_[name] to test_[name] to activate // rename this file from _test_[name] to test_[name] to activate
// and remove above this line // and remove above this line
QUnit.test("test: Issue", function (assert) { QUnit.test("test: Chart of Accounts Importer", function (assert) {
let done = assert.async(); let done = assert.async();
// number of asserts // number of asserts
assert.expect(1); assert.expect(1);
frappe.run_serially([ frappe.run_serially([
// insert a new Issue // insert a new Chart of Accounts Importer
() => frappe.tests.make('Issue', [ () => frappe.tests.make('Chart of Accounts Importer', [
// values to be set // values to be set
{key: 'value'} {key: 'value'}
]), ]),

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestChartofAccountsImporter(unittest.TestCase):
pass

View File

@@ -81,7 +81,8 @@ class GLEntry(Document):
def check_pl_account(self): def check_pl_account(self):
if self.is_opening=='Yes' and \ if self.is_opening=='Yes' and \
frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss": frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \
self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']:
frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry") frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry")
.format(self.voucher_type, self.voucher_no, self.account)) .format(self.voucher_type, self.voucher_no, self.account))

View File

@@ -52,6 +52,12 @@ class JournalEntry(AccountsController):
self.update_loan() self.update_loan()
self.update_inter_company_jv() self.update_inter_company_jv()
def before_print(self):
self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Journal Entry",
"voucher_no": self.name} ,
fields=["account", "party_type", "party", "debit", "credit", "remarks"]
)
def get_title(self): def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account return self.pay_to_recd_from or self.accounts[0].account

View File

@@ -150,7 +150,7 @@ class TestLoyaltyProgram(unittest.TestCase):
company_wise_info = get_dashboard_info("Customer", doc.name, doc.loyalty_program) company_wise_info = get_dashboard_info("Customer", doc.name, doc.loyalty_program)
for d in company_wise_info: for d in company_wise_info:
self.assertTrue(d.loyalty_points) self.assertTrue(d.get("loyalty_points"))
def get_points_earned(self): def get_points_earned(self):
def get_returned_amount(): def get_returned_amount():

View File

@@ -70,6 +70,12 @@ class PaymentEntry(AccountsController):
self.update_advance_paid() self.update_advance_paid()
self.update_expense_claim() self.update_expense_claim()
def before_print(self):
self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Payment Entry",
"voucher_no": self.name} ,
fields=["account", "party_type", "party", "debit", "credit", "remarks"]
)
def on_cancel(self): def on_cancel(self):
self.setup_party_account_field() self.setup_party_account_field()
self.make_gl_entries(cancel=1) self.make_gl_entries(cancel=1)

View File

@@ -214,9 +214,10 @@ class PaymentRequest(Document):
def check_if_payment_entry_exists(self): def check_if_payment_entry_exists(self):
if self.status == "Paid": if self.status == "Paid":
payment_entry = frappe.db.sql_list("""select parent from `tabPayment Entry Reference` if frappe.get_all("Payment Entry Reference",
where reference_name=%s""", self.reference_name) filters={"reference_name": self.reference_name, "docstatus": ["<", 2]},
if payment_entry: fields=["parent"],
limit=1):
frappe.throw(_("Payment Entry already exists"), title=_('Error')) frappe.throw(_("Payment Entry already exists"), title=_('Error'))
def make_communication_entry(self): def make_communication_entry(self):

View File

@@ -32,7 +32,7 @@ class PaymentTermsTemplate(Document):
def check_duplicate_terms(self): def check_duplicate_terms(self):
terms = [] terms = []
for term in self.terms: for term in self.terms:
term_info = (term.credit_days, term.due_date_based_on) term_info = (term.credit_days, term.credit_months, term.due_date_based_on)
if term_info in terms: if term_info in terms:
frappe.msgprint( frappe.msgprint(
_('The Payment Term at row {0} is possibly a duplicate.').format(term.idx), _('The Payment Term at row {0} is possibly a duplicate.').format(term.idx),

View File

@@ -33,6 +33,14 @@ frappe.ui.form.on('POS Profile', {
}; };
}); });
frm.set_query("account_for_change_amount", function() {
return {
filters: {
account_type: ['in', ["Cash", "Bank"]]
}
};
});
frm.set_query("print_format", function() { frm.set_query("print_format", function() {
return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} }; return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} };
}); });

View File

@@ -114,6 +114,16 @@ frappe.ui.form.on('Pricing Rule', {
} }
}; };
}; };
['items', 'item_groups', 'brands'].forEach(d => {
frm.fields_dict[d].grid.get_field('uom').get_query = function(doc, cdt, cdn){
var row = locals[cdt][cdn];
return {
query:"erpnext.accounts.doctype.pricing_rule.pricing_rule.get_item_uoms",
filters: {'value': row[frappe.scrub(doc.apply_on)], apply_on: doc.apply_on}
}
};
})
}, },
onload: function(frm) { onload: function(frm) {
@@ -191,6 +201,24 @@ frappe.ui.form.on('Pricing Rule', {
set_field_options("pricing_rule_help", help_content); set_field_options("pricing_rule_help", help_content);
frm.events.set_options_for_applicable_for(frm); frm.events.set_options_for_applicable_for(frm);
frm.trigger("toggle_reqd_apply_on");
},
apply_on: function(frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
}
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
}
}, },
rate_or_discount: function(frm) { rate_or_discount: function(frm) {
@@ -220,7 +248,7 @@ frappe.ui.form.on('Pricing Rule', {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]); options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
} }
if(frm.doc.buying) { if(frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Type"]); $.merge(options, ["Supplier", "Supplier Group"]);
} }
set_field_options("applicable_for", options.join("\n")); set_field_options("applicable_for", options.join("\n"));

File diff suppressed because it is too large Load Diff

View File

@@ -8,30 +8,45 @@ import frappe
import json import json
import copy import copy
from frappe import throw, _ from frappe import throw, _
from frappe.utils import flt, cint from frappe.utils import flt, cint, getdate
from frappe.model.document import Document from frappe.model.document import Document
from six import string_types from six import string_types
class MultiplePricingRuleConflict(frappe.ValidationError): pass apply_on_dict = {"Item Code": "items",
"Item Group": "item_groups", "Brand": "brands"}
class PricingRule(Document): class PricingRule(Document):
def validate(self): def validate(self):
self.validate_mandatory() self.validate_mandatory()
self.validate_duplicate_apply_on()
self.validate_applicable_for_selling_or_buying() self.validate_applicable_for_selling_or_buying()
self.validate_min_max_amt()
self.validate_min_max_qty() self.validate_min_max_qty()
self.cleanup_fields_value() self.cleanup_fields_value()
self.validate_rate_or_discount() self.validate_rate_or_discount()
self.validate_max_discount() self.validate_max_discount()
self.validate_price_list_with_currency() self.validate_price_list_with_currency()
self.validate_dates()
if not self.margin_type: self.margin_rate_or_amount = 0.0 if not self.margin_type: self.margin_rate_or_amount = 0.0
def validate_duplicate_apply_on(self):
field = apply_on_dict.get(self.apply_on)
values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field)]
if len(values) != len(set(values)):
frappe.throw(_("Duplicate {0} found in the table").format(self.apply_on))
def validate_mandatory(self): def validate_mandatory(self):
for field in ["apply_on", "applicable_for"]: for apply_on, field in apply_on_dict.items():
tocheck = frappe.scrub(self.get(field) or "") if self.apply_on == apply_on and len(self.get(field) or []) < 1:
if tocheck and not self.get(tocheck): throw(_("{0} is not added in the table").format(apply_on), frappe.MandatoryError)
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
tocheck = frappe.scrub(self.get("applicable_for", ""))
if tocheck and not self.get(tocheck):
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
def validate_applicable_for_selling_or_buying(self): def validate_applicable_for_selling_or_buying(self):
if not self.selling and not self.buying: if not self.selling and not self.buying:
@@ -50,6 +65,10 @@ class PricingRule(Document):
if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty): if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
throw(_("Min Qty can not be greater than Max Qty")) throw(_("Min Qty can not be greater than Max Qty"))
def validate_min_max_amt(self):
if self.min_amt and self.max_amt and flt(self.min_amt) > flt(self.max_amt):
throw(_("Min Amt can not be greater than Max Amt"))
def cleanup_fields_value(self): def cleanup_fields_value(self):
for logic_field in ["apply_on", "applicable_for", "rate_or_discount"]: for logic_field in ["apply_on", "applicable_for", "rate_or_discount"]:
fieldname = frappe.scrub(self.get(logic_field) or "") fieldname = frappe.scrub(self.get(logic_field) or "")
@@ -63,16 +82,26 @@ class PricingRule(Document):
if f!=fieldname: if f!=fieldname:
self.set(f, None) self.set(f, None)
if self.mixed_conditions and self.get("same_item"):
self.same_item = 0
def validate_rate_or_discount(self): def validate_rate_or_discount(self):
for field in ["Rate"]: for field in ["Rate"]:
if flt(self.get(frappe.scrub(field))) < 0: if flt(self.get(frappe.scrub(field))) < 0:
throw(_("{0} can not be negative").format(field)) throw(_("{0} can not be negative").format(field))
if self.price_or_product_discount == 'Product' and not self.free_item:
if self.mixed_conditions:
frappe.throw(_("Free item code is not selected"))
else:
self.same_item = 1
def validate_max_discount(self): def validate_max_discount(self):
if self.rate_or_discount == "Discount Percentage" and self.item_code: if self.rate_or_discount == "Discount Percentage" and self.items:
max_discount = frappe.get_cached_value("Item", self.item_code, "max_discount") for d in self.items:
if max_discount and flt(self.discount_percentage) > flt(max_discount): max_discount = frappe.get_cached_value("Item", d.item_code, "max_discount")
throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount)) if max_discount and flt(self.discount_percentage) > flt(max_discount):
throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount))
def validate_price_list_with_currency(self): def validate_price_list_with_currency(self):
if self.currency and self.for_price_list: if self.currency and self.for_price_list:
@@ -80,6 +109,13 @@ class PricingRule(Document):
if not self.currency == price_list_currency: if not self.currency == price_list_currency:
throw(_("Currency should be same as Price List Currency: {0}").format(price_list_currency)) throw(_("Currency should be same as Price List Currency: {0}").format(price_list_currency))
def validate_dates(self):
if self.is_cumulative and not (self.valid_from and self.valid_upto):
frappe.throw(_("Valid from and valid upto fields are mandatory for the cumulative"))
if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto):
frappe.throw(_("Valid from date must be less than valid upto date"))
#-------------------------------------------------------------------------------- #--------------------------------------------------------------------------------
@frappe.whitelist() @frappe.whitelist()
@@ -125,7 +161,8 @@ def apply_pricing_rule(args):
for item in item_list: for item in item_list:
args_copy = copy.deepcopy(args) args_copy = copy.deepcopy(args)
args_copy.update(item) args_copy.update(item)
out.append(get_pricing_rule_for_item(args_copy)) data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'))
out.append(data)
if set_serial_nos_based_on_fifo and not args.get('is_return'): if set_serial_nos_based_on_fifo and not args.get('is_return'):
out.append(get_serial_no_for_item(args_copy)) out.append(get_serial_no_for_item(args_copy))
return out return out
@@ -142,18 +179,26 @@ def get_serial_no_for_item(args):
item_details.serial_no = get_serial_no(args) item_details.serial_no = get_serial_no(args)
return item_details return item_details
def get_pricing_rule_for_item(args): def get_pricing_rule_for_item(args, price_list_rate=0, doc=None):
if args.get("parenttype") == "Material Request": return {} from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rules
if (args.get('is_free_item') or
args.get("parenttype") == "Material Request"): return {}
item_details = frappe._dict({ item_details = frappe._dict({
"doctype": args.doctype, "doctype": args.doctype,
"name": args.name, "name": args.name,
"pricing_rule": None "parent": args.parent,
"parenttype": args.parenttype,
"child_docname": args.get('child_docname'),
"discount_percentage_on_rate": [],
"discount_amount_on_rate": []
}) })
if args.ignore_pricing_rule or not args.item_code: if args.ignore_pricing_rule or not args.item_code:
if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rule"): if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rules"):
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details) item_details = remove_pricing_rule_for_item(args.get("pricing_rules"),
item_details, args.get('item_code'))
return item_details return item_details
if not (args.item_group and args.brand): if not (args.item_group and args.brand):
@@ -177,50 +222,113 @@ def get_pricing_rule_for_item(args):
args.supplier_group = frappe.get_cached_value("Supplier", args.supplier, "supplier_group") args.supplier_group = frappe.get_cached_value("Supplier", args.supplier, "supplier_group")
args.customer = args.customer_group = args.territory = None args.customer = args.customer_group = args.territory = None
pricing_rules = get_pricing_rules(args) pricing_rules = get_pricing_rules(args, doc)
pricing_rule = filter_pricing_rules(args, pricing_rules)
if pricing_rule: if pricing_rules:
item_details.pricing_rule = pricing_rule.name rules = []
item_details.pricing_rule_for = pricing_rule.rate_or_discount
if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)\ item_details.discount_percentage = 0
or (pricing_rule.margin_type == 'Percentage'): item_details.discount_amount = 0
item_details.margin_type = pricing_rule.margin_type for pricing_rule in pricing_rules:
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount if not pricing_rule or pricing_rule.get('suggestion'): continue
else:
item_details.margin_type = None
item_details.margin_rate_or_amount = 0.0
if pricing_rule.rate_or_discount == 'Rate': rules.append(get_pricing_rule_details(args, pricing_rule))
pricing_rule_rate = 0.0 if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other:
if pricing_rule.currency == args.currency: continue
pricing_rule_rate = pricing_rule.rate
item_details.update({ if (not pricing_rule.validate_applied_rule and
"price_list_rate": pricing_rule_rate * args.get("conversion_factor"), pricing_rule.price_or_product_discount == "Price"):
"discount_percentage": 0.0 apply_price_discount_pricing_rule(pricing_rule, item_details, args)
})
else: item_details.has_pricing_rule = 1
item_details.discount_percentage = (pricing_rule.get('discount_percentage', 0)
if pricing_rule else args.discount_percentage) # if discount is applied on the rate and not on price list rate
elif args.get('pricing_rule'): if price_list_rate:
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details) set_discount_amount(price_list_rate, item_details)
item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
if not doc: return item_details
for rule in rules:
doc.append('pricing_rules', rule)
elif args.get("pricing_rules"):
item_details = remove_pricing_rule_for_item(args.get("pricing_rules"),
item_details, args.get('item_code'))
return item_details return item_details
def remove_pricing_rule_for_item(pricing_rule, item_details): def get_pricing_rule_details(args, pricing_rule):
pricing_rule = frappe.get_cached_value('Pricing Rule', pricing_rule, return frappe._dict({
['price_or_discount', 'margin_type'], as_dict=1) 'pricing_rule': pricing_rule.name,
if pricing_rule and pricing_rule.price_or_discount == 'Discount Percentage': 'rate_or_discount': pricing_rule.rate_or_discount,
item_details.discount_percentage = 0.0 'margin_type': pricing_rule.margin_type,
'item_code': pricing_rule.item_code,
'child_docname': args.get('child_docname')
})
if pricing_rule and pricing_rule.margin_type in ['Percentage', 'Amount']: def apply_price_discount_pricing_rule(pricing_rule, item_details, args):
item_details.margin_rate_or_amount = 0.0 item_details.pricing_rule_for = pricing_rule.rate_or_discount
if ((pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)
or (pricing_rule.margin_type == 'Percentage')):
item_details.margin_type = pricing_rule.margin_type
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
else:
item_details.margin_type = None item_details.margin_type = None
item_details.margin_rate_or_amount = 0.0
if pricing_rule.rate_or_discount == 'Rate':
pricing_rule_rate = 0.0
if pricing_rule.currency == args.currency:
pricing_rule_rate = pricing_rule.rate
item_details.update({
"price_list_rate": pricing_rule_rate * args.get("conversion_factor", 1),
"discount_percentage": 0.0
})
for apply_on in ['Discount Amount', 'Discount Percentage']:
if pricing_rule.rate_or_discount != apply_on: continue
field = frappe.scrub(apply_on)
if pricing_rule.apply_discount_on_rate:
discount_field = "{0}_on_rate".format(field)
item_details[discount_field].append(pricing_rule.get(field, 0))
else:
item_details[field] += (pricing_rule.get(field, 0)
if pricing_rule else args.get(field, 0))
def set_discount_amount(rate, item_details):
for field in ['discount_percentage_on_rate', 'discount_amount_on_rate']:
for d in item_details.get(field):
dis_amount = (rate * d / 100
if field == 'discount_percentage_on_rate' else d)
rate -= dis_amount
item_details.rate = rate
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
for d in pricing_rules.split(','):
if not d: continue
pricing_rule = frappe.get_doc('Pricing Rule', d)
if pricing_rule.price_or_product_discount == 'Price':
if pricing_rule.rate_or_discount == 'Discount Percentage':
item_details.discount_percentage = 0.0
item_details.discount_amount = 0.0
if pricing_rule.rate_or_discount == 'Discount Amount':
item_details.discount_amount = 0.0
if pricing_rule.margin_type in ['Percentage', 'Amount']:
item_details.margin_rate_or_amount = 0.0
item_details.margin_type = None
elif pricing_rule.get('free_item'):
item_details.remove_free_item = (item_code if pricing_rule.get('same_item')
else pricing_rule.get('free_item'))
item_details.pricing_rules = ''
if item_details.pricing_rule:
item_details.pricing_rule = None
return item_details return item_details
@frappe.whitelist() @frappe.whitelist()
@@ -231,150 +339,12 @@ def remove_pricing_rules(item_list):
out = [] out = []
for item in item_list: for item in item_list:
item = frappe._dict(item) item = frappe._dict(item)
out.append(remove_pricing_rule_for_item(item.get("pricing_rule"), item)) if item.get('pricing_rules'):
out.append(remove_pricing_rule_for_item(item.get("pricing_rules"),
item, item.item_code))
return out return out
def get_pricing_rules(args):
def _get_tree_conditions(parenttype, allow_blank=True):
field = frappe.scrub(parenttype)
condition = ""
if args.get(field):
if not frappe.flags.tree_conditions:
frappe.flags.tree_conditions = {}
key = (parenttype, args[field], )
if key in frappe.flags.tree_conditions:
return frappe.flags.tree_conditions[key]
try:
lft, rgt = frappe.db.get_value(parenttype, args[field], ["lft", "rgt"])
except TypeError:
frappe.throw(_("Invalid {0}").format(args[field]))
parent_groups = frappe.db.sql_list("""select name from `tab%s`
where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt))
if parent_groups:
if allow_blank: parent_groups.append('')
condition = "ifnull({field}, '') in ({parent_groups})".format(
field=field,
parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups])
)
frappe.flags.tree_conditions[key] = condition
return condition
conditions = item_variant_condition = ""
values = {"item_code": args.get("item_code"), "brand": args.get("brand")}
for field in ["company", "customer", "supplier", "supplier_group", "campaign", "sales_partner"]:
if args.get(field):
conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
values[field] = args.get(field)
else:
conditions += " and ifnull("+field+", '') = ''"
for parenttype in ["Customer Group", "Territory"]:
group_condition = _get_tree_conditions(parenttype)
if group_condition:
conditions += " and " + group_condition
if not args.price_list: args.price_list = None
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
values["price_list"] = args.get("price_list")
if args.get("transaction_date"):
conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
and ifnull(valid_upto, '2500-12-31')"""
values['transaction_date'] = args.get('transaction_date')
item_group_condition = _get_tree_conditions("Item Group", False)
if item_group_condition:
item_group_condition = " or " + item_group_condition
# load variant of if not defined
if "variant_of" not in args:
args.variant_of = frappe.get_cached_value("Item", args.item_code, "variant_of")
if args.variant_of:
item_variant_condition = ' or item_code=%(variant_of)s '
values['variant_of'] = args.variant_of
return frappe.db.sql("""select * from `tabPricing Rule`
where (item_code=%(item_code)s {item_variant_condition} {item_group_condition} or brand=%(brand)s)
and docstatus < 2 and disable = 0
and {transaction_type} = 1 {conditions}
order by priority desc, name desc""".format(
item_group_condition = item_group_condition,
item_variant_condition = item_variant_condition,
transaction_type = args.transaction_type,
conditions = conditions), values, as_dict=1)
def filter_pricing_rules(args, pricing_rules):
# filter for qty
if pricing_rules:
stock_qty = flt(args.get('qty')) * args.get('conversion_factor', 1)
pricing_rules = list(filter(lambda x: (flt(stock_qty)>=flt(x.min_qty)
and (flt(stock_qty)<=x.max_qty if x.max_qty else True)), pricing_rules))
# add variant_of property in pricing rule
for p in pricing_rules:
if p.item_code and args.variant_of:
p.variant_of = args.variant_of
else:
p.variant_of = None
# find pricing rule with highest priority
if pricing_rules:
max_priority = max([cint(p.priority) for p in pricing_rules])
if max_priority:
pricing_rules = list(filter(lambda x: cint(x.priority)==max_priority, pricing_rules))
# apply internal priority
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
"supplier", "supplier_group", "campaign", "sales_partner", "variant_of"]
if len(pricing_rules) > 1:
for field_set in [["item_code", "variant_of", "item_group", "brand"],
["customer", "customer_group", "territory"], ["supplier", "supplier_group"]]:
remaining_fields = list(set(all_fields) - set(field_set))
if if_all_rules_same(pricing_rules, remaining_fields):
pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
break
if len(pricing_rules) > 1:
rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules]))
if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage":
pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \
or pricing_rules
if len(pricing_rules) > 1 and not args.for_shopping_cart:
frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}")
.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict)
elif pricing_rules:
return pricing_rules[0]
def if_all_rules_same(pricing_rules, fields):
all_rules_same = True
val = [pricing_rules[0][k] for k in fields]
for p in pricing_rules[1:]:
if val != [p[k] for k in fields]:
all_rules_same = False
break
return all_rules_same
def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args.get(field):
filtered_rules = list(filter(lambda x: x[field]==args[field], pricing_rules))
if filtered_rules: break
return filtered_rules or pricing_rules
def set_transaction_type(args): def set_transaction_type(args):
if args.transaction_type: if args.transaction_type:
return return
@@ -397,3 +367,44 @@ def make_pricing_rule(doctype, docname):
doc.buying = 1 if doctype == "Supplier" else 0 doc.buying = 1 if doctype == "Supplier" else 0
return doc return doc
@frappe.whitelist()
def get_free_items(pricing_rules, item_row):
if isinstance(item_row, string_types):
item_row = json.loads(item_row)
free_items = []
pricing_rules = list(set(pricing_rules.split(',')))
for d in pricing_rules:
pr_doc = frappe.get_doc('Pricing Rule', d)
if pr_doc.price_or_product_discount == 'Product':
item = (item_row.get('item_code') if pr_doc.same_item
else pr_doc.free_item)
if not item: return free_items
doc = frappe.get_doc('Item', item)
free_items.append({
'item_code': item,
'item_name': doc.item_name,
'description': doc.description,
'qty': pr_doc.free_qty,
'uom': pr_doc.free_item_uom,
'rate': pr_doc.free_item_rate or 0,
'is_free_item': 1
})
return free_items
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
items = [filters.get('value')]
if filters.get('apply_on') != 'Item Code':
field = frappe.scrub(filters.get('apply_on'))
items = frappe.db.sql_list("""select name
from `tabItem` where {0} = %s""".format(field), filters.get('value'))
return frappe.get_all('UOM Conversion Detail',
filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
fields = ["distinct uom"], as_list=1)

View File

@@ -12,10 +12,10 @@ from frappe import MandatoryError
class TestPricingRule(unittest.TestCase): class TestPricingRule(unittest.TestCase):
def setUp(self): def setUp(self):
frappe.db.sql("delete from `tabPricing Rule`") delete_existing_pricing_rules()
def tearDown(self): def tearDown(self):
frappe.db.sql("delete from `tabPricing Rule`") delete_existing_pricing_rules()
def test_pricing_rule_for_discount(self): def test_pricing_rule_for_discount(self):
from erpnext.stock.get_item_details import get_item_details from erpnext.stock.get_item_details import get_item_details
@@ -25,7 +25,9 @@ class TestPricingRule(unittest.TestCase):
"doctype": "Pricing Rule", "doctype": "Pricing Rule",
"title": "_Test Pricing Rule", "title": "_Test Pricing Rule",
"apply_on": "Item Code", "apply_on": "Item Code",
"item_code": "_Test Item", "items": [{
"item_code": "_Test Item"
}],
"currency": "USD", "currency": "USD",
"selling": 1, "selling": 1,
"rate_or_discount": "Discount Percentage", "rate_or_discount": "Discount Percentage",
@@ -64,7 +66,10 @@ class TestPricingRule(unittest.TestCase):
prule = frappe.get_doc(test_record.copy()) prule = frappe.get_doc(test_record.copy())
prule.apply_on = "Item Group" prule.apply_on = "Item Group"
prule.item_group = "All Item Groups" prule.items = []
prule.append('item_groups', {
'item_group': "All Item Groups"
})
prule.title = "_Test Pricing Rule for Item Group" prule.title = "_Test Pricing Rule for Item Group"
prule.discount_percentage = 15 prule.discount_percentage = 15
prule.insert() prule.insert()
@@ -86,7 +91,7 @@ class TestPricingRule(unittest.TestCase):
self.assertEqual(details.get("discount_percentage"), 5) self.assertEqual(details.get("discount_percentage"), 5)
frappe.db.sql("update `tabPricing Rule` set priority=NULL where campaign='_Test Campaign'") frappe.db.sql("update `tabPricing Rule` set priority=NULL where campaign='_Test Campaign'")
from erpnext.accounts.doctype.pricing_rule.pricing_rule import MultiplePricingRuleConflict from erpnext.accounts.doctype.pricing_rule.utils import MultiplePricingRuleConflict
self.assertRaises(MultiplePricingRuleConflict, get_item_details, args) self.assertRaises(MultiplePricingRuleConflict, get_item_details, args)
args.item_code = "_Test Item 2" args.item_code = "_Test Item 2"
@@ -101,7 +106,9 @@ class TestPricingRule(unittest.TestCase):
"doctype": "Pricing Rule", "doctype": "Pricing Rule",
"title": "_Test Pricing Rule", "title": "_Test Pricing Rule",
"apply_on": "Item Code", "apply_on": "Item Code",
"item_code": "_Test FG Item 2", "items": [{
"item_code": "_Test FG Item 2",
}],
"selling": 1, "selling": 1,
"currency": "USD", "currency": "USD",
"rate_or_discount": "Discount Percentage", "rate_or_discount": "Discount Percentage",
@@ -166,7 +173,9 @@ class TestPricingRule(unittest.TestCase):
"title": "_Test Pricing Rule 1", "title": "_Test Pricing Rule 1",
"apply_on": "Item Code", "apply_on": "Item Code",
"currency": "USD", "currency": "USD",
"item_code": "_Test Variant Item", "items": [{
"item_code": "_Test Variant Item",
}],
"selling": 1, "selling": 1,
"rate_or_discount": "Discount Percentage", "rate_or_discount": "Discount Percentage",
"rate": 0, "rate": 0,
@@ -196,7 +205,9 @@ class TestPricingRule(unittest.TestCase):
"doctype": "Pricing Rule", "doctype": "Pricing Rule",
"title": "_Test Pricing Rule 2", "title": "_Test Pricing Rule 2",
"apply_on": "Item Code", "apply_on": "Item Code",
"item_code": "Test Variant PRT", "items": [{
"item_code": "Test Variant PRT",
}],
"currency": "USD", "currency": "USD",
"selling": 1, "selling": 1,
"rate_or_discount": "Discount Percentage", "rate_or_discount": "Discount Percentage",
@@ -214,7 +225,9 @@ class TestPricingRule(unittest.TestCase):
"title": "_Test Pricing Rule", "title": "_Test Pricing Rule",
"apply_on": "Item Code", "apply_on": "Item Code",
"currency": "USD", "currency": "USD",
"item_code": "_Test Item", "items": [{
"item_code": "_Test Item",
}],
"selling": 1, "selling": 1,
"rate_or_discount": "Discount Percentage", "rate_or_discount": "Discount Percentage",
"rate": 0, "rate": 0,
@@ -273,7 +286,6 @@ def make_pricing_rule(**args):
"title": args.title or "_Test Pricing Rule", "title": args.title or "_Test Pricing Rule",
"company": args.company or "_Test Company", "company": args.company or "_Test Company",
"apply_on": args.apply_on or "Item Code", "apply_on": args.apply_on or "Item Code",
"item_code": args.item_code or "_Test Item",
"applicable_for": args.applicable_for, "applicable_for": args.applicable_for,
"selling": args.selling or 0, "selling": args.selling or 0,
"currency": "USD", "currency": "USD",
@@ -285,12 +297,25 @@ def make_pricing_rule(**args):
"rate": args.rate or 0.0, "rate": args.rate or 0.0,
"margin_type": args.margin_type, "margin_type": args.margin_type,
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0 "margin_rate_or_amount": args.margin_rate_or_amount or 0.0
}).insert(ignore_permissions=True) })
apply_on = doc.apply_on.replace(' ', '_').lower() apply_on = doc.apply_on.replace(' ', '_').lower()
child_table = {'Item Code': 'items', 'Item Group': 'item_groups', 'Brand': 'brands'}
doc.append(child_table.get(doc.apply_on), {
apply_on: args.get(apply_on) or "_Test Item"
})
doc.insert(ignore_permissions=True)
if args.get(apply_on) and apply_on != "item_code": if args.get(apply_on) and apply_on != "item_code":
doc.db_set(apply_on, args.get(apply_on)) doc.db_set(apply_on, args.get(apply_on))
applicable_for = doc.applicable_for.replace(' ', '_').lower() applicable_for = doc.applicable_for.replace(' ', '_').lower()
if args.get(applicable_for): if args.get(applicable_for):
doc.db_set(applicable_for, args.get(applicable_for)) doc.db_set(applicable_for, args.get(applicable_for))
def delete_existing_pricing_rules():
for doctype in ["Pricing Rule", "Pricing Rule Item Code",
"Pricing Rule Item Group", "Pricing Rule Brand"]:
frappe.db.sql("delete from `tab{0}`".format(doctype))

View File

@@ -0,0 +1,493 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
import json
import copy
from frappe import throw, _
from frappe.utils import flt, cint, get_datetime
from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
from erpnext.stock.get_item_details import get_conversion_factor
class MultiplePricingRuleConflict(frappe.ValidationError): pass
def get_pricing_rules(args, doc=None):
pricing_rules = []
values = {}
for apply_on in ['Item Code', 'Item Group', 'Brand']:
pricing_rules.extend(_get_pricing_rules(apply_on, args, values))
if pricing_rules and not apply_multiple_pricing_rules(pricing_rules):
break
rules = []
if not pricing_rules: return []
if apply_multiple_pricing_rules(pricing_rules):
for pricing_rule in pricing_rules:
pricing_rule = filter_pricing_rules(args, pricing_rule, doc)
if pricing_rule:
rules.append(pricing_rule)
else:
rules.append(filter_pricing_rules(args, pricing_rules, doc))
return rules
def _get_pricing_rules(apply_on, args, values):
apply_on_field = frappe.scrub(apply_on)
if not args.get(apply_on_field): return []
child_doc = '`tabPricing Rule {0}`'.format(apply_on)
conditions = item_variant_condition = item_conditions = ""
values[apply_on_field] = args.get(apply_on_field)
if apply_on_field in ['item_code', 'brand']:
item_conditions = "{child_doc}.{apply_on_field}= %({apply_on_field})s".format(child_doc=child_doc,
apply_on_field = apply_on_field)
if apply_on_field == 'item_code':
if "variant_of" not in args:
args.variant_of = frappe.get_cached_value("Item", args.item_code, "variant_of")
if args.variant_of:
item_variant_condition = ' or {child_doc}.item_code=%(variant_of)s '.format(child_doc=child_doc)
values['variant_of'] = args.variant_of
elif apply_on_field == 'item_group':
item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False)
conditions += get_other_conditions(conditions, values, args)
warehouse_conditions = _get_tree_conditions(args, "Warehouse", '`tabPricing Rule`')
if warehouse_conditions:
warehouse_conditions = " and {0}".format(warehouse_conditions)
if not args.price_list: args.price_list = None
conditions += " and ifnull(`tabPricing Rule`.for_price_list, '') in (%(price_list)s, '')"
values["price_list"] = args.get("price_list")
pricing_rules = frappe.db.sql("""select `tabPricing Rule`.*,
{child_doc}.{apply_on_field}, {child_doc}.uom
from `tabPricing Rule`, {child_doc}
where ({item_conditions} or (`tabPricing Rule`.apply_rule_on_other is not null
and `tabPricing Rule`.{apply_on_other_field}=%({apply_on_field})s) {item_variant_condition})
and {child_doc}.parent = `tabPricing Rule`.name
and `tabPricing Rule`.disable = 0 and
`tabPricing Rule`.{transaction_type} = 1 {warehouse_cond} {conditions}
order by `tabPricing Rule`.priority desc,
`tabPricing Rule`.name desc""".format(
child_doc = child_doc,
apply_on_field = apply_on_field,
item_conditions = item_conditions,
item_variant_condition = item_variant_condition,
transaction_type = args.transaction_type,
warehouse_cond = warehouse_conditions,
apply_on_other_field = "other_{0}".format(apply_on_field),
conditions = conditions), values, as_dict=1) or []
return pricing_rules
def apply_multiple_pricing_rules(pricing_rules):
apply_multiple_rule = [d.apply_multiple_pricing_rules
for d in pricing_rules if d.apply_multiple_pricing_rules]
if not apply_multiple_rule: return False
if (apply_multiple_rule
and len(apply_multiple_rule) == len(pricing_rules)):
return True
def _get_tree_conditions(args, parenttype, table, allow_blank=True):
field = frappe.scrub(parenttype)
condition = ""
if args.get(field):
if not frappe.flags.tree_conditions:
frappe.flags.tree_conditions = {}
key = (parenttype, args.get(field))
if key in frappe.flags.tree_conditions:
return frappe.flags.tree_conditions[key]
try:
lft, rgt = frappe.db.get_value(parenttype, args.get(field), ["lft", "rgt"])
except TypeError:
frappe.throw(_("Invalid {0}").format(args.get(field)))
parent_groups = frappe.db.sql_list("""select name from `tab%s`
where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt))
if parent_groups:
if allow_blank: parent_groups.append('')
condition = "ifnull({table}.{field}, '') in ({parent_groups})".format(
table=table,
field=field,
parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups])
)
frappe.flags.tree_conditions[key] = condition
return condition
def get_other_conditions(conditions, values, args):
for field in ["company", "customer", "supplier", "campaign", "sales_partner"]:
if args.get(field):
conditions += " and ifnull(`tabPricing Rule`.{0}, '') in (%({1})s, '')".format(field, field)
values[field] = args.get(field)
else:
conditions += " and ifnull(`tabPricing Rule`.{0}, '') = ''".format(field)
for parenttype in ["Customer Group", "Territory", "Supplier Group"]:
group_condition = _get_tree_conditions(args, parenttype, '`tabPricing Rule`')
if group_condition:
conditions += " and " + group_condition
if args.get("transaction_date"):
conditions += """ and %(transaction_date)s between ifnull(`tabPricing Rule`.valid_from, '2000-01-01')
and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')"""
values['transaction_date'] = args.get('transaction_date')
return conditions
def filter_pricing_rules(args, pricing_rules, doc=None):
if not isinstance(pricing_rules, list):
pricing_rules = [pricing_rules]
original_pricing_rule = copy.copy(pricing_rules)
# filter for qty
if pricing_rules:
stock_qty = flt(args.get('stock_qty'))
amount = flt(args.get('price_list_rate')) * flt(args.get('qty'))
if pricing_rules[0].apply_rule_on_other:
field = frappe.scrub(pricing_rules[0].apply_rule_on_other)
if (field and pricing_rules[0].get('other_' + field) != args.get(field)): return
pr_doc = frappe.get_doc('Pricing Rule', pricing_rules[0].name)
if pricing_rules[0].mixed_conditions and doc:
stock_qty, amount = get_qty_and_rate_for_mixed_conditions(doc, pr_doc)
elif pricing_rules[0].is_cumulative:
items = [args.get(frappe.scrub(pr_doc.get('apply_on')))]
data = get_qty_amount_data_for_cumulative(pr_doc, args, items)
if data:
stock_qty += data[0]
amount += data[1]
if pricing_rules[0].apply_rule_on_other and not pricing_rules[0].mixed_conditions and doc:
pricing_rules = get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules) or []
else:
pricing_rules = filter_pricing_rules_for_qty_amount(stock_qty, amount, pricing_rules, args)
if not pricing_rules:
for d in original_pricing_rule:
if not d.threshold_percentage: continue
msg = validate_quantity_and_amount_for_suggestion(d, stock_qty,
amount, args.get('item_code'), args.get('transaction_type'))
if msg:
return {'suggestion': msg, 'item_code': args.get('item_code')}
# add variant_of property in pricing rule
for p in pricing_rules:
if p.item_code and args.variant_of:
p.variant_of = args.variant_of
else:
p.variant_of = None
# find pricing rule with highest priority
if pricing_rules:
max_priority = max([cint(p.priority) for p in pricing_rules])
if max_priority:
pricing_rules = list(filter(lambda x: cint(x.priority)==max_priority, pricing_rules))
# apply internal priority
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
"supplier", "supplier_group", "campaign", "sales_partner", "variant_of"]
if len(pricing_rules) > 1:
for field_set in [["item_code", "variant_of", "item_group", "brand"],
["customer", "customer_group", "territory"], ["supplier", "supplier_group"]]:
remaining_fields = list(set(all_fields) - set(field_set))
if if_all_rules_same(pricing_rules, remaining_fields):
pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
break
if pricing_rules and not isinstance(pricing_rules, list):
pricing_rules = list(pricing_rules)
if len(pricing_rules) > 1:
rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules]))
if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage":
pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \
or pricing_rules
if len(pricing_rules) > 1 and not args.for_shopping_cart:
frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}")
.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict)
elif pricing_rules:
return pricing_rules[0]
def validate_quantity_and_amount_for_suggestion(args, qty, amount, item_code, transaction_type):
fieldname, msg = '', ''
type_of_transaction = 'purcahse' if transaction_type == "buying" else "sale"
for field, value in {'min_qty': qty, 'min_amt': amount}.items():
if (args.get(field) and value < args.get(field)
and (args.get(field) - cint(args.get(field) * args.threshold_percentage * 0.01)) <= value):
fieldname = field
for field, value in {'max_qty': qty, 'max_amt': amount}.items():
if (args.get(field) and value > args.get(field)
and (args.get(field) + cint(args.get(field) * args.threshold_percentage * 0.01)) >= value):
fieldname = field
if fieldname:
msg = _("""If you {0} {1} quantities of the item <b>{2}</b>, the scheme <b>{3}</b>
will be applied on the item.""").format(type_of_transaction, args.get(fieldname), item_code, args.rule_description)
if fieldname in ['min_amt', 'max_amt']:
msg = _("""If you {0} {1} worth item <b>{2}</b>, the scheme <b>{3}</b> will be applied on the item.
""").format(frappe.fmt_money(type_of_transaction, args.get(fieldname)), item_code, args.rule_description)
frappe.msgprint(msg)
return msg
def filter_pricing_rules_for_qty_amount(qty, rate, pricing_rules, args=None):
rules = []
for rule in pricing_rules:
status = False
conversion_factor = 1
if rule.get("uom"):
conversion_factor = get_conversion_factor(rule.item_code, rule.uom).get("conversion_factor", 1)
if (flt(qty) >= (flt(rule.min_qty) * conversion_factor)
and (flt(qty)<= (rule.max_qty * conversion_factor) if rule.max_qty else True)):
status = True
# if user has created item price against the transaction UOM
if rule.get("uom") == args.get("uom"):
conversion_factor = 1.0
if status and (flt(rate) >= (flt(rule.min_amt) * conversion_factor)
and (flt(rate)<= (rule.max_amt * conversion_factor) if rule.max_amt else True)):
status = True
else:
status = False
if status:
rules.append(rule)
return rules
def if_all_rules_same(pricing_rules, fields):
all_rules_same = True
val = [pricing_rules[0].get(k) for k in fields]
for p in pricing_rules[1:]:
if val != [p.get(k) for k in fields]:
all_rules_same = False
break
return all_rules_same
def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args.get(field):
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
if filtered_rules: break
return filtered_rules or pricing_rules
def get_qty_and_rate_for_mixed_conditions(doc, pr_doc):
sum_qty, sum_amt = [0, 0]
items = get_pricing_rule_items(pr_doc) or []
apply_on = frappe.scrub(pr_doc.get('apply_on'))
if items and doc.get("items"):
for row in doc.get('items'):
if row.get(apply_on) not in items: continue
if pr_doc.mixed_conditions:
sum_qty += row.stock_qty
sum_amt += row.amount
if pr_doc.is_cumulative:
data = get_qty_amount_data_for_cumulative(pr_doc, doc, items)
if data and data[0]:
sum_qty += data[0]
sum_amt += data[1]
return sum_qty, sum_amt
def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules):
for d in get_pricing_rule_items(pr_doc):
for row in doc.items:
if d == row.get(frappe.scrub(pr_doc.apply_on)):
pricing_rules = filter_pricing_rules_for_qty_amount(row.stock_qty,
row.amount, pricing_rules, row)
if pricing_rules and pricing_rules[0]:
return pricing_rules
def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]):
sum_qty, sum_amt = [0, 0]
doctype = doc.get('parenttype') or doc.doctype
date_field = ('transaction_date'
if doc.get('transaction_date') else 'posting_date')
child_doctype = '{0} Item'.format(doctype)
apply_on = frappe.scrub(pr_doc.get('apply_on'))
values = [pr_doc.valid_from, pr_doc.valid_upto]
condition = ""
if pr_doc.warehouse:
warehouses = get_child_warehouses(pr_doc.warehouse)
condition += """ and `tab{child_doc}`.warehouse in ({warehouses})
""".format(child_doc=child_doctype, warehouses = ','.join(['%s'] * len(warehouses)))
values.extend(warehouses)
if items:
condition = " and `tab{child_doc}`.{apply_on} in ({items})".format(child_doc = child_doctype,
apply_on = apply_on, items = ','.join(['%s'] * len(items)))
values.extend(items)
data_set = frappe.db.sql(""" SELECT `tab{child_doc}`.stock_qty,
`tab{child_doc}`.amount
FROM `tab{child_doc}`, `tab{parent_doc}`
WHERE
`tab{child_doc}`.parent = `tab{parent_doc}`.name and {date_field}
between %s and %s and `tab{parent_doc}`.docstatus = 1
{condition} group by `tab{child_doc}`.name
""".format(parent_doc = doctype,
child_doc = child_doctype,
condition = condition,
date_field = date_field
), tuple(values), as_dict=1)
for data in data_set:
sum_qty += data.get('stock_qty')
sum_amt += data.get('amount')
return [sum_qty, sum_amt]
def validate_pricing_rules(doc):
validate_pricing_rule_on_transactions(doc)
if not doc.pricing_rules: return
for d in doc.items:
validate_pricing_rule_on_items(doc, d)
doc.calculate_taxes_and_totals()
def validate_pricing_rule_on_items(doc, item_row):
value = 0
for pr_row in get_applied_pricing_rules(doc, item_row):
pr_doc = frappe.get_doc('Pricing Rule', pr_row.pricing_rule)
if pr_doc.get('apply_on') == 'Transaction': continue
if pr_doc.get('price_or_product_discount') == 'Product':
apply_pricing_rule_for_free_items(doc, pr_doc)
else:
for field in ['discount_percentage', 'discount_amount', 'rate']:
if not pr_doc.get(field): continue
value += pr_doc.get(field)
apply_pricing_rule(doc, pr_doc, pr_row, item_row, value)
def validate_pricing_rule_on_transactions(doc):
conditions = "apply_on = 'Transaction'"
values = {}
conditions = get_other_conditions(conditions, values, doc)
pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
where {conditions} """.format(conditions = conditions), values, as_dict=1)
if pricing_rules:
pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
doc.total, pricing_rules)
for d in pricing_rules:
if d.price_or_product_discount == 'Price':
if d.apply_discount_on:
doc.set('apply_discount_on', d.apply_discount_on)
for field in ['additional_discount_percentage', 'discount_amount']:
if not d.get(field): continue
pr_field = ('discount_percentage'
if field == 'additional_discount_percentage' else field)
if d.validate_applied_rule and doc.get(field) < d.get(pr_field):
frappe.msgprint(_("User has not applied rule on the invoice {0}")
.format(doc.name))
else:
doc.set(field, d.get(pr_field))
elif d.price_or_product_discount == 'Product':
apply_pricing_rule_for_free_items(doc, d)
def get_applied_pricing_rules(doc, item_row):
return [d for d in doc.pricing_rules
if d.child_docname == item_row.name]
def apply_pricing_rule_for_free_items(doc, pricing_rule):
if pricing_rule.get('free_item'):
items = [d.item_code for d in doc.items
if d.item_code == (d.item_code
if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item]
if not items:
doc.append('items', {
'item_code': pricing_rule.get('free_item'),
'qty': pricing_rule.get('free_qty'),
'uom': pricing_rule.get('free_item_uom'),
'rate': pricing_rule.get('free_item_rate'),
'is_free_item': 1
})
doc.set_missing_values()
def apply_pricing_rule(doc, pr_doc, pr_row, item_row, value):
apply_on = frappe.scrub(pr_doc.get('apply_on'))
items = (get_pricing_rule_items(pr_doc)
if pr_doc.mixed_conditions else [item_row.get(apply_on)])
if pr_doc.apply_rule_on_other:
apply_on = frappe.scrub(pr_doc.apply_rule_on_other)
items = [pr_doc.get(apply_on)]
rule_applied = 1
if item_row.get(apply_on) in items:
for field in ['discount_percentage', 'discount_amount', 'rate']:
if not pr_doc.get(field): continue
if not pr_doc.validate_applied_rule:
item_row.set(field, value)
elif item_row.get(field) < value:
rule_applied = 0
frappe.msgprint(_("Row {0}: user has not applied rule <b>{1}</b> on the item <b>{2}</b>")
.format(item_row.idx, pr_doc.title, item_row.item_code))
pr_row.rule_applied = rule_applied
def get_pricing_rule_items(pr_doc):
apply_on = frappe.scrub(pr_doc.get('apply_on'))
return [item.get(apply_on) for item in pr_doc.items] or []

View File

@@ -0,0 +1,110 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-24 14:48:59.649168",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:parent.apply_on == 'Item Code'",
"fieldname": "brand",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Brand",
"length": 0,
"no_copy": 0,
"options": "Brand",
"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": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-24 14:48:59.649168",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule Brand",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PricingRuleBrand(Document):
pass

View File

@@ -0,0 +1,237 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-02-01 13:07:49.073255",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "pricing_rule",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Pricing Rule",
"length": 0,
"no_copy": 0,
"options": "Pricing Rule",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_code",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "margin_type",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Margin Type",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rate_or_discount",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Rate or Discount",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "child_docname",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Child Docname",
"length": 0,
"no_copy": 1,
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "rule_applied",
"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": "Rule Applied",
"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,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-06 16:01:49.855764",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule Detail",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PricingRuleDetail(Document):
pass

View File

@@ -0,0 +1,112 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-24 14:48:59.649168",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:parent.apply_on == 'Item Code'",
"fetch_if_empty": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"options": "Item",
"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": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-25 14:05:41.504182",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule Item Code",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PricingRuleItemCode(Document):
pass

View File

@@ -0,0 +1,110 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-24 14:48:59.649168",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:parent.apply_on == 'Item Code'",
"fieldname": "item_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "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": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-24 14:48:59.649168",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule Item Group",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PricingRuleItemGroup(Document):
pass

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Promotional Scheme', {
refresh: function(frm) {
frm.trigger("set_options_for_applicable_for");
frm.trigger("toggle_reqd_apply_on");
},
selling: function(frm) {
frm.trigger("set_options_for_applicable_for");
},
buying: function(frm) {
frm.trigger("set_options_for_applicable_for");
},
set_options_for_applicable_for: function(frm) {
var options = [""];
var applicable_for = frm.doc.applicable_for;
if(frm.doc.selling) {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
}
if(frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Group"]);
}
set_field_options("applicable_for", options.join("\n"));
if(!in_list(options, applicable_for)) applicable_for = null;
frm.set_value("applicable_for", applicable_for);
},
apply_on: function(frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
};
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
}
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cstr
from frappe.model.naming import make_autoname
from frappe.model.document import Document
pricing_rule_fields = ['apply_on', 'mixed_conditions', 'is_cumulative', 'other_item_code', 'other_item_group'
'apply_rule_on_other', 'other_brand', 'selling', 'buying', 'applicable_for', 'valid_from',
'valid_upto', 'customer', 'customer_group', 'territory', 'sales_partner', 'campaign', 'supplier',
'supplier_group', 'company', 'currency']
other_fields = ['min_qty', 'max_qty', 'min_amt',
'max_amt', 'priority','warehouse', 'threshold_percentage', 'rule_description']
price_discount_fields = ['rate_or_discount', 'apply_discount_on', 'apply_discount_on_rate',
'rate', 'discount_amount', 'discount_percentage', 'validate_applied_rule']
product_discount_fields = ['free_item', 'free_qty', 'free_item_uom',
'free_item_rate', 'same_item']
class PromotionalScheme(Document):
def validate(self):
if not (self.price_discount_slabs
or self.product_discount_slabs):
frappe.throw(_("Price or product discount slabs are required"))
def on_update(self):
data = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name"],
filters = {'promotional_scheme': self.name}) or {}
self.update_pricing_rules(data)
def update_pricing_rules(self, data):
rules = {}
count = 0
for d in data:
rules[d.get('promotional_scheme_id')] = d.get('name')
docs = get_pricing_rules(self, rules)
for doc in docs:
doc.run_method("validate")
if doc.get("__islocal"):
count += 1
doc.insert()
else:
doc.save()
frappe.msgprint(_("Pricing Rule {0} is updated").format(doc.name))
if count:
frappe.msgprint(_("New {0} pricing rules are created").format(count))
def on_trash(self):
for d in frappe.get_all('Pricing Rule',
{'promotional_scheme': self.name}):
frappe.delete_doc('Pricing Rule', d.name)
def get_pricing_rules(doc, rules = {}):
new_doc = []
for child_doc, fields in {'price_discount_slabs': price_discount_fields,
'product_discount_slabs': product_discount_fields}.items():
if doc.get(child_doc):
new_doc.extend(_get_pricing_rules(doc, child_doc, fields, rules))
return new_doc
def _get_pricing_rules(doc, child_doc, discount_fields, rules = {}):
new_doc = []
args = get_args_for_pricing_rule(doc)
for d in doc.get(child_doc):
if d.name in rules:
pr = frappe.get_doc('Pricing Rule', rules.get(d.name))
else:
pr = frappe.new_doc("Pricing Rule")
pr.title = make_autoname("{0}/.####".format(doc.name))
pr.update(args)
for field in (other_fields + discount_fields):
pr.set(field, d.get(field))
pr.promotional_scheme_id = d.name
pr.promotional_scheme = doc.name
pr.disable = d.disable if d.disable else doc.disable
pr.price_or_product_discount = ('Price'
if child_doc == 'price_discount_slabs' else 'Product')
for field in ['items', 'item_groups', 'brands']:
if doc.get(field):
pr.set(field, [])
apply_on = frappe.scrub(doc.get('apply_on'))
for d in doc.get(field):
pr.append(field, {
apply_on: d.get(apply_on),
'uom': d.uom
})
new_doc.append(pr)
return new_doc
def get_args_for_pricing_rule(doc):
args = { 'promotional_scheme': doc.name }
for d in pricing_rule_fields:
args[d] = doc.get(d)
return args

View File

@@ -0,0 +1,12 @@
from frappe import _
def get_data():
return {
'fieldname': 'promotional_scheme',
'transactions': [
{
'label': _('Reference'),
'items': ['Pricing Rule']
}
]
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestPromotionalScheme(unittest.TestCase):
pass

View File

@@ -0,0 +1,792 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-24 14:48:59.649168",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "disable",
"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": "Disable",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rule_description",
"fieldtype": "Small 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": "Rule Description",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 1,
"default": "0",
"fieldname": "min_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min 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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 1,
"default": "0",
"fieldname": "max_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Max 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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "min_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "",
"fieldname": "max_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Max Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "section_break_6",
"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": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Discount Percentage",
"depends_on": "",
"fieldname": "rate_or_discount",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Discount Type",
"length": 0,
"no_copy": 0,
"options": "\nRate\nDiscount Percentage\nDiscount Amount",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "column_break_10",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"depends_on": "eval:doc.rate_or_discount==\"Rate\"",
"fieldname": "rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.rate_or_discount==\"Discount Amount\"",
"fieldname": "discount_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Discount Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.rate_or_discount==\"Discount Percentage\"",
"fieldname": "discount_percentage",
"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": "Discount Percentage",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_11",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "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": "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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "threshold_percentage",
"fieldtype": "Percent",
"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": "Threshold for Suggestion",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "validate_applied_rule",
"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": "Validate Applied Rule",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_14",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "priority",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Priority",
"length": 0,
"no_copy": 0,
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "priority",
"fieldname": "apply_multiple_pricing_rules",
"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": "Apply Multiple Pricing Rules",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:in_list(['Discount Percentage', 'Discount Amount'], doc.rate_or_discount) && doc.apply_multiple_pricing_rules",
"fieldname": "apply_discount_on_rate",
"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": "Apply Discount on Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-24 14:48:59.649168",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Promotional Scheme Price Discount",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PromotionalSchemePriceDiscount(Document):
pass

View File

@@ -0,0 +1,751 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-24 14:48:59.649168",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "disable",
"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": "Disable",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rule_description",
"fieldtype": "Small 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": "Rule Description",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_1",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "min_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min 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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "max_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Max 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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "min_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "max_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Max Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"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": "Free Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!parent.mixed_conditions",
"fieldname": "same_item",
"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": "Same Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.same_item || parent.mixed_conditions",
"fieldname": "free_item",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "free_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "free_item_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "free_item_rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "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": "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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "threshold_percentage",
"fieldtype": "Percent",
"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": "Threshold for Suggestion",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_15",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "priority",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Priority",
"length": 0,
"no_copy": 0,
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "apply_multiple_pricing_rules",
"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": "Apply Multiple Pricing Rules",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-24 14:48:59.649168",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Promotional Scheme Product Discount",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, 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 PromotionalSchemeProductDiscount(Document):
pass

View File

@@ -510,6 +510,15 @@ frappe.ui.form.on("Purchase Invoice", {
} }
} }
} }
frm.set_query("cost_center", function() {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
};
});
}, },
onload: function(frm) { onload: function(frm) {

View File

@@ -1819,6 +1819,73 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"fieldname": "pricing_rule_details",
"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": "Pricing Rules",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"fieldname": "pricing_rules",
"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": "Pricing Rule Detail",
"length": 0,
"no_copy": 0,
"options": "Pricing Rule Detail",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -4759,7 +4826,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2018-12-27 02:07:04.299399", "modified": "2019-02-13 00:55:15.530604",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice", "name": "Purchase Invoice",

View File

@@ -8,6 +8,7 @@ from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate
from frappe import _, throw from frappe import _, throw
import frappe.defaults import frappe.defaults
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.controllers.buying_controller import BuyingController from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency, get_fiscal_year from erpnext.accounts.utils import get_account_currency, get_fiscal_year
@@ -17,7 +18,7 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.buying.utils import check_for_closed_status from erpnext.buying.utils import check_for_closed_status
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled
from frappe.model.mapper import get_mapped_doc from frappe.model.mapper import get_mapped_doc
from six import iteritems from six import iteritems
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\ from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
@@ -54,6 +55,12 @@ class PurchaseInvoice(BuyingController):
if not self.on_hold: if not self.on_hold:
self.release_date = '' self.release_date = ''
def before_print(self):
self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Purchase Invoice",
"voucher_no": self.name} ,
fields=["account", "party_type", "party", "debit", "credit"]
)
def invoice_is_blocked(self): def invoice_is_blocked(self):
return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate())) return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate()))
@@ -216,7 +223,7 @@ class PurchaseInvoice(BuyingController):
self.validate_item_code() self.validate_item_code()
self.validate_warehouse() self.validate_warehouse()
if auto_accounting_for_stock: if auto_accounting_for_stock:
warehouse_account = get_warehouse_account_map() warehouse_account = get_warehouse_account_map(self.company)
for item in self.get("items"): for item in self.get("items"):
# in case of auto inventory accounting, # in case of auto inventory accounting,
@@ -232,6 +239,13 @@ class PurchaseInvoice(BuyingController):
item.expense_account = warehouse_account[item.warehouse]["account"] item.expense_account = warehouse_account[item.warehouse]["account"]
else: else:
item.expense_account = stock_not_billed_account item.expense_account = stock_not_billed_account
elif item.is_fixed_asset and is_cwip_accounting_disabled():
if not item.asset:
frappe.throw(_("Row {0}: asset is required for item {1}")
.format(item.idx, item.item_code))
item.expense_account = get_asset_category_account(item.asset, 'fixed_asset_account',
company = self.company)
elif item.is_fixed_asset and item.pr_detail: elif item.is_fixed_asset and item.pr_detail:
item.expense_account = asset_received_but_not_billed item.expense_account = asset_received_but_not_billed
elif not item.expense_account and for_validate: elif not item.expense_account and for_validate:
@@ -360,7 +374,8 @@ class PurchaseInvoice(BuyingController):
if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock: if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
from erpnext.controllers.stock_controller import update_gl_entries_after from erpnext.controllers.stock_controller import update_gl_entries_after
items, warehouses = self.get_items_and_warehouses() items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items) update_gl_entries_after(self.posting_date, self.posting_time,
warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock: elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -377,7 +392,9 @@ class PurchaseInvoice(BuyingController):
self.make_supplier_gl_entry(gl_entries) self.make_supplier_gl_entry(gl_entries)
self.make_item_gl_entries(gl_entries) self.make_item_gl_entries(gl_entries)
self.get_asset_gl_entry(gl_entries) if not is_cwip_accounting_disabled():
self.get_asset_gl_entry(gl_entries)
self.make_tax_gl_entries(gl_entries) self.make_tax_gl_entries(gl_entries)
gl_entries = merge_similar_entries(gl_entries) gl_entries = merge_similar_entries(gl_entries)
@@ -417,7 +434,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items() stock_items = self.get_stock_items()
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
if self.update_stock and self.auto_accounting_for_stock: if self.update_stock and self.auto_accounting_for_stock:
warehouse_account = get_warehouse_account_map() warehouse_account = get_warehouse_account_map(self.company)
voucher_wise_stock_value = {} voucher_wise_stock_value = {}
if self.update_stock: if self.update_stock:
@@ -469,7 +486,7 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Stock"), "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost) "credit": flt(item.rm_supp_cost)
}, warehouse_account[self.supplier_warehouse]["account_currency"])) }, warehouse_account[self.supplier_warehouse]["account_currency"]))
elif not item.is_fixed_asset: elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()):
gl_entries.append( gl_entries.append(
self.get_gl_dict({ self.get_gl_dict({
"account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account, "account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account,
@@ -514,7 +531,7 @@ class PurchaseInvoice(BuyingController):
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
if (not item.expense_account or frappe.db.get_value('Account', if (not item.expense_account or frappe.db.get_value('Account',
item.expense_account, 'account_type') != 'Asset Received But Not Billed'): item.expense_account, 'account_type') not in ['Asset Received But Not Billed', 'Fixed Asset']):
arbnb_account = self.get_company_default("asset_received_but_not_billed") arbnb_account = self.get_company_default("asset_received_but_not_billed")
item.expense_account = arbnb_account item.expense_account = arbnb_account

View File

@@ -20,6 +20,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 3, "columns": 3,
"fetch_if_empty": 0,
"fieldname": "item_code", "fieldname": "item_code",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -54,6 +55,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break1", "fieldname": "col_break1",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -84,6 +86,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_name", "fieldname": "item_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -117,6 +120,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "description_section", "fieldname": "description_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -149,6 +153,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text Editor", "fieldtype": "Text Editor",
"hidden": 0, "hidden": 0,
@@ -184,6 +189,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image", "fieldname": "image",
"fieldtype": "Attach", "fieldtype": "Attach",
"hidden": 1, "hidden": 1,
@@ -216,6 +222,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image_view", "fieldname": "image_view",
"fieldtype": "Image", "fieldtype": "Image",
"hidden": 0, "hidden": 0,
@@ -249,6 +256,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "quantity_and_rate", "fieldname": "quantity_and_rate",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -280,6 +288,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "received_qty", "fieldname": "received_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -312,6 +321,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "qty", "fieldname": "qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -345,6 +355,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "rejected_qty", "fieldname": "rejected_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -377,6 +388,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_uom", "fieldname": "stock_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -410,6 +422,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break2", "fieldname": "col_break2",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -440,6 +453,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "uom", "fieldname": "uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -473,6 +487,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "conversion_factor", "fieldname": "conversion_factor",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -505,6 +520,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -537,6 +553,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_break1", "fieldname": "sec_break1",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -567,6 +584,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "price_list_rate", "fieldname": "price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -600,6 +618,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "price_list_rate", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_percentage", "fieldname": "discount_percentage",
"fieldtype": "Percent", "fieldtype": "Percent",
"hidden": 0, "hidden": 0,
@@ -631,7 +650,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "discount_percentage", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_amount", "fieldname": "discount_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -649,7 +669,7 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@@ -665,6 +685,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "col_break3", "fieldname": "col_break3",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -695,6 +717,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_price_list_rate", "fieldname": "base_price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -727,6 +750,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_break2", "fieldname": "sec_break2",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -757,6 +781,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 3, "columns": 3,
"fetch_if_empty": 0,
"fieldname": "rate", "fieldname": "rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -791,6 +816,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "amount", "fieldname": "amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -825,6 +851,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break4", "fieldname": "col_break4",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -855,6 +882,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rate", "fieldname": "base_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -889,6 +917,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount", "fieldname": "base_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -923,21 +952,22 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "pricing_rule", "fetch_if_empty": 0,
"fieldtype": "Link", "fieldname": "pricing_rules",
"hidden": 0, "fieldtype": "Small Text",
"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": "Pricing Rule", "label": "Pricing Rules",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Pricing Rule",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "precision": "",
"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,
@@ -955,6 +985,40 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_free_item",
"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": "Is Free Item",
"length": 0,
"no_copy": 0,
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_22", "fieldname": "section_break_22",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -986,6 +1050,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_rate", "fieldname": "net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1019,6 +1084,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_amount", "fieldname": "net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1052,6 +1118,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_25", "fieldname": "column_break_25",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1083,6 +1150,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_rate", "fieldname": "base_net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1116,6 +1184,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_amount", "fieldname": "base_net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1149,6 +1218,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_weight_details", "fieldname": "item_weight_details",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1181,6 +1251,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_per_unit", "fieldname": "weight_per_unit",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1213,6 +1284,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_weight", "fieldname": "total_weight",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1245,6 +1317,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_38", "fieldname": "column_break_38",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1276,6 +1349,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_uom", "fieldname": "weight_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1309,6 +1383,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "warehouse_section", "fieldname": "warehouse_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1342,6 +1417,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "", "default": "",
"fetch_if_empty": 0,
"fieldname": "warehouse", "fieldname": "warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1375,6 +1451,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "rejected_warehouse", "fieldname": "rejected_warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1409,6 +1486,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.__islocal", "depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "quality_inspection", "fieldname": "quality_inspection",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1442,6 +1520,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "batch_no", "fieldname": "batch_no",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1475,6 +1554,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_br_wh", "fieldname": "col_br_wh",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1507,6 +1587,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "serial_no", "fieldname": "serial_no",
"fieldtype": "Text", "fieldtype": "Text",
"hidden": 0, "hidden": 0,
@@ -1539,6 +1620,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "rejected_serial_no", "fieldname": "rejected_serial_no",
"fieldtype": "Text", "fieldtype": "Text",
"hidden": 0, "hidden": 0,
@@ -1571,6 +1653,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "accounting", "fieldname": "accounting",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1602,6 +1685,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "expense_account", "fieldname": "expense_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1638,6 +1722,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_tax_template", "fieldname": "item_tax_template",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1671,6 +1756,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break5", "fieldname": "col_break5",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1701,6 +1787,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "project", "fieldname": "project",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1735,6 +1822,7 @@
"columns": 0, "columns": 0,
"default": ":Company", "default": ":Company",
"depends_on": "eval:!doc.is_fixed_asset", "depends_on": "eval:!doc.is_fixed_asset",
"fetch_if_empty": 0,
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1771,6 +1859,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "deferred_expense_section", "fieldname": "deferred_expense_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1804,6 +1893,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_expense", "depends_on": "enable_deferred_expense",
"fetch_if_empty": 0,
"fieldname": "deferred_expense_account", "fieldname": "deferred_expense_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1838,6 +1928,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_expense", "depends_on": "enable_deferred_expense",
"fetch_if_empty": 0,
"fieldname": "service_stop_date", "fieldname": "service_stop_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1870,6 +1961,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "enable_deferred_expense", "fieldname": "enable_deferred_expense",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -1902,6 +1994,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_58", "fieldname": "column_break_58",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1934,6 +2027,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_expense", "depends_on": "enable_deferred_expense",
"fetch_if_empty": 0,
"fieldname": "service_start_date", "fieldname": "service_start_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1967,6 +2061,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_expense", "depends_on": "enable_deferred_expense",
"fetch_if_empty": 0,
"fieldname": "service_end_date", "fieldname": "service_end_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1999,6 +2094,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "reference", "fieldname": "reference",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -2030,6 +2126,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "allow_zero_valuation_rate", "fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2062,6 +2159,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "brand", "fieldname": "brand",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2096,6 +2194,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "", "description": "",
"fetch_if_empty": 0,
"fieldname": "item_group", "fieldname": "item_group",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -2131,6 +2230,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges", "description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges",
"fetch_if_empty": 0,
"fieldname": "item_tax_rate", "fieldname": "item_tax_rate",
"fieldtype": "Code", "fieldtype": "Code",
"hidden": 1, "hidden": 1,
@@ -2164,6 +2264,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_tax_amount", "fieldname": "item_tax_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 1, "hidden": 1,
@@ -2198,6 +2299,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "purchase_order", "fieldname": "purchase_order",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2232,6 +2334,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "bom", "fieldname": "bom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2266,6 +2369,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:parent.is_subcontracted == 'Yes'", "depends_on": "eval:parent.is_subcontracted == 'Yes'",
"fetch_if_empty": 0,
"fieldname": "include_exploded_items", "fieldname": "include_exploded_items",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2298,6 +2402,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break6", "fieldname": "col_break6",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -2328,6 +2433,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_fixed_asset", "fieldname": "is_fixed_asset",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 1, "hidden": 1,
@@ -2361,6 +2467,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "is_fixed_asset", "depends_on": "is_fixed_asset",
"fetch_if_empty": 0,
"fieldname": "asset", "fieldname": "asset",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2395,6 +2502,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "is_fixed_asset", "depends_on": "is_fixed_asset",
"fetch_if_empty": 0,
"fieldname": "asset_location", "fieldname": "asset_location",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2428,6 +2536,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "po_detail", "fieldname": "po_detail",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2461,6 +2570,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "purchase_receipt", "fieldname": "purchase_receipt",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2495,6 +2605,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "page_break", "fieldname": "page_break",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2526,6 +2637,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "pr_detail", "fieldname": "pr_detail",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2559,6 +2671,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "valuation_rate", "fieldname": "valuation_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 1, "hidden": 1,
@@ -2591,6 +2704,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "rm_supp_cost", "fieldname": "rm_supp_cost",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 1, "hidden": 1,
@@ -2623,6 +2737,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "landed_cost_voucher_amount", "fieldname": "landed_cost_voucher_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -2659,7 +2774,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2019-02-18 19:03:19.250280", "modified": "2019-03-19 03:00:30.827973",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice Item", "name": "Purchase Invoice Item",

View File

@@ -556,6 +556,23 @@ frappe.ui.form.on('Sales Invoice', {
frm.add_fetch('payment_term', 'invoice_portion', 'invoice_portion'); frm.add_fetch('payment_term', 'invoice_portion', 'invoice_portion');
frm.add_fetch('payment_term', 'description', 'description'); frm.add_fetch('payment_term', 'description', 'description');
frm.set_query("account_for_change_amount", function() {
return {
filters: {
account_type: ['in', ["Cash", "Bank"]]
}
};
});
frm.set_query("cost_center", function() {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
};
});
frm.custom_make_buttons = { frm.custom_make_buttons = {
'Delivery Note': 'Delivery', 'Delivery Note': 'Delivery',
'Sales Invoice': 'Sales Return', 'Sales Invoice': 'Sales Return',

View File

@@ -1783,6 +1783,71 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "pricing_rule_details",
"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": "Pricing Rules",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "pricing_rules",
"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": "Pricing Rule Detail",
"length": 0,
"no_copy": 0,
"options": "Pricing Rule Detail",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -5677,7 +5742,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2019-02-18 18:56:51.265257", "modified": "2019-03-17 18:56:51.265257",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice", "name": "Sales Invoice",

View File

@@ -205,6 +205,12 @@ class SalesInvoice(SellingController):
def before_cancel(self): def before_cancel(self):
self.update_time_sheet(None) self.update_time_sheet(None)
def before_print(self):
self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Sales Invoice",
"voucher_no": self.name} ,
fields=["account", "party_type", "party", "debit", "credit"]
)
def on_cancel(self): def on_cancel(self):
self.check_sales_order_on_hold_or_close("sales_order") self.check_sales_order_on_hold_or_close("sales_order")
@@ -399,7 +405,7 @@ class SalesInvoice(SellingController):
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name', for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'cash_bank_account', 'company_address', 'company', 'select_print_heading', 'cash_bank_account', 'company_address',
'write_off_account', 'write_off_cost_center', 'apply_discount_on'): 'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)): if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname)) self.set(fieldname, pos.get(fieldname))
@@ -523,8 +529,8 @@ class SalesInvoice(SellingController):
def validate_pos(self): def validate_pos(self):
if self.is_return: if self.is_return:
if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) < \ if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) > \
1/(10**(self.precision("grand_total") + 1)): 1.0/(10.0**(self.precision("grand_total") + 1.0)):
frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total")) frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total"))
def validate_item_code(self): def validate_item_code(self):
@@ -689,7 +695,8 @@ class SalesInvoice(SellingController):
if repost_future_gle and cint(self.update_stock) \ if repost_future_gle and cint(self.update_stock) \
and cint(auto_accounting_for_stock): and cint(auto_accounting_for_stock):
items, warehouses = self.get_items_and_warehouses() items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items) update_gl_entries_after(self.posting_date, self.posting_time,
warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) \ elif self.docstatus == 2 and cint(self.update_stock) \
and cint(auto_accounting_for_stock): and cint(auto_accounting_for_stock):
from erpnext.accounts.general_ledger import delete_gl_entries from erpnext.accounts.general_ledger import delete_gl_entries

View File

@@ -543,6 +543,7 @@ class TestSalesInvoice(unittest.TestCase):
si.get("taxes")[6].tax_amount = 2 si.get("taxes")[6].tax_amount = 2
si.insert() si.insert()
print(si.name)
expected_values = [ expected_values = [
{ {

View File

@@ -21,6 +21,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "barcode", "fieldname": "barcode",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -52,6 +53,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 4, "columns": 4,
"fetch_if_empty": 0,
"fieldname": "item_code", "fieldname": "item_code",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -86,6 +88,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break1", "fieldname": "col_break1",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -116,6 +119,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_name", "fieldname": "item_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -149,6 +153,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_item_code", "fieldname": "customer_item_code",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -180,6 +185,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_6", "fieldname": "section_break_6",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -212,6 +218,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text Editor", "fieldtype": "Text Editor",
"hidden": 0, "hidden": 0,
@@ -247,6 +254,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_8", "fieldname": "column_break_8",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -278,6 +286,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image_view", "fieldname": "image_view",
"fieldtype": "Image", "fieldtype": "Image",
"hidden": 0, "hidden": 0,
@@ -311,6 +320,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image", "fieldname": "image",
"fieldtype": "Attach", "fieldtype": "Attach",
"hidden": 1, "hidden": 1,
@@ -343,6 +353,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "quantity_and_rate", "fieldname": "quantity_and_rate",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -374,6 +385,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "qty", "fieldname": "qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -407,6 +419,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_uom", "fieldname": "stock_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -439,6 +452,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break2", "fieldname": "col_break2",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -469,6 +483,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "uom", "fieldname": "uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -502,6 +517,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "conversion_factor", "fieldname": "conversion_factor",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -534,6 +550,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -566,6 +583,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_17", "fieldname": "section_break_17",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -597,6 +615,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "price_list_rate", "fieldname": "price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -631,6 +650,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_price_list_rate", "fieldname": "base_price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -665,6 +685,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "discount_and_margin", "fieldname": "discount_and_margin",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -698,6 +719,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "price_list_rate", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "margin_type", "fieldname": "margin_type",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -732,6 +754,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.margin_type && doc.price_list_rate", "depends_on": "eval:doc.margin_type && doc.price_list_rate",
"fetch_if_empty": 0,
"fieldname": "margin_rate_or_amount", "fieldname": "margin_rate_or_amount",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -765,6 +788,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
"fetch_if_empty": 0,
"fieldname": "rate_with_margin", "fieldname": "rate_with_margin",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -798,6 +822,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_19", "fieldname": "column_break_19",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -830,6 +855,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "price_list_rate", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_percentage", "fieldname": "discount_percentage",
"fieldtype": "Percent", "fieldtype": "Percent",
"hidden": 0, "hidden": 0,
@@ -864,7 +890,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "discount_percentage", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_amount", "fieldname": "discount_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -882,7 +909,7 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@@ -899,6 +926,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
"fetch_if_empty": 0,
"fieldname": "base_rate_with_margin", "fieldname": "base_rate_with_margin",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -932,6 +960,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break1", "fieldname": "section_break1",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -962,6 +991,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "rate", "fieldname": "rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -996,6 +1026,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "amount", "fieldname": "amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1030,6 +1061,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break3", "fieldname": "col_break3",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1060,6 +1092,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rate", "fieldname": "base_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1094,6 +1127,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount", "fieldname": "base_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1128,21 +1162,22 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "pricing_rule", "fetch_if_empty": 0,
"fieldtype": "Link", "fieldname": "pricing_rules",
"hidden": 0, "fieldtype": "Small Text",
"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": "Pricing Rule", "label": "Pricing Rules",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Pricing Rule",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "precision": "",
"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,
@@ -1160,6 +1195,40 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_free_item",
"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": "Is Free Item",
"length": 0,
"no_copy": 0,
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_21", "fieldname": "section_break_21",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1191,6 +1260,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_rate", "fieldname": "net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1224,6 +1294,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_amount", "fieldname": "net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1257,6 +1328,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_24", "fieldname": "column_break_24",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1288,6 +1360,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_rate", "fieldname": "base_net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1321,6 +1394,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_amount", "fieldname": "base_net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1355,6 +1429,7 @@
"collapsible": 1, "collapsible": 1,
"collapsible_depends_on": "eval:doc.delivered_by_supplier==1", "collapsible_depends_on": "eval:doc.delivered_by_supplier==1",
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "drop_ship", "fieldname": "drop_ship",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1387,6 +1462,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "delivered_by_supplier", "fieldname": "delivered_by_supplier",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -1419,6 +1495,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "accounting", "fieldname": "accounting",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1450,6 +1527,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "income_account", "fieldname": "income_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1486,6 +1564,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "expense_account", "fieldname": "expense_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1519,6 +1598,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break4", "fieldname": "col_break4",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1549,6 +1629,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_tax_template", "fieldname": "item_tax_template",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1583,6 +1664,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": ":Company", "default": ":Company",
"fetch_if_empty": 0,
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1619,6 +1701,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "deferred_revenue", "fieldname": "deferred_revenue",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1652,6 +1735,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_revenue", "depends_on": "enable_deferred_revenue",
"fetch_if_empty": 0,
"fieldname": "deferred_revenue_account", "fieldname": "deferred_revenue_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1686,6 +1770,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_revenue", "depends_on": "enable_deferred_revenue",
"fetch_if_empty": 0,
"fieldname": "service_stop_date", "fieldname": "service_stop_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1719,6 +1804,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "0", "default": "0",
"fetch_if_empty": 0,
"fieldname": "enable_deferred_revenue", "fieldname": "enable_deferred_revenue",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -1751,6 +1837,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_50", "fieldname": "column_break_50",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1783,6 +1870,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_revenue", "depends_on": "enable_deferred_revenue",
"fetch_if_empty": 0,
"fieldname": "service_start_date", "fieldname": "service_start_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1816,6 +1904,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "enable_deferred_revenue", "depends_on": "enable_deferred_revenue",
"fetch_if_empty": 0,
"fieldname": "service_end_date", "fieldname": "service_end_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -1848,6 +1937,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_18", "fieldname": "section_break_18",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1880,6 +1970,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_per_unit", "fieldname": "weight_per_unit",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1913,6 +2004,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_weight", "fieldname": "total_weight",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1945,6 +2037,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_21", "fieldname": "column_break_21",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1976,6 +2069,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_uom", "fieldname": "weight_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2011,6 +2105,7 @@
"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": "",
"fetch_if_empty": 0,
"fieldname": "warehouse_and_reference", "fieldname": "warehouse_and_reference",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -2042,6 +2137,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "warehouse", "fieldname": "warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2076,6 +2172,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "target_warehouse", "fieldname": "target_warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -2110,6 +2207,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.__islocal", "depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "quality_inspection", "fieldname": "quality_inspection",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2143,6 +2241,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "batch_no", "fieldname": "batch_no",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2175,6 +2274,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break5", "fieldname": "col_break5",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -2205,6 +2305,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "allow_zero_valuation_rate", "fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2237,6 +2338,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "serial_no", "fieldname": "serial_no",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"hidden": 0, "hidden": 0,
@@ -2271,6 +2373,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "", "description": "",
"fetch_if_empty": 0,
"fieldname": "item_group", "fieldname": "item_group",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -2305,6 +2408,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "brand", "fieldname": "brand",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2338,6 +2442,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_tax_rate", "fieldname": "item_tax_rate",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"hidden": 1, "hidden": 1,
@@ -2371,6 +2476,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "actual_batch_qty", "fieldname": "actual_batch_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2405,6 +2511,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "actual_qty", "fieldname": "actual_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2438,6 +2545,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "edit_references", "fieldname": "edit_references",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -2470,6 +2578,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sales_order", "fieldname": "sales_order",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2504,6 +2613,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "so_detail", "fieldname": "so_detail",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2537,6 +2647,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_74", "fieldname": "column_break_74",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -2568,6 +2679,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "delivery_note", "fieldname": "delivery_note",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2602,6 +2714,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "dn_detail", "fieldname": "dn_detail",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -2635,6 +2748,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "delivered_qty", "fieldname": "delivered_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2668,6 +2782,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_fixed_asset", "fieldname": "is_fixed_asset",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 1, "hidden": 1,
@@ -2700,6 +2815,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "asset", "fieldname": "asset",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2733,6 +2849,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_54", "fieldname": "section_break_54",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -2764,6 +2881,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "page_break", "fieldname": "page_break",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2799,7 +2917,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2019-02-18 18:59:52.223628", "modified": "2019-03-18 14:03:13.084320",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice Item", "name": "Sales Invoice Item",

View File

@@ -20,6 +20,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:parent.doctype == 'POS Profile'", "depends_on": "eval:parent.doctype == 'POS Profile'",
"fetch_if_empty": 0,
"fieldname": "default", "fieldname": "default",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -52,6 +53,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "mode_of_payment", "fieldname": "mode_of_payment",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -85,8 +87,9 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "", "default": "0",
"depends_on": "eval:parent.doctype == 'Sales Invoice'", "depends_on": "eval:parent.doctype == 'Sales Invoice'",
"fetch_if_empty": 0,
"fieldname": "amount", "fieldname": "amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -120,6 +123,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3", "fieldname": "column_break_3",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -151,6 +155,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "account", "fieldname": "account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -185,6 +190,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_from": "mode_of_payment.type", "fetch_from": "mode_of_payment.type",
"fetch_if_empty": 0,
"fieldname": "type", "fieldname": "type",
"fieldtype": "Read Only", "fieldtype": "Read Only",
"hidden": 0, "hidden": 0,
@@ -218,6 +224,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount", "fieldname": "base_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -251,6 +258,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "clearance_date", "fieldname": "clearance_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -287,7 +295,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2019-02-18 15:03:59.720469", "modified": "2019-03-06 15:58:37.839241",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice Payment", "name": "Sales Invoice Payment",

View File

@@ -595,8 +595,10 @@ def get_party_shipping_address(doctype, name):
def get_partywise_advanced_payment_amount(party_type="Customer"): def get_partywise_advanced_payment_amount(party_type="Customer"):
data = frappe.db.sql(""" SELECT party, sum({0}) as amount data = frappe.db.sql(""" SELECT party, sum({0}) as amount
FROM `tabGL Entry` FROM `tabGL Entry`
WHERE party_type = %s and against_voucher is null GROUP BY party""" WHERE
.format(("credit - debit") if party_type == "Customer" else "debit") , party_type) party_type = %s and against_voucher is null
GROUP BY party"""
.format(("credit") if party_type == "Customer" else "debit") , party_type)
if data: if data:
return frappe._dict(data) return frappe._dict(data)

View File

@@ -0,0 +1,82 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<style>
.table-bordered td.top-bottom {border-top: none !important;border-bottom: none !important;}
.table-bordered td.right{border-right: none !important;}
.table-bordered td.left{border-left: none !important;}
</style>
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Payment Entry")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class="table table-bordered table-condensed">
<tr>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Amount</th>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
</tr>
{% set total_credit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.debit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
<td class="left top-bottom">{{ entries.credit }}</td>
{% set total_credit = total_credit + entries.credit -%}
</tr>
<tr>
<td class="top-bottom" colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
</tr>
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{total_credit}}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td class="top-bottom" colspan="4"> </td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
</tr>
{% set total_debit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.credit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
{% set total_debit = total_debit + entries.debit -%}
<td class="left top-bottom">{{ entries.debit }}</td>
</tr>
<tr>
<td class="top-bottom"colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
</tr>
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{total_debit}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 11:49:08.608619",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Payment Entry",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 11:49:08.608619",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank and Cash Payment Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<style>
.table-bordered td.top-bottom {border-top: none !important;border-bottom: none !important;}
.table-bordered td.right{border-right: none !important;}
.table-bordered td.left{border-left: none !important;}
</style>
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Journal Entry")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class="table table-bordered table-condensed">
<tr>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Amount</th>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
</tr>
{% set total_credit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.debit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
<td class="left top-bottom">{{ entries.credit }}</td>
{% set total_credit = total_credit + entries.credit -%}
</tr>
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{total_credit}}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td class="top-bottom" colspan="4"> </td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
</tr>
{% set total_debit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.credit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
{% set total_debit = total_debit + entries.debit -%}
<td class="left top-bottom">{{ entries.debit }}</td>
</tr>
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{total_debit}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 14:13:05.721784",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Journal Entry",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 14:13:05.721784",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -0,0 +1,99 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Purchase Invoice")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Supplier Name: </strong></td><td>{{ doc.supplier }}</td></tr>
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
<tr><td><strong>Address: </strong></td><td>{{doc.address_display}}</td></tr>
<tr><td><strong>Contact: </strong></td><td>{{doc.contact_display}}</td></tr>
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top margin-bottom">
<table class="table table-bordered table-condensed">
<tr>
<th>SL</th>
<th>Item Code</th>
<th>Item Name</th>
<th>UOM</th>
<th>Received Qty.</th>
<th>Rejected Qty</th>
<th>Qty</th>
<th>Basic Rate</th>
<th>Amount</th>
</tr>
{% for item in doc.items %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ item.item_code }}</td>
<td>{{ item.item_name }}</td>
<td>{{ item.uom }}</td>
<td>{{ item.received_qty }}</td>
<td>{{ item.rejected_qty }}</td>
<td>{{ item.qty}}</td>
<td>{{ item.rate }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
{% for tax in doc.taxes %}
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
{% endfor %}
<tr><td><strong> Taxes and Charges Added: </strong></td><td>{{ doc.taxes_and_charges_added }}</td></tr>
<tr><td><strong> Taxes and Charges Deducted: </strong></td><td>{{ doc.taxes_and_charges_deducted }}</td></tr>
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class='table table-bordered table-condensed'>
<tr>
<th>SL</th>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Credit Amount</th>
<th>Debit Amount</th>
</tr>
{% for entries in doc.gl_entries %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entries.account }}</td>
<td>{{ entries.party_type }}</td>
<td>{{ entries.party }}</td>
<td>{{ entries.credit }}</td>
<td>{{ entries.debit }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4"><strong>Total</strong></td>
<td>{{ doc.grand_total|flt }}</td>
<td>{{ doc.grand_total|flt }}</td>
</tr>
</table>
</div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-14 14:42:35.151611",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Purchase Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-14 14:42:35.151611",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -0,0 +1,93 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Sales Invoice")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Customer Name: </strong></td><td>{{ doc.customer }}</td></tr>
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
<tr><td><strong>Address: </strong></td><td>{{doc.address_display}}</td></tr>
<tr><td><strong>Contact: </strong></td><td>{{doc.contact_display}}</td></tr>
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top margin-bottom">
<table class="table table-bordered table-condensed">
<tr>
<th>SL</th>
<th>Item Code</th>
<th>Item Name</th>
<th>UOM</th>
<th>Quantity</th>
<th>Basic Rate</th>
<th>Amount</th>
</tr>
{% for item in doc.items %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ item.item_code }}</td>
<td>{{ item.item_name }}</td>
<td>{{ item.uom }}</td>
<td>{{ item.qty}}</td>
<td>{{ item.rate }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
{% for tax in doc.taxes %}
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
{% endfor %}
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class='table table-bordered table-condensed'>
<tr>
<th>SL</th>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Credit Amount</th>
<th>Debit Amount</th>
</tr>
{% for entries in doc.gl_entries %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entries.account }}</td>
<td>{{ entries.party_type }}</td>
<td>{{ entries.party }}</td>
<td>{{ entries.credit }}</td>
<td>{{ entries.debit }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4"><strong>Total</strong></td>
<td>{{ doc.grand_total|flt }}</td>
<td>{{ doc.grand_total|flt }}</td>
</tr>
</table>
</div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 15:02:51.454754",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 15:02:51.454754",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Payable"] = {
"fieldtype": "Link", "fieldtype": "Link",
"options": "Finance Book" "options": "Finance Book"
}, },
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value('company');
return {
filters: {
'company': company
}
}
}
},
{ {
"fieldname":"supplier", "fieldname":"supplier",
"label": __("Supplier"), "label": __("Supplier"),

View File

@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Payable Summary"] = {
"fieldtype": "Link", "fieldtype": "Link",
"options": "Finance Book" "options": "Finance Book"
}, },
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value('company');
return {
filters: {
'company': company
}
}
}
},
{ {
"fieldname":"supplier", "fieldname":"supplier",
"label": __("Supplier"), "label": __("Supplier"),

View File

@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link", "fieldtype": "Link",
"options": "Finance Book" "options": "Finance Book"
}, },
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value('company');
return {
filters: {
'company': company
}
}
}
},
{ {
"fieldname":"customer", "fieldname":"customer",
"label": __("Customer"), "label": __("Customer"),

View File

@@ -537,6 +537,13 @@ class ReceivablePayableReport(object):
where supplier_group=%s)""") where supplier_group=%s)""")
values.append(self.filters.get("supplier_group")) values.append(self.filters.get("supplier_group"))
if self.filters.get("cost_center"):
lft, rgt = frappe.get_cached_value("Cost Center",
self.filters.get("cost_center"), ['lft', 'rgt'])
conditions.append("""cost_center in (select name from `tabCost Center` where
lft >= {0} and rgt <= {1})""".format(lft, rgt))
accounts = [d.name for d in frappe.get_all("Account", accounts = [d.name for d in frappe.get_all("Account",
filters={"account_type": account_type, "company": self.filters.company})] filters={"account_type": account_type, "company": self.filters.company})]
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts))) conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))

View File

@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"fieldtype": "Link", "fieldtype": "Link",
"options": "Finance Book" "options": "Finance Book"
}, },
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value('company');
return {
filters: {
'company': company
}
}
}
},
{ {
"fieldname":"customer", "fieldname":"customer",
"label": __("Customer"), "label": __("Customer"),

View File

@@ -144,9 +144,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
row += [self.get_party_name(args.get("party_type"), party)] row += [self.get_party_name(args.get("party_type"), party)]
row += [partywise_advance_amount.get(party, 0)] row += [partywise_advance_amount.get(party, 0)]
paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0))
row += [ row += [
party_dict.invoiced_amt, party_dict.paid_amt, party_dict.credit_amt, party_dict.outstanding_amt, party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4,
] ]
@@ -205,7 +206,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
cols += ["invoiced_amt", "paid_amt", "credit_amt", cols += ["invoiced_amt", "paid_amt", "credit_amt",
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref", "outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref",
"pdc/lc_amount", "remaining_balance"] "pdc/lc_amount"]
if args.get("party_type") == "Supplier": if args.get("party_type") == "Supplier":
cols += ["supplier_group", "remarks"] cols += ["supplier_group", "remarks"]

View File

@@ -195,7 +195,7 @@ class PartyLedgerSummaryReport(object):
conditions = [""] conditions = [""]
if self.filters.company: if self.filters.company:
conditions.append("company=%(company)s") conditions.append("gle.company=%(company)s")
self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company) self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company)

View File

@@ -15,7 +15,7 @@
height: 37px; height: 37px;
} }
</style> </style>
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %} {% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) %}
{% if(letterhead) { %} {% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center"> <div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[letterhead].header %} {%= frappe.boot.letter_heads[letterhead].header %}

View File

@@ -126,7 +126,7 @@ def get_label(periodicity, from_date, to_date):
def get_data( def get_data(
company, root_type, balance_must_be, period_list, filters=None, 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 , total = True):
accounts = get_accounts(company, root_type) accounts = get_accounts(company, root_type)
if not accounts: if not accounts:
@@ -154,7 +154,7 @@ def get_data(
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 and total:
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)
return out return out
@@ -218,6 +218,9 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
"year_start_date": year_start_date, "year_start_date": year_start_date,
"year_end_date": year_end_date, "year_end_date": year_end_date,
"currency": company_currency, "currency": company_currency,
"include_in_gross": d.include_in_gross,
"account_type": d.account_type,
"is_group": d.is_group,
"opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be=="Debit" else -1), "opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be=="Debit" else -1),
"account_name": ('%s - %s' %(_(d.account_number), _(d.account_name)) "account_name": ('%s - %s' %(_(d.account_number), _(d.account_name))
if d.account_number else _(d.account_name)) if d.account_number else _(d.account_name))
@@ -285,7 +288,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
def get_accounts(company, root_type): def get_accounts(company, root_type):
return frappe.db.sql(""" return frappe.db.sql("""
select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name, include_in_gross, account_type, is_group, lft, rgt
from `tabAccount` from `tabAccount`
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True) where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)

View File

@@ -0,0 +1 @@
{% include "accounts/report/financial_statements.html" %}

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Gross and Net Profit Report"] = {
"filters": [
]
}
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Gross and Net Profit Report"] = $.extend({},
erpnext.financial_statements);
frappe.query_reports["Gross and Net Profit Report"]["filters"].push(
{
"fieldname":"project",
"label": __("Project"),
"fieldtype": "MultiSelect",
get_data: function() {
var projects = frappe.query_report.get_filter_value("project") || "";
const values = projects.split(/\s*,\s*/).filter(d => d);
const txt = projects.match(/[^,\s*]*$/)[0] || '';
let data = [];
frappe.call({
type: "GET",
method:'frappe.desk.search.search_link',
async: false,
no_spinner: true,
args: {
doctype: "Project",
txt: txt,
filters: {
"name": ["not in", values]
}
},
callback: function(r) {
data = r.results;
}
});
return data;
}
},
{
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),
"fieldtype": "Check"
}
);
});

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"creation": "2019-02-08 10:58:55.763090",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-02-08 10:58:55.763090",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Gross and Net Profit Report",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "GL Entry",
"report_name": "Gross and Net Profit Report",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
{
"role": "Accounts Manager"
},
{
"role": "Auditor"
}
]
}

View File

@@ -0,0 +1,154 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
import copy
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.accumulated_values, filters.company)
columns, data = [], []
income = get_data(filters.company, "Income", "Credit", period_list, filters = filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False)
expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company)
gross_income = get_revenue(income, period_list)
gross_expense = get_revenue(expense, period_list)
if(len(gross_income)==0 and len(gross_expense)== 0):
data.append({"account_name": "'" + _("Nothing is included in gross") + "'",
"account": "'" + _("Nothing is included in gross") + "'"})
return columns, data
data.append({"account_name": "'" + _("Included in Gross Profit") + "'",
"account": "'" + _("Included in Gross Profit") + "'"})
data.append({})
data.extend(gross_income or [])
data.append({})
data.extend(gross_expense or [])
data.append({})
gross_profit = get_profit(gross_income, gross_expense, period_list, filters.company, 'Gross Profit',filters.presentation_currency)
data.append(gross_profit)
non_gross_income = get_revenue(income, period_list, 0)
data.append({})
data.extend(non_gross_income or [])
non_gross_expense = get_revenue(expense, period_list, 0)
data.append({})
data.extend(non_gross_expense or [])
net_profit = get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, filters.company,filters.presentation_currency)
data.append({})
data.append(net_profit)
return columns, data
def get_revenue(data, period_list, include_in_gross=1):
revenue = [item for item in data if item['include_in_gross']==include_in_gross or item['is_group']==1]
data_to_be_removed =True
while data_to_be_removed:
revenue, data_to_be_removed = remove_parent_with_no_child(revenue, period_list)
revenue = adjust_account(revenue, period_list)
return copy.deepcopy(revenue)
def remove_parent_with_no_child(data, period_list):
data_to_be_removed = False
for parent in data:
if 'is_group' in parent and parent.get("is_group") == 1:
have_child = False
for child in data:
if 'parent_account' in child and child.get("parent_account") == parent.get("account"):
have_child = True
break
if not have_child:
data_to_be_removed = True
data.remove(parent)
return data, data_to_be_removed
def adjust_account(data, period_list, consolidated= False):
leaf_nodes = [item for item in data if item['is_group'] == 0]
totals = {}
for node in leaf_nodes:
set_total(node, node["total"], data, totals)
for d in data:
for period in period_list:
key = period if consolidated else period.key
d[key] = totals[d["account"]]
d['total'] = totals[d["account"]]
return data
def set_total(node, value, complete_list, totals):
if not totals.get(node['account']):
totals[node["account"]] = 0
totals[node["account"]] += value
parent = node['parent_account']
if not parent == '':
return set_total(next(item for item in complete_list if item['account'] == parent), value, complete_list, totals)
def get_profit(gross_income, gross_expense, period_list, company, profit_type, currency=None, consolidated=False):
profit_loss = {
"account_name": "'" + _(profit_type) + "'",
"account": "'" + _(profit_type) + "'",
"warn_if_negative": True,
"currency": currency or frappe.get_cached_value('Company', company, "default_currency")
}
has_value = False
for period in period_list:
key = period if consolidated else period.key
profit_loss[key] = flt(gross_income[0].get(key, 0)) - flt(gross_expense[0].get(key, 0))
if profit_loss[key]:
has_value=True
if has_value:
return profit_loss
def get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, company, currency=None, consolidated=False):
profit_loss = {
"account_name": "'" + _("Net Profit") + "'",
"account": "'" + _("Net Profit") + "'",
"warn_if_negative": True,
"currency": currency or frappe.get_cached_value('Company', company, "default_currency")
}
has_value = False
for period in period_list:
key = period if consolidated else period.key
total_income = flt(gross_income[0].get(key, 0)) + flt(non_gross_income[0].get(key, 0))
total_expense = flt(gross_expense[0].get(key, 0)) + flt(non_gross_expense[0].get(key, 0))
profit_loss[key] = flt(total_income) - flt(total_expense)
if profit_loss[key]:
has_value=True
if has_value:
return profit_loss

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _, scrub from frappe import _, scrub
from erpnext.stock.utils import get_incoming_rate from erpnext.stock.utils import get_incoming_rate
from erpnext.controllers.queries import get_match_cond from erpnext.controllers.queries import get_match_cond
from frappe.utils import flt from frappe.utils import flt, cint
def execute(filters=None): def execute(filters=None):
@@ -106,11 +106,14 @@ class GrossProfitGenerator(object):
self.grouped = {} self.grouped = {}
self.grouped_data = [] self.grouped_data = []
self.currency_precision = cint(frappe.db.get_default("currency_precision")) or 3
self.float_precision = cint(frappe.db.get_default("float_precision")) or 2
for row in self.si_list: for row in self.si_list:
if self.skip_row(row, self.product_bundles): if self.skip_row(row, self.product_bundles):
continue continue
row.base_amount = flt(row.base_net_amount) row.base_amount = flt(row.base_net_amount, self.currency_precision)
product_bundles = [] product_bundles = []
if row.update_stock: if row.update_stock:
@@ -122,22 +125,23 @@ class GrossProfitGenerator(object):
# get buying amount # get buying amount
if row.item_code in product_bundles: if row.item_code in product_bundles:
row.buying_amount = self.get_buying_amount_from_product_bundle(row, row.buying_amount = flt(self.get_buying_amount_from_product_bundle(row,
product_bundles[row.item_code]) product_bundles[row.item_code]), self.currency_precision)
else: else:
row.buying_amount = self.get_buying_amount(row, row.item_code) row.buying_amount = flt(self.get_buying_amount(row, row.item_code),
self.currency_precision)
# get buying rate # get buying rate
if row.qty: if row.qty:
row.buying_rate = row.buying_amount / row.qty row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision)
row.base_rate = row.base_amount / row.qty row.base_rate = flt(row.base_amount / row.qty, self.float_precision)
else: else:
row.buying_rate, row.base_rate = 0.0, 0.0 row.buying_rate, row.base_rate = 0.0, 0.0
# calculate gross profit # calculate gross profit
row.gross_profit = flt(row.base_amount - row.buying_amount, 3) row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision)
if row.base_amount: if row.base_amount:
row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, 3) row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, self.currency_precision)
else: else:
row.gross_profit_percent = 0.0 row.gross_profit_percent = 0.0
@@ -156,8 +160,8 @@ class GrossProfitGenerator(object):
new_row = row new_row = row
else: else:
new_row.qty += row.qty new_row.qty += row.qty
new_row.buying_amount += row.buying_amount new_row.buying_amount += flt(row.buying_amount, self.currency_precision)
new_row.base_amount += row.base_amount new_row.base_amount += flt(row.base_amount, self.currency_precision)
new_row = self.set_average_rate(new_row) new_row = self.set_average_rate(new_row)
self.grouped_data.append(new_row) self.grouped_data.append(new_row)
else: else:
@@ -167,18 +171,19 @@ class GrossProfitGenerator(object):
returned_item_rows = self.returned_invoices[row.parent][row.item_code] returned_item_rows = self.returned_invoices[row.parent][row.item_code]
for returned_item_row in returned_item_rows: for returned_item_row in returned_item_rows:
row.qty += returned_item_row.qty row.qty += returned_item_row.qty
row.base_amount += returned_item_row.base_amount row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
row.buying_amount = row.qty * row.buying_rate row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision)
if row.qty or row.base_amount: if row.qty or row.base_amount:
row = self.set_average_rate(row) row = self.set_average_rate(row)
self.grouped_data.append(row) self.grouped_data.append(row)
def set_average_rate(self, new_row): def set_average_rate(self, new_row):
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount,3) new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision)
new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0),3) \ new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \
if new_row.base_amount else 0 if new_row.base_amount else 0
new_row.buying_rate = (new_row.buying_amount / new_row.qty) if new_row.qty else 0 new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0
new_row.base_rate = (new_row.base_amount / new_row.qty) if new_row.qty else 0 new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0
return new_row return new_row
def get_returned_invoice_items(self): def get_returned_invoice_items(self):
@@ -211,7 +216,7 @@ class GrossProfitGenerator(object):
if packed_item.get("parent_detail_docname")==row.item_row: if packed_item.get("parent_detail_docname")==row.item_row:
buying_amount += self.get_buying_amount(row, packed_item.item_code) buying_amount += self.get_buying_amount(row, packed_item.item_code)
return buying_amount return flt(buying_amount, self.currency_precision)
def get_buying_amount(self, row, item_code): def get_buying_amount(self, row, item_code):
# IMP NOTE # IMP NOTE

View File

@@ -66,8 +66,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
total_tax += tax_amount total_tax += tax_amount
row.append(tax_amount) row.append(tax_amount)
# total tax, grand total, outstanding amount & rounded total # total tax, grand total, rounded total & outstanding amount
row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount] row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount]
data.append(row) data.append(row)
return columns, data return columns, data

View File

@@ -35,9 +35,9 @@ frappe.query_reports["Supplier Ledger Summary"] = {
}, },
{ {
"fieldname":"party", "fieldname":"party",
"label": __("Customer"), "label": __("Supplier"),
"fieldtype": "Link", "fieldtype": "Link",
"options": "Customer", "options": "Supplier",
on_change: () => { on_change: () => {
var party = frappe.query_report.get_filter_value('party'); var party = frappe.query_report.get_filter_value('party');
if (party) { if (party) {

View File

@@ -544,14 +544,14 @@ def fix_total_debit_credit():
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr), (dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no)) (d.diff, d.voucher_type, d.voucher_no))
def get_stock_and_account_difference(account_list=None, posting_date=None): def get_stock_and_account_difference(account_list=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map from erpnext.stock import get_warehouse_account_map
if not posting_date: posting_date = nowdate() if not posting_date: posting_date = nowdate()
difference = {} difference = {}
warehouse_account = get_warehouse_account_map() warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account): for warehouse, account_data in iteritems(warehouse_account):
if account_data.get('account') in account_list: if account_data.get('account') in account_list:

View File

@@ -33,7 +33,7 @@ class Asset(AccountsController):
self.validate_in_use_date() self.validate_in_use_date()
self.set_status() self.set_status()
self.update_stock_movement() self.update_stock_movement()
if not self.booked_fixed_asset: if not self.booked_fixed_asset and not is_cwip_accounting_disabled():
self.make_gl_entries() self.make_gl_entries()
def on_cancel(self): def on_cancel(self):
@@ -71,14 +71,15 @@ class Asset(AccountsController):
if not flt(self.gross_purchase_amount): if not flt(self.gross_purchase_amount):
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice): if not is_cwip_accounting_disabled():
frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}"). if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice):
format(self.item_code)) frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}").
format(self.item_code))
if (not self.purchase_receipt and self.purchase_invoice if (not self.purchase_receipt and self.purchase_invoice
and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')): and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')):
frappe.throw(_("Update stock must be enable for the purchase invoice {0}"). frappe.throw(_("Update stock must be enable for the purchase invoice {0}").
format(self.purchase_invoice)) format(self.purchase_invoice))
if not self.calculate_depreciation: if not self.calculate_depreciation:
return return
@@ -255,7 +256,7 @@ class Asset(AccountsController):
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row): def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0 percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
factor = percentage_value / total_number_of_depreciations factor = percentage_value / cint(total_number_of_depreciations)
depreciation_amount = flt(depreciable_value * factor / 100, 0) depreciation_amount = flt(depreciable_value * factor / 100, 0)
value_after_depreciation = flt(depreciable_value) - depreciation_amount value_after_depreciation = flt(depreciable_value) - depreciation_amount
@@ -275,7 +276,7 @@ class Asset(AccountsController):
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) - flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis cint(self.number_of_depreciations_booked)) * prorata_temporis
else: else:
depreciation_amount = self.get_depreciation_amount(depreciable_value, row) depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
return depreciation_amount return depreciation_amount
@@ -404,6 +405,9 @@ def update_maintenance_status():
asset.set_status('Out of Order') asset.set_status('Out of Order')
def make_post_gl_entry(): def make_post_gl_entry():
if is_cwip_accounting_disabled():
return
assets = frappe.db.sql_list(""" select name from `tabAsset` assets = frappe.db.sql_list(""" select name from `tabAsset`
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate()) where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
@@ -551,3 +555,6 @@ def make_journal_entry(asset_name):
}) })
return je return je
def is_cwip_accounting_disabled():
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))

View File

@@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
@@ -14,10 +15,12 @@
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "depreciation_options", "fieldname": "depreciation_options",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -40,14 +43,17 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "schedule_based_on_fiscal_year", "fieldname": "schedule_based_on_fiscal_year",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -70,10 +76,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -81,6 +89,7 @@
"default": "360", "default": "360",
"depends_on": "eval:doc.schedule_based_on_fiscal_year", "depends_on": "eval:doc.schedule_based_on_fiscal_year",
"description": "This value is used for pro-rata temporis calculation", "description": "This value is used for pro-rata temporis calculation",
"fetch_if_empty": 0,
"fieldname": "number_of_days_in_fiscal_year", "fieldname": "number_of_days_in_fiscal_year",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -103,6 +112,40 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disable_cwip_accounting",
"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": "Disable CWIP Accounting",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
} }
], ],
@@ -116,7 +159,7 @@
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-01-05 10:10:39.803255", "modified": "2019-03-08 10:44:41.924547",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Assets", "module": "Assets",
"name": "Asset Settings", "name": "Asset Settings",
@@ -125,7 +168,6 @@
"permissions": [ "permissions": [
{ {
"amend": 0, "amend": 0,
"apply_user_permissions": 0,
"cancel": 0, "cancel": 0,
"create": 1, "create": 1,
"delete": 1, "delete": 1,
@@ -145,7 +187,6 @@
}, },
{ {
"amend": 0, "amend": 0,
"apply_user_permissions": 0,
"cancel": 0, "cancel": 0,
"create": 1, "create": 1,
"delete": 1, "delete": 1,
@@ -171,5 +212,6 @@
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 0,
"track_views": 0
} }

View File

@@ -25,6 +25,9 @@ frappe.ui.form.on("Purchase Order", {
frm.set_indicator_formatter('item_code', frm.set_indicator_formatter('item_code',
function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" }) function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
frm.set_indicator_formatter('pricing_rule',
function(doc) { return (doc.rule_applied) ? "green" : "red" })
frm.set_query("blanket_order", "items", function() { frm.set_query("blanket_order", "items", function() {
return { return {
filters: { filters: {

View File

@@ -298,7 +298,7 @@
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 0,
"label": "Date", "label": "Date",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
@@ -1548,6 +1548,72 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "section_break_48",
"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": "Pricing Rules",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"fieldname": "pricing_rules",
"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": "Purchase Order Pricing Rule",
"length": 0,
"no_copy": 0,
"options": "Pricing Rule Detail",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -1914,7 +1980,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "tax_category", "description": "",
"fieldname": "taxes_and_charges",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
@@ -1923,12 +1990,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": "Tax Category", "label": "Taxes and Charges",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Tax Category", "oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
@@ -2035,41 +2103,6 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "taxes_and_charges",
"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": "Purchase Taxes and Charges Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"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,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -2914,7 +2947,6 @@
"label": "Rounded Total", "label": "Rounded Total",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "currency",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@@ -3865,7 +3897,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-12-27 02:04:14.410491", "modified": "2019-02-14 19:36:49.390935",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Purchase Order", "name": "Purchase Order",

View File

@@ -391,9 +391,10 @@ def make_purchase_invoice(source_name, target_doc=None):
item = get_item_defaults(target.item_code, source_parent.company) item = get_item_defaults(target.item_code, source_parent.company)
item_group = get_item_group_defaults(target.item_code, source_parent.company) item_group = get_item_group_defaults(target.item_code, source_parent.company)
target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \ target.cost_center = (obj.cost_center
or item.get("buying_cost_center") \ or frappe.db.get_value("Project", obj.project, "cost_center")
or item_group.get("buying_cost_center") or item.get("buying_cost_center")
or item_group.get("buying_cost_center"))
doc = get_mapped_doc("Purchase Order", source_name, { doc = get_mapped_doc("Purchase Order", source_name, {
"Purchase Order": { "Purchase Order": {

View File

@@ -21,6 +21,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 3, "columns": 3,
"fetch_if_empty": 0,
"fieldname": "item_code", "fieldname": "item_code",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -56,6 +57,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "", "description": "",
"fetch_if_empty": 0,
"fieldname": "supplier_part_no", "fieldname": "supplier_part_no",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -87,6 +89,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_name", "fieldname": "item_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -120,6 +123,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "column_break_4", "fieldname": "column_break_4",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -151,6 +156,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"fetch_if_empty": 0,
"fieldname": "schedule_date", "fieldname": "schedule_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -184,6 +190,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "expected_delivery_date", "fieldname": "expected_delivery_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@@ -216,6 +223,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_5", "fieldname": "section_break_5",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -248,6 +256,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text Editor", "fieldtype": "Text Editor",
"hidden": 0, "hidden": 0,
@@ -283,6 +292,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break1", "fieldname": "col_break1",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -313,6 +323,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image", "fieldname": "image",
"fieldtype": "Attach", "fieldtype": "Attach",
"hidden": 1, "hidden": 1,
@@ -345,6 +356,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "image_view", "fieldname": "image_view",
"fieldtype": "Image", "fieldtype": "Image",
"hidden": 0, "hidden": 0,
@@ -378,6 +390,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "quantity_and_rate", "fieldname": "quantity_and_rate",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -409,6 +422,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 1, "columns": 1,
"fetch_if_empty": 0,
"fieldname": "qty", "fieldname": "qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -444,6 +458,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_uom", "fieldname": "stock_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -460,7 +475,7 @@
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "UOM", "options": "UOM",
"permlevel": 0, "permlevel": 0,
"print_hide": 1, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
@@ -480,6 +495,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break2", "fieldname": "col_break2",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -511,6 +527,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "uom", "fieldname": "uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -547,6 +564,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "conversion_factor", "fieldname": "conversion_factor",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -583,6 +601,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_break1", "fieldname": "sec_break1",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -613,6 +632,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "price_list_rate", "fieldname": "price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -646,6 +667,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "price_list_rate", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_percentage", "fieldname": "discount_percentage",
"fieldtype": "Percent", "fieldtype": "Percent",
"hidden": 0, "hidden": 0,
@@ -677,7 +699,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "discount_percentage", "depends_on": "price_list_rate",
"fetch_if_empty": 0,
"fieldname": "discount_amount", "fieldname": "discount_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -695,7 +718,7 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@@ -711,6 +734,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break3", "fieldname": "col_break3",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -741,6 +765,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "last_purchase_rate", "fieldname": "last_purchase_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -774,6 +799,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_price_list_rate", "fieldname": "base_price_list_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -806,6 +832,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_break2", "fieldname": "sec_break2",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -836,6 +863,8 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "rate", "fieldname": "rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -870,6 +899,8 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 2, "columns": 2,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "amount", "fieldname": "amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -904,6 +935,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break4", "fieldname": "col_break4",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -934,6 +966,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rate", "fieldname": "base_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -971,6 +1004,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount", "fieldname": "base_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1005,20 +1039,21 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "pricing_rule", "fetch_if_empty": 0,
"fieldtype": "Link", "fieldname": "pricing_rules",
"hidden": 0, "fieldtype": "Small Text",
"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": "Pricing Rule", "label": "Pricing Rules",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Pricing Rule",
"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": 1, "read_only": 1,
@@ -1037,6 +1072,40 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_free_item",
"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": "Is Free Item",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_29", "fieldname": "section_break_29",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1068,6 +1137,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_rate", "fieldname": "net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1101,6 +1171,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_amount", "fieldname": "net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1134,6 +1205,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_32", "fieldname": "column_break_32",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1165,6 +1237,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_rate", "fieldname": "base_net_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1198,6 +1271,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_amount", "fieldname": "base_net_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1231,6 +1305,7 @@
"bold": 0, "bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "item_weight_details", "fieldname": "item_weight_details",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1263,6 +1338,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_per_unit", "fieldname": "weight_per_unit",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1295,6 +1371,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_weight", "fieldname": "total_weight",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -1327,6 +1404,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_40", "fieldname": "column_break_40",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1358,6 +1436,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "weight_uom", "fieldname": "weight_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1391,6 +1470,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "warehouse_and_reference", "fieldname": "warehouse_and_reference",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1422,6 +1502,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "warehouse", "fieldname": "warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1456,6 +1537,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "project", "fieldname": "project",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1488,6 +1570,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "material_request", "fieldname": "material_request",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1524,6 +1607,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "material_request_item", "fieldname": "material_request_item",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -1557,6 +1641,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sales_order", "fieldname": "sales_order",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1590,6 +1675,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "sales_order_item", "fieldname": "sales_order_item",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@@ -1622,6 +1708,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "supplier_quotation", "fieldname": "supplier_quotation",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1654,6 +1741,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "supplier_quotation_item", "fieldname": "supplier_quotation_item",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -1686,6 +1774,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "delivered_by_supplier", "fieldname": "delivered_by_supplier",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -1718,6 +1807,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "blanket_order", "fieldname": "blanket_order",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1751,6 +1841,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "blanket_order_rate", "fieldname": "blanket_order_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -1783,6 +1874,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break5", "fieldname": "col_break5",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -1814,6 +1906,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "", "description": "",
"fetch_if_empty": 0,
"fieldname": "item_group", "fieldname": "item_group",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -1848,6 +1941,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "brand", "fieldname": "brand",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1, "hidden": 1,
@@ -1882,6 +1976,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "bom", "fieldname": "bom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -1917,6 +2012,7 @@
"columns": 0, "columns": 0,
"default": "1", "default": "1",
"depends_on": "eval:parent.is_subcontracted == 'Yes'", "depends_on": "eval:parent.is_subcontracted == 'Yes'",
"fetch_if_empty": 0,
"fieldname": "include_exploded_items", "fieldname": "include_exploded_items",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -1949,6 +2045,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_56", "fieldname": "section_break_56",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -1980,6 +2077,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2015,6 +2113,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "received_qty", "fieldname": "received_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2049,6 +2148,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "returned_qty", "depends_on": "returned_qty",
"fetch_if_empty": 0,
"fieldname": "returned_qty", "fieldname": "returned_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@@ -2081,6 +2181,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_60", "fieldname": "column_break_60",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -2112,6 +2213,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "billed_amt", "fieldname": "billed_amt",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@@ -2145,6 +2247,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges", "description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges",
"fetch_if_empty": 0,
"fieldname": "item_tax_rate", "fieldname": "item_tax_rate",
"fieldtype": "Code", "fieldtype": "Code",
"hidden": 1, "hidden": 1,
@@ -2178,6 +2281,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "accounting_details", "fieldname": "accounting_details",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@@ -2210,6 +2314,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "expense_account", "fieldname": "expense_account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2243,39 +2348,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "item_tax_template", "fetch_if_empty": 0,
"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": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_68", "fieldname": "column_break_68",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": 0, "hidden": 0,
@@ -2307,6 +2380,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "cost_center", "fieldname": "cost_center",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -2340,6 +2414,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fetch_if_empty": 0,
"fieldname": "page_break", "fieldname": "page_break",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@@ -2377,7 +2452,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-11-23 16:53:57.220731", "modified": "2019-03-19 03:00:17.096662",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Purchase Order Item", "name": "Purchase Order Item",
@@ -2386,6 +2461,7 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"search_fields": "item_name",
"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

@@ -1,11 +1,16 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from frappe import _ from frappe import _
def get_data(): def get_data():
return { return {
'heatmap': True, 'heatmap': True,
'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'), 'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'),
'fieldname': 'supplier', 'fieldname': 'supplier',
'non_standard_fieldnames': {
'Payment Entry': 'party_name'
},
'transactions': [ 'transactions': [
{ {
'label': _('Procurement'), 'label': _('Procurement'),
@@ -15,6 +20,10 @@ def get_data():
'label': _('Orders'), 'label': _('Orders'),
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'] 'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
}, },
{
'label': _('Payments'),
'items': ['Payment Entry']
},
{ {
'label': _('Pricing'), 'label': _('Pricing'),
'items': ['Pricing Rule'] 'items': ['Pricing Rule']

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