Skip to content

Commit

Permalink
Merge branch 'staging-fixes' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
frappe-bot committed Nov 14, 2018
2 parents 25a74b8 + fac4998 commit e419303
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 5 deletions.
2 changes: 1 addition & 1 deletion erpnext/hooks.py
Expand Up @@ -12,7 +12,7 @@
source_link = "https://github.com/frappe/erpnext" source_link = "https://github.com/frappe/erpnext"


develop_version = '12.x.x-develop' develop_version = '12.x.x-develop'
staging_version = '11.0.3-beta.21' staging_version = '11.0.3-beta.22'


error_report_email = "support@erpnext.com" error_report_email = "support@erpnext.com"


Expand Down
40 changes: 40 additions & 0 deletions erpnext/hr/doctype/salary_structure/salary_structure.js
Expand Up @@ -58,13 +58,53 @@ frappe.ui.form.on('Salary Structure', {
doc.company = frm.doc.company; doc.company = frm.doc.company;
frappe.set_route('Form', 'Salary Structure Assignment', doc.name); frappe.set_route('Form', 'Salary Structure Assignment', doc.name);
}); });
frm.add_custom_button(__("Assign to Employees"),function () {
frm.trigger('assign_to_employees')
})
} }
let fields_read_only = ["is_tax_applicable", "is_flexible_benefit", "variable_based_on_taxable_salary"]; let fields_read_only = ["is_tax_applicable", "is_flexible_benefit", "variable_based_on_taxable_salary"];
fields_read_only.forEach(function(field) { fields_read_only.forEach(function(field) {
frappe.meta.get_docfield("Salary Detail", field, frm.doc.name).read_only = 1; frappe.meta.get_docfield("Salary Detail", field, frm.doc.name).read_only = 1;
}); });
}, },


assign_to_employees:function (frm) {
var d = new frappe.ui.Dialog({
title: __("Assign to Employees"),
fields: [
{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
{fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
{fieldname:'base_variable', fieldtype:'Section Break'},
{fieldname:'from_date', fieldtype:'Date', label: __('From Date'), "reqd": 1},
{fieldname:'base_col_br', fieldtype:'Column Break'},
{fieldname:'base', fieldtype:'Currency', label: __('Base')},
{fieldname:'variable', fieldtype:'Currency', label: __('Variable')}
],
primary_action: function() {
var data = d.get_values();

frappe.call({
doc: frm.doc,
method: "assign_salary_structure",
args: data,
callback: function(r) {
if(!r.exc) {
d.hide();
frm.reload_doc();
}
}
});
},
primary_action_label: __('Assign')
});


d.show();
},

salary_slip_based_on_timesheet: function(frm) { salary_slip_based_on_timesheet: function(frm) {
frm.trigger("toggle_fields") frm.trigger("toggle_fields")
}, },
Expand Down
70 changes: 70 additions & 0 deletions erpnext/hr/doctype/salary_structure/salary_structure.py
Expand Up @@ -65,6 +65,76 @@ def validate_max_benefits_with_flexi(self):
if not have_a_flexi and flt(self.max_benefits) > 0: if not have_a_flexi and flt(self.max_benefits) > 0:
frappe.throw(_("Salary Structure should have flexible benefit component(s) to dispense benefit amount")) frappe.throw(_("Salary Structure should have flexible benefit component(s) to dispense benefit amount"))


def get_employees(self, **kwargs):
conditions, values = [], []
for field, value in kwargs.items():
if value:
conditions.append("{0}=%s".format(field))
values.append(value)

condition_str = " and " + " and ".join(conditions) if conditions else ""

employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}"
.format(condition=condition_str), tuple(values))

return employees

@frappe.whitelist()
def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
from_date=None, base=None,variable=None):
employees = self.get_employees(grade= grade,department= department,designation= designation,name=employee)

if employees:
if len(employees) > 20:
frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
else:
assign_salary_structure_for_employees(employees, self,from_date=from_date, base=base,variable=variable)
else:
frappe.msgprint(_("No Employee Found"))



