mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
Merge branch 'hotfix'
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
__version__ = '7.1.23'
|
__version__ = '7.1.24'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ frappe.treeview_settings["Account"] = {
|
|||||||
description: __("Optional. This setting will be used to filter in various transactions.")
|
description: __("Optional. This setting will be used to filter in various transactions.")
|
||||||
},
|
},
|
||||||
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
|
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
|
||||||
depends_on: 'eval:doc.is_group==1&&doc.account_type=="Tax"'},
|
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"'},
|
||||||
{fieldtype:'Link', fieldname:'warehouse', label:__('Warehouse'), options:"Warehouse",
|
{fieldtype:'Link', fieldname:'warehouse', label:__('Warehouse'), options:"Warehouse",
|
||||||
depends_on: 'eval:(!doc.is_group&&doc.account_type=="Stock")',
|
depends_on: 'eval:(!doc.is_group&&doc.account_type=="Stock")',
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -86,6 +88,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -112,6 +115,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -138,6 +142,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -163,6 +168,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -190,6 +196,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -217,6 +224,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -245,6 +253,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -273,6 +282,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -300,6 +310,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -325,6 +336,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -351,6 +363,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -378,6 +391,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -404,6 +418,7 @@
|
|||||||
"print_hide": 1,
|
"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,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -416,7 +431,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "payment_url",
|
"fieldname": "payment_url",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Small Text",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@@ -430,6 +445,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -457,6 +473,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -484,6 +501,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -511,6 +529,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -537,6 +556,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -564,6 +584,7 @@
|
|||||||
"print_hide": 1,
|
"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,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -591,6 +612,7 @@
|
|||||||
"print_hide": 1,
|
"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,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -617,6 +639,7 @@
|
|||||||
"print_hide": 1,
|
"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,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -634,7 +657,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-09-02 04:07:15.279949",
|
"modified": "2016-12-12 13:30:42.858205",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Request",
|
"name": "Payment Request",
|
||||||
@@ -651,6 +674,7 @@
|
|||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
|
"is_custom": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
@@ -671,6 +695,7 @@
|
|||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
|
"is_custom": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
|
|||||||
@@ -26,30 +26,6 @@ frappe.ui.form.on("POS Profile", "onload", function(frm) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("POS Profile", {
|
|
||||||
setup: function(frm) {
|
|
||||||
frm.trigger("get_query_for_groups")
|
|
||||||
},
|
|
||||||
|
|
||||||
get_query_for_groups: function(frm) {
|
|
||||||
frm.fields_dict['item_groups'].grid.get_field('item_group').get_query = function(frm, cdt, cdn) {
|
|
||||||
return{
|
|
||||||
filters: {
|
|
||||||
'is_group': 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
frm.fields_dict['customer_groups'].grid.get_field('customer_group').get_query = function(frm, cdt, cdn) {
|
|
||||||
return{
|
|
||||||
filters: {
|
|
||||||
'is_group': 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Income Account
|
// Income Account
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) {
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ def get_pricing_rule_for_item(args):
|
|||||||
})
|
})
|
||||||
|
|
||||||
if args.ignore_pricing_rule or not args.item_code:
|
if args.ignore_pricing_rule or not args.item_code:
|
||||||
|
if args.name and args.get("pricing_rule"):
|
||||||
|
item_details = remove_pricing_rule(args, item_details)
|
||||||
return item_details
|
return item_details
|
||||||
|
|
||||||
if not (args.item_group and args.brand):
|
if not (args.item_group and args.brand):
|
||||||
@@ -166,9 +168,16 @@ def get_pricing_rule_for_item(args):
|
|||||||
else:
|
else:
|
||||||
item_details.discount_percentage = pricing_rule.discount_percentage
|
item_details.discount_percentage = pricing_rule.discount_percentage
|
||||||
elif args.get('pricing_rule'):
|
elif args.get('pricing_rule'):
|
||||||
if frappe.db.get_value('Pricing Rule', args.get('pricing_rule'), 'price_or_discount') == 'Discount Percentage':
|
item_details = remove_pricing_rule(args, item_details)
|
||||||
item_details.discount_percentage = 0.0
|
|
||||||
|
|
||||||
|
return item_details
|
||||||
|
|
||||||
|
def remove_pricing_rule(args, item_details):
|
||||||
|
pricing_rule = frappe.db.get_value('Pricing Rule', args.get('pricing_rule'), ['price_or_discount', 'margin_type'], as_dict=1)
|
||||||
|
if pricing_rule and pricing_rule.price_or_discount == 'Discount Percentage':
|
||||||
|
item_details.discount_percentage = 0.0
|
||||||
|
|
||||||
|
if pricing_rule and pricing_rule.margin_type in ['Percentage', 'Amount']:
|
||||||
item_details.margin_rate_or_amount = 0.0
|
item_details.margin_rate_or_amount = 0.0
|
||||||
item_details.margin_type = None
|
item_details.margin_type = None
|
||||||
|
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ def get_items_list(pos_profile):
|
|||||||
item_groups = []
|
item_groups = []
|
||||||
if pos_profile.get('item_groups'):
|
if pos_profile.get('item_groups'):
|
||||||
# Get items based on the item groups defined in the POS profile
|
# Get items based on the item groups defined in the POS profile
|
||||||
|
for d in pos_profile.get('item_groups'):
|
||||||
cond = "item_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('item_groups'))))
|
item_groups.extend(get_child_nodes('Item Group', d.item_group))
|
||||||
item_groups = [d.item_group for d in pos_profile.get('item_groups')]
|
cond = "item_group in (%s)"%(', '.join(['%s']*len(item_groups)))
|
||||||
|
|
||||||
return frappe.db.sql("""
|
return frappe.db.sql("""
|
||||||
select
|
select
|
||||||
@@ -135,14 +135,19 @@ def get_customers_list(pos_profile):
|
|||||||
customer_groups = []
|
customer_groups = []
|
||||||
if pos_profile.get('customer_groups'):
|
if pos_profile.get('customer_groups'):
|
||||||
# Get customers based on the customer groups defined in the POS profile
|
# Get customers based on the customer groups defined in the POS profile
|
||||||
|
for d in pos_profile.get('customer_groups'):
|
||||||
cond = "customer_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('customer_groups'))))
|
customer_groups.extend(get_child_nodes('Customer Group', d.customer_group))
|
||||||
customer_groups = [d.customer_group for d in pos_profile.get('customer_groups')]
|
cond = "customer_group in (%s)"%(', '.join(['%s']*len(customer_groups)))
|
||||||
|
|
||||||
return frappe.db.sql(""" select name, customer_name, customer_group,
|
return frappe.db.sql(""" select name, customer_name, customer_group,
|
||||||
territory from tabCustomer where disabled = 0
|
territory from tabCustomer where disabled = 0
|
||||||
and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
|
and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
|
||||||
|
|
||||||
|
def get_child_nodes(group_type, root):
|
||||||
|
lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
|
||||||
|
return frappe.db.sql_list(""" Select name from `tab{tab}` where
|
||||||
|
lft >= {lft} and rgt <= {rgt}""".format(tab=group_type, lft=lft, rgt=rgt))
|
||||||
|
|
||||||
def get_serial_no_data(pos_profile, company):
|
def get_serial_no_data(pos_profile, company):
|
||||||
# get itemwise serial no data
|
# get itemwise serial no data
|
||||||
# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
|
# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
|
||||||
@@ -240,8 +245,7 @@ def make_invoice(doc_list):
|
|||||||
|
|
||||||
for docs in doc_list:
|
for docs in doc_list:
|
||||||
for name, doc in docs.items():
|
for name, doc in docs.items():
|
||||||
if not frappe.db.exists('Sales Invoice',
|
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
||||||
{'offline_pos_name': name, 'docstatus': ("<", "2")}):
|
|
||||||
validate_records(doc)
|
validate_records(doc)
|
||||||
si_doc = frappe.new_doc('Sales Invoice')
|
si_doc = frappe.new_doc('Sales Invoice')
|
||||||
si_doc.offline_pos_name = name
|
si_doc.offline_pos_name = name
|
||||||
@@ -286,6 +290,7 @@ def submit_invoice(si_doc, name):
|
|||||||
try:
|
try:
|
||||||
si_doc.insert()
|
si_doc.insert()
|
||||||
si_doc.submit()
|
si_doc.submit()
|
||||||
|
frappe.db.commit()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if frappe.message_log: frappe.message_log.pop()
|
if frappe.message_log: frappe.message_log.pop()
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
|
|||||||
@@ -223,7 +223,6 @@ class SalarySlip(TransactionBase):
|
|||||||
["date_of_joining", "relieving_date"])
|
["date_of_joining", "relieving_date"])
|
||||||
|
|
||||||
holidays = self.get_holidays_for_employee(self.start_date, self.end_date)
|
holidays = self.get_holidays_for_employee(self.start_date, self.end_date)
|
||||||
|
|
||||||
working_days = date_diff(self.end_date, self.start_date) + 1
|
working_days = date_diff(self.end_date, self.start_date) + 1
|
||||||
if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
|
if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
|
||||||
working_days -= len(holidays)
|
working_days -= len(holidays)
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"company": "_Test Company",
|
|
||||||
"doctype": "Salary Slip",
|
|
||||||
"deductions": [
|
|
||||||
{
|
|
||||||
"doctype": "Salary Detail",
|
|
||||||
"amount": 100,
|
|
||||||
"depends_on_lwp": 0,
|
|
||||||
"salary_component": "_Test Professional Tax",
|
|
||||||
"parentfield": "deductions"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Salary Detail",
|
|
||||||
"amount": 48.39,
|
|
||||||
"depends_on_lwp": 0,
|
|
||||||
"salary_component": "_Test TDS",
|
|
||||||
"parentfield": "deductions"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"earnings": [
|
|
||||||
{
|
|
||||||
"doctype": "Salary Detail",
|
|
||||||
"amount": 14516.13,
|
|
||||||
"depends_on_lwp": 0,
|
|
||||||
"salary_component": "_Test Basic Salary",
|
|
||||||
"parentfield": "earnings"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Salary Detail",
|
|
||||||
"amount": 500,
|
|
||||||
"depends_on_lwp": 0,
|
|
||||||
"salary_component": "_Test Allowance",
|
|
||||||
"parentfield": "earnings"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"employee_name": "_Test Employee",
|
|
||||||
"posting_date": "2013-02-01",
|
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
|
||||||
"month": "01",
|
|
||||||
"payment_days": 31,
|
|
||||||
"total_days_in_month": 31
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -5,32 +5,31 @@ from __future__ import unicode_literals
|
|||||||
import unittest
|
import unittest
|
||||||
import frappe
|
import frappe
|
||||||
import erpnext
|
import erpnext
|
||||||
from frappe.utils.make_random import get_random
|
import calendar
|
||||||
from frappe.utils import today, now_datetime, getdate, cstr, add_years, nowdate
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
from frappe.utils import getdate, nowdate, add_days
|
||||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||||
from erpnext.hr.doctype.process_payroll.test_process_payroll import get_salary_component_account
|
from erpnext.hr.doctype.process_payroll.test_process_payroll import get_salary_component_account
|
||||||
|
|
||||||
class TestSalarySlip(unittest.TestCase):
|
class TestSalarySlip(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
make_salary_component(["Basic Salary", "Allowance", "HRA", "Professional Tax", "TDS"])
|
make_earning_salary_component(["Basic Salary", "Allowance", "HRA"])
|
||||||
|
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||||
|
|
||||||
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
self.make_holiday_list()
|
self.make_holiday_list()
|
||||||
|
|
||||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
|
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
|
||||||
|
|
||||||
from erpnext.hr.doctype.leave_application.test_leave_application import _test_records as leave_applications
|
|
||||||
la = frappe.copy_doc(leave_applications[2])
|
|
||||||
la.insert()
|
|
||||||
la.status = "Approved"
|
|
||||||
la.submit()
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
def test_salary_slip_with_holidays_included(self):
|
def test_salary_slip_with_holidays_included(self):
|
||||||
|
no_of_days = self.get_no_of_days()
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
@@ -38,8 +37,8 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 31)
|
self.assertEquals(ss.total_days_in_month, no_of_days[0])
|
||||||
self.assertEquals(ss.payment_days, 31)
|
self.assertEquals(ss.payment_days, no_of_days[0])
|
||||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||||
self.assertEquals(ss.earnings[1].amount, 3000)
|
self.assertEquals(ss.earnings[1].amount, 3000)
|
||||||
self.assertEquals(ss.deductions[0].amount, 5000)
|
self.assertEquals(ss.deductions[0].amount, 5000)
|
||||||
@@ -48,6 +47,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
self.assertEquals(ss.net_pay, 3000)
|
self.assertEquals(ss.net_pay, 3000)
|
||||||
|
|
||||||
def test_salary_slip_with_holidays_excluded(self):
|
def test_salary_slip_with_holidays_excluded(self):
|
||||||
|
no_of_days = self.get_no_of_days()
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
@@ -55,8 +55,8 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_days_in_month, no_of_days[0] - no_of_days[1])
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, no_of_days[0] - no_of_days[1])
|
||||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||||
self.assertEquals(ss.earnings[0].default_amount, 5000)
|
self.assertEquals(ss.earnings[0].default_amount, 5000)
|
||||||
self.assertEquals(ss.earnings[1].amount, 3000)
|
self.assertEquals(ss.earnings[1].amount, 3000)
|
||||||
@@ -66,37 +66,46 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
self.assertEquals(ss.net_pay, 3000)
|
self.assertEquals(ss.net_pay, 3000)
|
||||||
|
|
||||||
def test_payment_days(self):
|
def test_payment_days(self):
|
||||||
|
no_of_days = self.get_no_of_days()
|
||||||
# Holidays not included in working days
|
# Holidays not included in working days
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
||||||
|
|
||||||
# set joinng date in the same month
|
# set joinng date in the same month
|
||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", "2013-01-11")
|
if getdate(nowdate()).day > 15:
|
||||||
|
date_of_joining = getdate(add_days(nowdate(),-10))
|
||||||
|
relieving_date = getdate(add_days(nowdate(),-10))
|
||||||
|
elif getdate(nowdate()).day < 15 and getdate(nowdate()).day > 5:
|
||||||
|
date_of_joining = getdate(add_days(nowdate(),-3))
|
||||||
|
relieving_date = getdate(add_days(nowdate(),-3))
|
||||||
|
elif getdate(nowdate()).day < 5 and not getdate(nowdate()).day == 1:
|
||||||
|
date_of_joining = getdate(add_days(nowdate(),-1))
|
||||||
|
relieving_date = getdate(add_days(nowdate(),-1))
|
||||||
|
elif getdate(nowdate()).day == 1:
|
||||||
|
date_of_joining = getdate(nowdate())
|
||||||
|
relieving_date = getdate(nowdate())
|
||||||
|
|
||||||
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", date_of_joining)
|
||||||
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
||||||
|
|
||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_days_in_month, no_of_days[0])
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, (no_of_days[0] - getdate(date_of_joining).day + 1))
|
||||||
|
|
||||||
# set relieving date in the same month
|
# set relieving date in the same month
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", "12-12-2016")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
|
||||||
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", relieving_date)
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
|
||||||
self.assertEquals(ss.payment_days, 28)
|
|
||||||
ss.save()
|
ss.save()
|
||||||
|
|
||||||
|
self.assertEquals(ss.total_days_in_month, no_of_days[0])
|
||||||
|
self.assertEquals(ss.payment_days, getdate(relieving_date).day)
|
||||||
|
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
||||||
# Holidays included in working days
|
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
|
||||||
self.assertEquals(ss.payment_days, 28)
|
|
||||||
ss.save()
|
|
||||||
#
|
|
||||||
# frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", "2001-01-11")
|
|
||||||
# frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
|
||||||
|
|
||||||
def test_employee_salary_slip_read_permission(self):
|
def test_employee_salary_slip_read_permission(self):
|
||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
@@ -120,7 +129,6 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
email_queue = frappe.db.sql("""select name from `tabEmail Queue`""")
|
email_queue = frappe.db.sql("""select name from `tabEmail Queue`""")
|
||||||
self.assertTrue(email_queue)
|
self.assertTrue(email_queue)
|
||||||
|
|
||||||
|
|
||||||
def make_employee(self, user):
|
def make_employee(self, user):
|
||||||
if not frappe.db.get_value("User", user):
|
if not frappe.db.get_value("User", user):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
@@ -148,29 +156,30 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
"status": "Active",
|
"status": "Active",
|
||||||
"employment_type": "Intern"
|
"employment_type": "Intern"
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
def make_holiday_list(self):
|
def make_holiday_list(self):
|
||||||
|
fiscal_year = get_fiscal_year(nowdate())
|
||||||
if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
|
if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
|
||||||
holiday_list = frappe.get_doc({
|
holiday_list = frappe.get_doc({
|
||||||
"doctype": "Holiday List",
|
"doctype": "Holiday List",
|
||||||
"holiday_list_name": "Salary Slip Test Holiday List",
|
"holiday_list_name": "Salary Slip Test Holiday List",
|
||||||
"from_date": nowdate(),
|
"from_date": fiscal_year[1],
|
||||||
"to_date": add_years(nowdate(), 1),
|
"to_date": fiscal_year[2],
|
||||||
"weekly_off": "Sunday"
|
"weekly_off": "Sunday"
|
||||||
}).insert()
|
}).insert()
|
||||||
holiday_list.get_weekly_off_dates()
|
holiday_list.get_weekly_off_dates()
|
||||||
holiday_list.save()
|
holiday_list.save()
|
||||||
|
|
||||||
def make_employee_salary_slip(self, user):
|
def make_employee_salary_slip(self, user):
|
||||||
employee = frappe.db.get_value("Employee", {"user_id": user})
|
employee = frappe.db.get_value("Employee", {"user_id": user})
|
||||||
salary_structure = make_salary_structure("Salary Structure Test for Salary Slip")
|
salary_structure = make_salary_structure("Salary Structure Test for Salary Slip", employee)
|
||||||
salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
|
salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
|
||||||
|
|
||||||
if not salary_slip:
|
if not salary_slip:
|
||||||
salary_slip = make_salary_slip(salary_structure, employee = employee)
|
salary_slip = make_salary_slip(salary_structure, employee = employee)
|
||||||
salary_slip.employee_name = frappe.get_value("Employee", {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
|
salary_slip.employee_name = frappe.get_value("Employee", {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
|
||||||
salary_slip.month = "12"
|
|
||||||
salary_slip.fiscal_year = "_Test Fiscal Year 2016"
|
salary_slip.fiscal_year = "_Test Fiscal Year 2016"
|
||||||
|
salary_slip.month = getdate(nowdate()).month
|
||||||
salary_slip.posting_date = nowdate()
|
salary_slip.posting_date = nowdate()
|
||||||
salary_slip.insert()
|
salary_slip.insert()
|
||||||
# salary_slip.submit()
|
# salary_slip.submit()
|
||||||
@@ -185,38 +194,67 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
activity_type.wage_rate = 25
|
activity_type.wage_rate = 25
|
||||||
activity_type.save()
|
activity_type.save()
|
||||||
|
|
||||||
def make_salary_component(salary_components):
|
def get_no_of_days(self):
|
||||||
|
no_of_days_in_month = calendar.monthrange(getdate(nowdate()).year,
|
||||||
|
getdate(nowdate()).month)
|
||||||
|
no_of_holidays_in_month = len([1 for i in calendar.monthcalendar(getdate(nowdate()).year,
|
||||||
|
getdate(nowdate()).month) if i[6] != 0])
|
||||||
|
return [no_of_days_in_month[1], no_of_holidays_in_month]
|
||||||
|
|
||||||
|
|
||||||
|
def make_earning_salary_component(salary_components):
|
||||||
for salary_component in salary_components:
|
for salary_component in salary_components:
|
||||||
if not frappe.db.exists('Salary Component', salary_component):
|
if not frappe.db.exists('Salary Component', salary_component):
|
||||||
sal_comp = frappe.get_doc({
|
sal_comp = frappe.get_doc({
|
||||||
"doctype": "Salary Component",
|
"doctype": "Salary Component",
|
||||||
"salary_component": salary_component
|
"salary_component": salary_component,
|
||||||
|
"type": "Earning"
|
||||||
})
|
})
|
||||||
sal_comp.insert()
|
sal_comp.insert()
|
||||||
get_salary_component_account(salary_component)
|
get_salary_component_account(salary_component)
|
||||||
|
|
||||||
def make_salary_structure(sal_struct):
|
def make_deduction_salary_component(salary_components):
|
||||||
|
for salary_component in salary_components:
|
||||||
|
if not frappe.db.exists('Salary Component', salary_component):
|
||||||
|
sal_comp = frappe.get_doc({
|
||||||
|
"doctype": "Salary Component",
|
||||||
|
"salary_component": salary_component,
|
||||||
|
"type": "Deduction"
|
||||||
|
})
|
||||||
|
sal_comp.insert()
|
||||||
|
get_salary_component_account(salary_component)
|
||||||
|
|
||||||
|
def make_salary_structure(sal_struct, employee):
|
||||||
if not frappe.db.exists('Salary Structure', sal_struct):
|
if not frappe.db.exists('Salary Structure', sal_struct):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Salary Structure",
|
"doctype": "Salary Structure",
|
||||||
"name": sal_struct,
|
"name": sal_struct,
|
||||||
"company": erpnext.get_default_company(),
|
"company": erpnext.get_default_company(),
|
||||||
"from_date": nowdate(),
|
"from_date": nowdate(),
|
||||||
"employees": get_employee_details(),
|
"employees": get_employee_details(employee),
|
||||||
"earnings": get_earnings_component(),
|
"earnings": get_earnings_component(),
|
||||||
"deductions": get_deductions_component(),
|
"deductions": get_deductions_component(),
|
||||||
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
|
elif not frappe.db.get_value("Salary Structure Employee",{'parent':sal_struct, 'employee':employee},'name'):
|
||||||
|
sal_struct = frappe.get_doc("Salary Structure", sal_struct)
|
||||||
|
sal_struct.append("employees", {"employee": employee,
|
||||||
|
"employee_name": employee,
|
||||||
|
"base": 32000,
|
||||||
|
"variable": 3200
|
||||||
|
})
|
||||||
|
sal_struct.save()
|
||||||
|
sal_struct = sal_struct.name
|
||||||
return sal_struct
|
return sal_struct
|
||||||
|
|
||||||
|
def get_employee_details(employee):
|
||||||
def get_employee_details():
|
return [{"employee": employee,
|
||||||
return [{"employee": frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"),
|
|
||||||
"base": 25000,
|
"base": 25000,
|
||||||
"variable": 5000
|
"variable": 5000
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_earnings_component():
|
def get_earnings_component():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -270,7 +308,4 @@ def get_deductions_component():
|
|||||||
"formula": 'base*.1',
|
"formula": 'base*.1',
|
||||||
"idx": 3
|
"idx": 3
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
test_dependencies = ["Leave Application", "Holiday List"]
|
|
||||||
|
|
||||||
@@ -6,25 +6,19 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
import erpnext
|
import erpnext
|
||||||
from frappe.utils.make_random import get_random
|
from frappe.utils.make_random import get_random
|
||||||
from frappe.utils import nowdate, add_days, add_years
|
from frappe.utils import nowdate, add_days, add_years, getdate
|
||||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||||
from erpnext.hr.doctype.salary_slip.test_salary_slip import make_salary_component
|
from erpnext.hr.doctype.salary_slip.test_salary_slip import make_earning_salary_component, make_deduction_salary_component
|
||||||
# test_records = frappe.get_test_records('Salary Structure')
|
# test_records = frappe.get_test_records('Salary Structure')
|
||||||
|
|
||||||
|
test_dependencies = ["Fiscal Year"]
|
||||||
|
|
||||||
class TestSalaryStructure(unittest.TestCase):
|
class TestSalaryStructure(unittest.TestCase):
|
||||||
def test_setup(self):
|
def setUp(self):
|
||||||
if not frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2016"):
|
|
||||||
fy = frappe.get_doc({
|
|
||||||
"doctype": "Fiscal Year",
|
|
||||||
"year": "_Test Fiscal Year 2016",
|
|
||||||
"year_end_date": "2016-12-31",
|
|
||||||
"year_start_date": "2016-01-01"
|
|
||||||
})
|
|
||||||
fy.insert()
|
|
||||||
|
|
||||||
self.make_holiday_list()
|
self.make_holiday_list()
|
||||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
||||||
make_salary_component(["Basic Salary", "Allowance", "HRA", "Professional Tax", "TDS"])
|
make_earning_salary_component(["Basic Salary", "Allowance", "HRA"])
|
||||||
|
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||||
employee1 = self.make_employee("test_employee@salary.com")
|
employee1 = self.make_employee("test_employee@salary.com")
|
||||||
employee2 = self.make_employee("test_employee_2@salary.com")
|
employee2 = self.make_employee("test_employee_2@salary.com")
|
||||||
|
|
||||||
@@ -87,8 +81,8 @@ def make_salary_slip_from_salary_structure(employee):
|
|||||||
sal_struct = make_salary_structure('Salary Structure Sample')
|
sal_struct = make_salary_structure('Salary Structure Sample')
|
||||||
sal_slip = make_salary_slip(sal_struct, employee = employee)
|
sal_slip = make_salary_slip(sal_struct, employee = employee)
|
||||||
sal_slip.employee_name = frappe.get_value("Employee", {"name":employee}, "employee_name")
|
sal_slip.employee_name = frappe.get_value("Employee", {"name":employee}, "employee_name")
|
||||||
sal_slip.month = "11"
|
|
||||||
sal_slip.fiscal_year = "_Test Fiscal Year 2016"
|
sal_slip.fiscal_year = "_Test Fiscal Year 2016"
|
||||||
|
sal_slip.month = getdate(nowdate()).month
|
||||||
sal_slip.posting_date = nowdate()
|
sal_slip.posting_date = nowdate()
|
||||||
sal_slip.insert()
|
sal_slip.insert()
|
||||||
sal_slip.submit()
|
sal_slip.submit()
|
||||||
|
|||||||
@@ -350,4 +350,5 @@ erpnext.patches.v7_1.update_invoice_status
|
|||||||
erpnext.patches.v7_0.po_status_issue_for_pr_return
|
erpnext.patches.v7_0.po_status_issue_for_pr_return
|
||||||
erpnext.patches.v7_1.update_missing_salary_component_type
|
erpnext.patches.v7_1.update_missing_salary_component_type
|
||||||
erpnext.patches.v7_0.update_autoname_field
|
erpnext.patches.v7_0.update_autoname_field
|
||||||
erpnext.patches.v7_0.update_status_of_po_so
|
erpnext.patches.v7_0.update_status_of_po_so
|
||||||
|
erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from erpnext.stock.stock_balance import repost_stock
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
modified_items = frappe.db.sql_list("""
|
||||||
|
select name from `tabItem`
|
||||||
|
where is_stock_item=1 and modified >= '2016-10-31'
|
||||||
|
""")
|
||||||
|
|
||||||
|
if not modified_items:
|
||||||
|
return
|
||||||
|
|
||||||
|
item_warehouses_with_transactions = []
|
||||||
|
transactions = ("Sales Order Item", "Material Request Item", "Purchase Order Item",
|
||||||
|
"Stock Ledger Entry", "Packed Item")
|
||||||
|
|
||||||
|
for doctype in transactions:
|
||||||
|
item_warehouses_with_transactions += list(frappe.db.sql("""
|
||||||
|
select distinct item_code, warehouse
|
||||||
|
from `tab{0}` where docstatus=1 and item_code in ({1})"""
|
||||||
|
.format(doctype, ', '.join(['%s']*len(modified_items))), tuple(modified_items)))
|
||||||
|
|
||||||
|
item_warehouses_with_transactions += list(frappe.db.sql("""
|
||||||
|
select distinct production_item, fg_warehouse
|
||||||
|
from `tabProduction Order` where docstatus=1 and production_item in ({0})"""
|
||||||
|
.format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
|
||||||
|
|
||||||
|
item_warehouses_with_transactions += list(frappe.db.sql("""
|
||||||
|
select distinct pr_item.item_code, pr.source_warehouse
|
||||||
|
from `tabProduction Order` pr, `tabProduction Order Item` pr_item
|
||||||
|
where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})"""
|
||||||
|
.format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
|
||||||
|
|
||||||
|
item_warehouses_with_bin = list(frappe.db.sql("select distinct item_code, warehouse from `tabBin`"))
|
||||||
|
|
||||||
|
item_warehouses_with_missing_bin = list(
|
||||||
|
set(item_warehouses_with_transactions) - set(item_warehouses_with_bin))
|
||||||
|
|
||||||
|
for item_code, warehouse in item_warehouses_with_missing_bin:
|
||||||
|
repost_stock(item_code, warehouse)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -532,8 +532,6 @@ class Item(WebsiteGenerator):
|
|||||||
frappe.throw(_("To merge, following properties must be same for both items")
|
frappe.throw(_("To merge, following properties must be same for both items")
|
||||||
+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
|
+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabBin` where item_code=%s", old_name)
|
|
||||||
|
|
||||||
def after_rename(self, old_name, new_name, merge):
|
def after_rename(self, old_name, new_name, merge):
|
||||||
if self.route:
|
if self.route:
|
||||||
invalidate_cache_for_item(self)
|
invalidate_cache_for_item(self)
|
||||||
@@ -567,8 +565,14 @@ class Item(WebsiteGenerator):
|
|||||||
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
||||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||||
|
|
||||||
for warehouse in frappe.db.sql("select warehouse from `tabBin` where item_code=%s", new_name):
|
repost_stock_for_warehouses = frappe.db.sql_list("""select distinct warehouse
|
||||||
repost_stock(new_name, warehouse[0])
|
from tabBin where item_code=%s""", new_name)
|
||||||
|
|
||||||
|
# Delete all existing bins to avoid duplicate bins for the same item and warehouse
|
||||||
|
frappe.db.sql("delete from `tabBin` where item_code=%s", new_name)
|
||||||
|
|
||||||
|
for warehouse in repost_stock_for_warehouses:
|
||||||
|
repost_stock(new_name, warehouse)
|
||||||
|
|
||||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
|
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
|
||||||
frappe.db.auto_commit_on_many_writes = 0
|
frappe.db.auto_commit_on_many_writes = 0
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ from frappe.test_runner import make_test_records
|
|||||||
from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
|
from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
|
||||||
InvalidItemAttributeValueError)
|
InvalidItemAttributeValueError)
|
||||||
|
|
||||||
|
from frappe.model.rename_doc import rename_doc
|
||||||
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
|
||||||
test_ignore = ["BOM"]
|
test_ignore = ["BOM"]
|
||||||
test_dependencies = ["Warehouse"]
|
test_dependencies = ["Warehouse"]
|
||||||
|
|
||||||
@@ -164,11 +167,31 @@ class TestItem(unittest.TestCase):
|
|||||||
variant.item_name = "_Test Numeric Variant Large 1.1m"
|
variant.item_name = "_Test Numeric Variant Large 1.1m"
|
||||||
self.assertRaises(InvalidItemAttributeValueError, variant.save)
|
self.assertRaises(InvalidItemAttributeValueError, variant.save)
|
||||||
|
|
||||||
variant = create_variant("_Test Numeric Template Item", {"Test Size": "Large", "Test Item Length": 1.5})
|
variant = create_variant("_Test Numeric Template Item",
|
||||||
|
{"Test Size": "Large", "Test Item Length": 1.5})
|
||||||
self.assertEquals(variant.item_code, None)
|
self.assertEquals(variant.item_code, None)
|
||||||
variant.item_code = "_Test Numeric Variant-L-1.5"
|
variant.item_code = "_Test Numeric Variant-L-1.5"
|
||||||
variant.item_name = "_Test Numeric Variant Large 1.5m"
|
variant.item_name = "_Test Numeric Variant Large 1.5m"
|
||||||
variant.save()
|
variant.save()
|
||||||
|
|
||||||
|
def test_item_merging(self):
|
||||||
|
create_item("Test Item for Merging 1")
|
||||||
|
create_item("Test Item for Merging 2")
|
||||||
|
|
||||||
|
make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC",
|
||||||
|
qty=1, rate=100)
|
||||||
|
make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC",
|
||||||
|
qty=1, rate=100)
|
||||||
|
|
||||||
|
rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True)
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1"))
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.get_value("Bin",
|
||||||
|
{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC"}))
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.get_value("Bin",
|
||||||
|
{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))
|
||||||
|
|
||||||
def make_item_variant():
|
def make_item_variant():
|
||||||
if not frappe.db.exists("Item", "_Test Variant Item-S"):
|
if not frappe.db.exists("Item", "_Test Variant Item-S"):
|
||||||
@@ -184,3 +207,14 @@ def get_total_projected_qty(item):
|
|||||||
return total_qty[0].projected_qty if total_qty else 0.0
|
return total_qty[0].projected_qty if total_qty else 0.0
|
||||||
|
|
||||||
test_records = frappe.get_test_records('Item')
|
test_records = frappe.get_test_records('Item')
|
||||||
|
|
||||||
|
def create_item(item_code, is_stock_item=None):
|
||||||
|
if not frappe.db.exists("Item", item_code):
|
||||||
|
item = frappe.new_doc("Item")
|
||||||
|
item.item_code = item_code
|
||||||
|
item.item_name = item_code
|
||||||
|
item.description = item_code
|
||||||
|
item.item_group = "All Item Groups"
|
||||||
|
item.is_stock_item = is_stock_item or 1
|
||||||
|
item.save()
|
||||||
|
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from frappe.model.rename_doc import rename_doc
|
||||||
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
from frappe.utils import cint
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
@@ -21,5 +24,77 @@ class TestWarehouse(unittest.TestCase):
|
|||||||
for child_warehouse in child_warehouses:
|
for child_warehouse in child_warehouses:
|
||||||
self.assertEquals(p_warehouse.name, child_warehouse.parent_warehouse)
|
self.assertEquals(p_warehouse.name, child_warehouse.parent_warehouse)
|
||||||
self.assertEquals(child_warehouse.is_group, 0)
|
self.assertEquals(child_warehouse.is_group, 0)
|
||||||
|
|
||||||
|
def test_warehouse_renaming(self):
|
||||||
|
set_perpetual_inventory(1)
|
||||||
|
create_warehouse("Test Warehouse for Renaming 1")
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 1 - _TC"))
|
||||||
|
self.assertTrue(frappe.db.get_value("Account",
|
||||||
|
filters={"warehouse": "Test Warehouse for Renaming 1 - _TC"}))
|
||||||
|
|
||||||
|
# Rename with abbr
|
||||||
|
if frappe.db.exists("Warehouse", "Test Warehouse for Renaming 2 - _TC"):
|
||||||
|
frappe.delete_doc("Warehouse", "Test Warehouse for Renaming 2 - _TC")
|
||||||
|
rename_doc("Warehouse", "Test Warehouse for Renaming 1 - _TC", "Test Warehouse for Renaming 2 - _TC")
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 2 - _TC"))
|
||||||
|
self.assertTrue(frappe.db.get_value("Account",
|
||||||
|
filters={"warehouse": "Test Warehouse for Renaming 2 - _TC"}))
|
||||||
|
|
||||||
|
# Rename without abbr
|
||||||
|
if frappe.db.exists("Warehouse", "Test Warehouse for Renaming 3 - _TC"):
|
||||||
|
frappe.delete_doc("Warehouse", "Test Warehouse for Renaming 3 - _TC")
|
||||||
|
|
||||||
|
rename_doc("Warehouse", "Test Warehouse for Renaming 2 - _TC", "Test Warehouse for Renaming 3")
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 3 - _TC"))
|
||||||
|
self.assertTrue(frappe.db.get_value("Account",
|
||||||
|
filters={"warehouse": "Test Warehouse for Renaming 3 - _TC"}))
|
||||||
|
|
||||||
|
set_perpetual_inventory(0)
|
||||||
|
|
||||||
|
def test_warehouse_merging(self):
|
||||||
|
set_perpetual_inventory(1)
|
||||||
|
|
||||||
|
create_warehouse("Test Warehouse for Merging 1")
|
||||||
|
create_warehouse("Test Warehouse for Merging 2")
|
||||||
|
|
||||||
|
make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - _TC",
|
||||||
|
qty=1, rate=100)
|
||||||
|
make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - _TC",
|
||||||
|
qty=1, rate=100)
|
||||||
|
|
||||||
|
existing_bin_qty = (
|
||||||
|
cint(frappe.db.get_value("Bin",
|
||||||
|
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - _TC"}, "actual_qty"))
|
||||||
|
+ cint(frappe.db.get_value("Bin",
|
||||||
|
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty"))
|
||||||
|
)
|
||||||
|
|
||||||
|
rename_doc("Warehouse", "Test Warehouse for Merging 1 - _TC",
|
||||||
|
"Test Warehouse for Merging 2 - _TC", merge=True)
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - _TC"))
|
||||||
|
|
||||||
|
bin_qty = frappe.db.get_value("Bin",
|
||||||
|
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty")
|
||||||
|
|
||||||
|
self.assertEqual(bin_qty, existing_bin_qty)
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.exists("Account", "Test Warehouse for Merging 1 - _TC"))
|
||||||
|
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Merging 2 - _TC"))
|
||||||
|
self.assertTrue(frappe.db.get_value("Account",
|
||||||
|
filters={"warehouse": "Test Warehouse for Merging 2 - _TC"}))
|
||||||
|
|
||||||
|
set_perpetual_inventory(0)
|
||||||
|
|
||||||
|
def create_warehouse(warehouse_name):
|
||||||
|
if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"):
|
||||||
|
w = frappe.new_doc("Warehouse")
|
||||||
|
w.warehouse_name = warehouse_name
|
||||||
|
w.parent_warehouse = "_Test Warehouse Group - _TC"
|
||||||
|
w.company = "_Test Company"
|
||||||
|
w.save()
|
||||||
|
|
||||||
|
|
||||||
@@ -143,9 +143,7 @@ class Warehouse(NestedSet):
|
|||||||
if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"):
|
if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"):
|
||||||
frappe.throw(_("Both Warehouse must belong to same Company"))
|
frappe.throw(_("Both Warehouse must belong to same Company"))
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabBin` where warehouse=%s", olddn)
|
self.rename_account_for(olddn, new_warehouse, merge)
|
||||||
|
|
||||||
self.rename_account_for(olddn, newdn, merge)
|
|
||||||
|
|
||||||
return new_warehouse
|
return new_warehouse
|
||||||
|
|
||||||
@@ -195,11 +193,14 @@ class Warehouse(NestedSet):
|
|||||||
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
||||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||||
|
|
||||||
for item in frappe.db.sql("""select distinct item_code from (
|
repost_stock_for_items = frappe.db.sql_list("""select distinct item_code
|
||||||
select name as item_code from `tabItem` where is_stock_item=1
|
from tabBin where warehouse=%s""", newdn)
|
||||||
union
|
|
||||||
select distinct item_code from tabBin) a"""):
|
# Delete all existing bins to avoid duplicate bins for the same item and warehouse
|
||||||
repost_stock(item[0], newdn)
|
frappe.db.sql("delete from `tabBin` where warehouse=%s", newdn)
|
||||||
|
|
||||||
|
for item_code in repost_stock_for_items:
|
||||||
|
repost_stock(item_code, newdn)
|
||||||
|
|
||||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
|
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
|
||||||
frappe.db.auto_commit_on_many_writes = 0
|
frappe.db.auto_commit_on_many_writes = 0
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ def get_basic_details(args, item):
|
|||||||
"net_amount": 0.0,
|
"net_amount": 0.0,
|
||||||
"discount_percentage": 0.0,
|
"discount_percentage": 0.0,
|
||||||
"supplier": item.default_supplier,
|
"supplier": item.default_supplier,
|
||||||
"delivered_by_supplier": item.delivered_by_supplier,
|
"delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,
|
||||||
"is_fixed_asset": item.is_fixed_asset
|
"is_fixed_asset": item.is_fixed_asset
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1086,7 +1086,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-11-03 16:16:32.681068",
|
"modified": "2016-12-13 11:17:40.538428",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Warranty Claim",
|
"name": "Warranty Claim",
|
||||||
|
|||||||
Reference in New Issue
Block a user