def assign_salary_structure_for_employees(employees, salary_structure,from_date=None, base=None,variable=None):
salary_structures_assignments = []
existing_assignments_for = get_existing_assignments(employees, salary_structure.name,from_date)
count=0
for employee in employees:
if employee in existing_assignments_for:
continue
count +=1

salary_structures_assignment = create_salary_structures_assignment(employee, salary_structure, from_date, base, variable)
salary_structures_assignments.append(salary_structures_assignment)
frappe.publish_progress(count*100/len(set(employees) - set(existing_assignments_for)), title = _("Assigning Structures..."))

if salary_structures_assignments:
frappe.msgprint(_("Structures have been assigned successfully"))


def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable):
assignment = frappe.new_doc("Salary Structure Assignment")
assignment.employee = employee
assignment.salary_structure = salary_structure.name
assignment.from_date = from_date
assignment.base = base
assignment.variable = variable
assignment.save(ignore_permissions = True)
assignment.submit()
return assignment.name


def get_existing_assignments(employees, salary_structure,from_date):
salary_structures_assignments = frappe.db.sql_list("""
select distinct employee from `tabSalary Structure Assignment`
where salary_structure=%s and employee in (%s)
and from_date=%s and docstatus=1
""" % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])
if salary_structures_assignments:
frappe.msgprint(_("Skipping Salary Structure Assignment for the following employees, as Salary Structure Assignment records already exists against them. {0}")
.format("\n".join(salary_structures_assignments)))
return salary_structures_assignments

@frappe.whitelist() @frappe.whitelist()
def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None): def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None):
def postprocess(source, target): def postprocess(source, target):
Expand Down
13 changes: 13 additions & 0 deletions erpnext/hr/doctype/salary_structure/test_salary_structure.py
Expand Up @@ -71,6 +71,19 @@ def test_whitespaces_in_formula_conditions_fields(self):
for row in salary_structure.deductions: for row in salary_structure.deductions:
self.assertFalse(("\n" in row.formula) or ("\n" in row.condition)) self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))


def test_salary_structures_assignment(self):
salary_structure = make_salary_structure("Salary Structure Sample", "Monthly")
employee = "test_assign_stucture@salary.com"
employee_doc_name = make_employee(employee)
# clear the already assigned stuctures
frappe.db.sql('''delete from `tabSalary Structure Assignment` where employee=%s and salary_structure=%s ''',
("test_assign_stucture@salary.com",salary_structure.name))
#test structure_assignment
salary_structure.assign_salary_structure(employee=employee_doc_name,from_date='2013-01-01',base=5000,variable=200)
salary_structure_assignment = frappe.get_doc("Salary Structure Assignment",{'employee':employee_doc_name, 'from_date':'2013-01-01'})
self.assertEqual(salary_structure_assignment.docstatus, 1)
self.assertEqual(salary_structure_assignment.base, 5000)
self.assertEqual(salary_structure_assignment.variable, 200)


def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None, test_tax=False): def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None, test_tax=False):
if test_tax: if test_tax:
Expand Down
7 changes: 5 additions & 2 deletions erpnext/manufacturing/doctype/bom/bom.py
Expand Up @@ -108,7 +108,8 @@ def set_bom_material_details(self):
"item_code": item.item_code, "item_code": item.item_code,
"item_name": item.item_name, "item_name": item.item_name,
"bom_no": item.bom_no, "bom_no": item.bom_no,
"stock_qty": item.stock_qty "stock_qty": item.stock_qty,
"allow_transfer_for_manufacture": item.allow_transfer_for_manufacture
}) })
for r in ret: for r in ret:
if not item.get(r): if not item.get(r):
Expand All @@ -127,6 +128,8 @@ def get_bom_material_detail(self, args=None):
self.validate_rm_item(item) self.validate_rm_item(item)


args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or '' args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
args['transfer_for_manufacture'] = (cstr(args.get('allow_transfer_for_manufacture', '')) or
item and item[0].allow_transfer_for_manufacture or 0)
args.update(item[0]) args.update(item[0])


rate = self.get_rm_rate(args) rate = self.get_rm_rate(args)
Expand All @@ -142,7 +145,7 @@ def get_bom_material_detail(self, args=None):
'qty' : args.get("qty") or args.get("stock_qty") or 1, 'qty' : args.get("qty") or args.get("stock_qty") or 1,
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1, 'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
'base_rate' : rate, 'base_rate' : rate,
'allow_transfer_for_manufacture': item and args['allow_transfer_for_manufacture'] or 0 'allow_transfer_for_manufacture': cint(args['transfer_for_manufacture']) or 0
} }


return ret_item return ret_item
Expand Down
3 changes: 2 additions & 1 deletion erpnext/patches.txt
Expand Up @@ -572,9 +572,10 @@ execute:frappe.delete_doc("Page", "Sales Analytics")
execute:frappe.delete_doc("Page", "Purchase Analytics") execute:frappe.delete_doc("Page", "Purchase Analytics")
execute:frappe.delete_doc("Page", "Stock Analytics") execute:frappe.delete_doc("Page", "Stock Analytics")
execute:frappe.delete_doc("Page", "Production Analytics") execute:frappe.delete_doc("Page", "Production Analytics")
erpnext.patches.v11_0.ewaybill_fields_gst_india erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13
erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v11_0.drop_column_max_days_allowed
erpnext.patches.v11_0.change_healthcare_desktop_icons erpnext.patches.v11_0.change_healthcare_desktop_icons
erpnext.patches.v10_0.update_user_image_in_employee erpnext.patches.v10_0.update_user_image_in_employee
erpnext.patches.v11_0.update_delivery_trip_status erpnext.patches.v11_0.update_delivery_trip_status
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
erpnext.patches.v11_0.set_missing_gst_hsn_code
43 changes: 43 additions & 0 deletions erpnext/patches/v11_0/set_missing_gst_hsn_code.py
@@ -0,0 +1,43 @@
import frappe
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html

def execute():
company = frappe.db.sql_list("select name from tabCompany where country = 'India'")
if not company:
return

doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
"Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]

for dt in doctypes:
date_field = "posting_date"
if dt in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]:
date_field = "transaction_date"

transactions = frappe.db.sql("""
select dt.name, dt_item.name as child_name
from `tab{dt}` dt, `tab{dt} Item` dt_item
where dt.name = dt_item.parent
and dt.`{date_field}` > '2018-06-01'
and dt.docstatus = 1
and ifnull(dt_item.gst_hsn_code, '') = ''
and ifnull(dt_item.item_code, '') != ''
and dt.company in ({company})
""".format(dt=dt, date_field=date_field, company=", ".join(['%s']*len(company))), tuple(company), as_dict=1)

if not transactions:
continue

transaction_rows_name = [d.child_name for d in transactions]

frappe.db.sql("""
update `tab{dt} Item` dt_item
set dt_item.gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code)
where dt_item.name in ({rows_name})
""".format(dt=dt, rows_name=", ".join(['%s']*len(transaction_rows_name))), tuple(transaction_rows_name))

for t in transactions:
print(t.name)
trans_doc = frappe.get_doc(dt, t.name)
hsnwise_tax = get_itemised_tax_breakup_html(trans_doc)
frappe.db.set_value(dt, t.name, "other_charges_calculation", hsnwise_tax, update_modified=False)
2 changes: 1 addition & 1 deletion erpnext/regional/india/setup.py
Expand Up @@ -85,7 +85,7 @@ def add_print_formats():


def make_custom_fields(update=True): def make_custom_fields(update=True):
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description', fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description',
allow_on_submit=1, print_hide=1) allow_on_submit=1, print_hide=1)
invoice_gst_fields = [ invoice_gst_fields = [
dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break',
Expand Down

0 comments on commit e419303

Please sign in to comment.