|
|
|
@@ -1,5 +1,6 @@ |
|
|
|
(function ($) { |
|
|
|
$(function () { |
|
|
|
|
|
|
|
// http://davidwalsh.name/javascript-debounce-function |
|
|
|
function debounce(func, wait, immediate) { |
|
|
|
var timeout; |
|
|
|
@@ -43,7 +44,7 @@ |
|
|
|
var html = Mustache.render(template, data); |
|
|
|
$(this.selector).html(html); |
|
|
|
//save it |
|
|
|
$(this.selector).data(data); |
|
|
|
$(this.selector).data({obj:this, data:data}); |
|
|
|
//draw rating star |
|
|
|
this.set_ratings(this.data.rating); |
|
|
|
this.set_unconfirmed_job(this.data.unconfirmedjob); |
|
|
|
@@ -68,6 +69,38 @@ |
|
|
|
this.data.unconfirmedjob = num; |
|
|
|
} |
|
|
|
|
|
|
|
reset_summary() { |
|
|
|
this.summary = { |
|
|
|
wages : 0, |
|
|
|
normal_hour : 0, |
|
|
|
ot_hour : 0, |
|
|
|
petrol : 0, |
|
|
|
}; |
|
|
|
this.update_summary_in_gui(); |
|
|
|
} |
|
|
|
|
|
|
|
add_payment_summary(ps) |
|
|
|
{ |
|
|
|
//{ot: false, hour: "2.67", money: "76.90"} |
|
|
|
this.summary.wages += ps.money; |
|
|
|
if (! ps.ot ) |
|
|
|
this.summary.normal_hour += ps.hour; |
|
|
|
else |
|
|
|
this.summary.ot_hour += ps.hour; |
|
|
|
this.update_summary_in_gui(); |
|
|
|
} |
|
|
|
|
|
|
|
update_summary_in_gui() |
|
|
|
{ |
|
|
|
var msg = '$' + this.summary.wages.toFixed(2); |
|
|
|
$(this.selector).find('div[name="wages"]').html(msg); |
|
|
|
|
|
|
|
msg = this.summary.normal_hour.toFixed(2) + '+' +this.summary.ot_hour.toFixed(2) + 'hr'; |
|
|
|
$(this.selector).find('div[name="hours"]').html(msg); |
|
|
|
|
|
|
|
msg = 'petrol:' + this.summary.petrol.toFixed(2) + 'km'; |
|
|
|
$(this.selector).find('div[name="petrol"]').html(msg); |
|
|
|
} |
|
|
|
}//end of class People |
|
|
|
|
|
|
|
function bts_staff_html(data){ |
|
|
|
@@ -112,12 +145,13 @@ |
|
|
|
action: "list_staff", // action |
|
|
|
}, function(response, status, xhr){ |
|
|
|
if (response.status =='success'){ |
|
|
|
hide_loading_staff(); |
|
|
|
response.users.forEach(function(u){ |
|
|
|
var html = bts_staff_html(u); |
|
|
|
jQuery('div.stafflist').append(html); |
|
|
|
new People("#p" + u.login,'#staff_item', u); |
|
|
|
}); |
|
|
|
hide_loading_staff(); |
|
|
|
calculate_total_working_hour(); |
|
|
|
}else{ |
|
|
|
alert('error getting staff list'); |
|
|
|
} |
|
|
|
@@ -209,26 +243,6 @@ |
|
|
|
return selector; |
|
|
|
} |
|
|
|
|
|
|
|
function init_ts(){ |
|
|
|
list_staff(); |
|
|
|
list_clients(); |
|
|
|
xero(false); |
|
|
|
wifi(false); |
|
|
|
init_user_search(); |
|
|
|
ajax_earning_rate(); |
|
|
|
} |
|
|
|
|
|
|
|
function ajax_earning_rate(){ |
|
|
|
$.post(bts().ajax_url, { // POST request |
|
|
|
_ajax_nonce: bts().nonce, // nonce |
|
|
|
action: "earnings_rate", // action |
|
|
|
}, function(response, status, xhr){ |
|
|
|
bts().earnings_rate = response; |
|
|
|
console.log("%o", bts().earnings_rate); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
init_ts(); |
|
|
|
|
|
|
|
$(document).on('click', 'div.divTableHead.bdelete', function(){ |
|
|
|
var o = new Job({empty:true}); |
|
|
|
@@ -275,7 +289,7 @@ |
|
|
|
}); |
|
|
|
|
|
|
|
$(document).on('click', 'span.ticon.ticon-save', function(){ |
|
|
|
var table = $(this).closest('div.divTable') |
|
|
|
var table = $(this).closest('div.divTable'); |
|
|
|
table.data().job.do_save_record(); |
|
|
|
}); |
|
|
|
|
|
|
|
@@ -333,8 +347,9 @@ |
|
|
|
else{ |
|
|
|
this.mark_saved(); |
|
|
|
} |
|
|
|
|
|
|
|
this.mark_week_color(); |
|
|
|
console.log('this job money = %o', this.get_payment_summary()); |
|
|
|
this.validate(); |
|
|
|
} |
|
|
|
|
|
|
|
get_job_id(){ |
|
|
|
@@ -520,11 +535,100 @@ |
|
|
|
|
|
|
|
validate() |
|
|
|
{ |
|
|
|
if (this.is_finish_resonable()){ |
|
|
|
this.el.addClass('validjob'); |
|
|
|
this.clear_err_msg(); |
|
|
|
var ok = this.validate_start() && |
|
|
|
this.validate_finish() && |
|
|
|
this.validate_rate(); |
|
|
|
if (ok){ |
|
|
|
this.el.removeClass('invalidjob'); |
|
|
|
}else{ |
|
|
|
this.el.addClass('invalidjob'); |
|
|
|
} |
|
|
|
return ok; |
|
|
|
} |
|
|
|
|
|
|
|
validate_start(){ |
|
|
|
var str = this.get_start(); |
|
|
|
if ( is_valid_date_str(str) ){ |
|
|
|
this.mark_start_valid(); |
|
|
|
this.set_err_msg_start(''); |
|
|
|
return true; |
|
|
|
}else{ |
|
|
|
this.mark_start_invalid(); |
|
|
|
this.set_err_msg_start('wrong date'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
validate_finish() |
|
|
|
{ |
|
|
|
var str = this.get_finish(); |
|
|
|
if (! is_valid_date_str(str)){ |
|
|
|
this.set_err_msg_finish('wront date'); |
|
|
|
this.mark_finish_invalid(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (!this.is_finish_resonable()){ |
|
|
|
this.set_err_msg_finish("older than start") |
|
|
|
this.mark_finish_invalid(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
this.mark_finish_valid(); |
|
|
|
this.set_err_msg_finish(''); |
|
|
|
return true; |
|
|
|
} |
|
|
|
validate_rate() |
|
|
|
{ |
|
|
|
var rate_info = this.get_rate_info_by_id(this.get_rate()); |
|
|
|
if ( rate_info.RatePerUnit <= 0){ |
|
|
|
this.set_err_msg_rate('bad rate'); |
|
|
|
this.mark_rate_invalid(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
this.set_err_msg_rate(''); |
|
|
|
this.mark_rate_valid(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
clear_err_msg(){ |
|
|
|
this.el.find('.divTableRow.errmsg > div').html(''); |
|
|
|
} |
|
|
|
set_err_msg_start(str) |
|
|
|
{ |
|
|
|
this.el.find('div.bstart_err').html(str); |
|
|
|
} |
|
|
|
set_err_msg_finish(str) |
|
|
|
{ |
|
|
|
this.el.find('div.bfinish_err').html(str); |
|
|
|
} |
|
|
|
set_err_msg_rate(str) |
|
|
|
{ |
|
|
|
this.el.find('div.brate_err').html(str); |
|
|
|
} |
|
|
|
set_err_msg_save(str) |
|
|
|
{ |
|
|
|
this.el.find('div.bsave_err').html(str); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mark_start_valid(){ |
|
|
|
this.el.find('div.bstart input').removeClass('invalid'); |
|
|
|
} |
|
|
|
mark_start_invalid(){ |
|
|
|
this.el.find('div.bstart input').addClass('invalid'); |
|
|
|
} |
|
|
|
|
|
|
|
mark_finish_valid(){ |
|
|
|
this.el.find('div.bfinish input').removeClass('invalid'); |
|
|
|
} |
|
|
|
mark_finish_invalid(){ |
|
|
|
this.el.find('div.bfinish input').addClass('invalid'); |
|
|
|
} |
|
|
|
mark_rate_valid(){ |
|
|
|
this.el.find('div.brate select').removeClass('invalid'); |
|
|
|
} |
|
|
|
mark_rate_invalid(){ |
|
|
|
this.el.find('div.brate select').addClass('invalid'); |
|
|
|
} |
|
|
|
|
|
|
|
mark_week_color(){ |
|
|
|
@@ -555,8 +659,58 @@ |
|
|
|
var me = new Date(this.data.start); |
|
|
|
return (w2_begin <= me && me <= w2_end ); |
|
|
|
} |
|
|
|
get_payment_summary(){ |
|
|
|
var result ={}; |
|
|
|
result.ot = this.get_is_high_pay(); |
|
|
|
result.hour = this.get_working_duration(); |
|
|
|
result.money = this.get_wages(); |
|
|
|
return result; |
|
|
|
} |
|
|
|
get_is_high_pay() |
|
|
|
{ |
|
|
|
var rate_info = this.get_rate_info_by_id(this.get_rate()); |
|
|
|
return this.is_high_pay_hour(rate_info); |
|
|
|
} |
|
|
|
get_working_duration() |
|
|
|
{ |
|
|
|
//finish - start |
|
|
|
var f = new Date(this.get_finish()); |
|
|
|
var s = new Date(this.get_start()); |
|
|
|
var diff = f.getTime() - s.getTime(); |
|
|
|
var hours = Math.floor(diff / 1000 / 60 / 60); |
|
|
|
diff -= hours * 1000 * 60 * 60; |
|
|
|
var minutes = Math.floor(diff / 1000 / 60); |
|
|
|
var minute_to_hour = minutes/60; |
|
|
|
return (hours + minute_to_hour); |
|
|
|
} |
|
|
|
get_wages(){ |
|
|
|
var hour = this.get_working_duration(); |
|
|
|
var rate_info = this.get_rate_info_by_id(this.get_rate()); |
|
|
|
return hour * rate_info.RatePerUnit; |
|
|
|
} |
|
|
|
|
|
|
|
get_rate_info_by_id(id){ |
|
|
|
var rate_info = {}; |
|
|
|
var rates = bts().earnings_rate; |
|
|
|
for(var i =0; i< rates.length; i++){ |
|
|
|
var r = rates[i]; |
|
|
|
if(r.EarningsRateID == id){ |
|
|
|
rate_info = $.extend(true,{}, r);//make a copy |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return rate_info; |
|
|
|
} |
|
|
|
|
|
|
|
is_high_pay_hour(rate_info){ |
|
|
|
var keywords =bts().high_pay_keywords; |
|
|
|
var found = false; |
|
|
|
keywords.forEach(function(e){ |
|
|
|
if (-1 != rate_info.Name.toLowerCase().indexOf(e.toLowerCase()) ) |
|
|
|
found = true; |
|
|
|
}); |
|
|
|
return found; |
|
|
|
} |
|
|
|
}//end of class Job |
|
|
|
|
|
|
|
//global GUI summary |
|
|
|
@@ -809,19 +963,17 @@ |
|
|
|
|
|
|
|
$('div.sheettitle h1').click(function(){ |
|
|
|
reset_title_to_today(); |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
function reset_title_to_today(){ |
|
|
|
set_today(); |
|
|
|
init_weekdays(); |
|
|
|
set_week_number(); |
|
|
|
load_timesheet(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function load_timesheet() |
|
|
|
{ |
|
|
|
show_loading_jobs(); |
|
|
|
clear_workspace(); |
|
|
|
var first = $('span[name="w1d1"]').data().date; |
|
|
|
var last = $('span[name="w2d7"]').data().date; |
|
|
|
@@ -880,7 +1032,8 @@ |
|
|
|
} |
|
|
|
|
|
|
|
$('button[name="confirmschedule"]').click(function(){ |
|
|
|
$('span.ticon.ticon-save').trigger('click'); |
|
|
|
//$('div.workspace span.ticon.ticon-save').trigger('click'); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
@@ -901,10 +1054,8 @@ |
|
|
|
clients.push(id.substring(1)); |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('staffs %o' , staffs); |
|
|
|
console.log('clients %o' , clients); |
|
|
|
|
|
|
|
filter_workspace(staffs, clients); |
|
|
|
calculate_total_working_hour(); |
|
|
|
} |
|
|
|
|
|
|
|
function filter_workspace(staffs, clients){ |
|
|
|
@@ -932,7 +1083,29 @@ |
|
|
|
|
|
|
|
function calculate_total_working_hour() |
|
|
|
{ |
|
|
|
//init pays for all staff; |
|
|
|
var pays=[]; |
|
|
|
$('.stafflist > div.peopleitem').each(function(i,e){ |
|
|
|
var people = $(this).data().obj; |
|
|
|
people.reset_summary(); |
|
|
|
}); |
|
|
|
|
|
|
|
$('div.workspace > .divTable').each(function(i,e){ |
|
|
|
var job = $(e).data().job; //class Job |
|
|
|
var ps = job.get_payment_summary(); |
|
|
|
var staff = job.get_staff(); |
|
|
|
var people = find_staff(staff); //class People |
|
|
|
if (people !=false) |
|
|
|
people.add_payment_summary(ps); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function find_staff(login) |
|
|
|
{ |
|
|
|
var d = $('#p'+login).data(); |
|
|
|
if (typeof d === 'undefined') |
|
|
|
return false; |
|
|
|
return $('#p'+login).data().obj; |
|
|
|
} |
|
|
|
|
|
|
|
function calculate_total_money() |
|
|
|
@@ -940,43 +1113,37 @@ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//visually hint whether start is correct; |
|
|
|
$(document).on('change','div.bstart input', function(){ |
|
|
|
var str = $(this).attr('value'); |
|
|
|
if ( ! is_valid_date_str(str) ) |
|
|
|
$(this).css('background-color', 'orange'); |
|
|
|
else |
|
|
|
$(this).css('background-color', 'white'); |
|
|
|
}); |
|
|
|
|
|
|
|
//visually hint whether finish date is correct; |
|
|
|
$(document).on('change','div.bfinish input', function(){ |
|
|
|
var job = $(this).closest('div.divTable').data().job; |
|
|
|
var str = $(this).attr('value'); |
|
|
|
if ( ! is_valid_date_str(str) ){ |
|
|
|
$(this).css('background-color', 'orange'); |
|
|
|
return; |
|
|
|
}else |
|
|
|
$(this).css('background-color', 'white'); |
|
|
|
|
|
|
|
//must be later than start |
|
|
|
if (! job.is_finish_resonable()){ |
|
|
|
alert('finish date should be bigger than start date'); |
|
|
|
$(this).css('background-color', 'orange'); |
|
|
|
}else{ |
|
|
|
$(this).css('background-color', 'white'); |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
$(document).on('change', '.divTableRow select, .divTableRow input', function() { |
|
|
|
var job = $(this).closest('.divTable').data().job; |
|
|
|
job.validate(); |
|
|
|
job.mark_dirty(); |
|
|
|
}); |
|
|
|
|
|
|
|
reset_title_to_today(); |
|
|
|
function init_ts(){ |
|
|
|
show_loading_jobs(); |
|
|
|
list_staff(); |
|
|
|
list_clients(); |
|
|
|
xero(false); |
|
|
|
wifi(false); |
|
|
|
init_user_search(); |
|
|
|
//ajax_earning_rate(); |
|
|
|
reset_title_to_today(); |
|
|
|
load_timesheet(); |
|
|
|
} |
|
|
|
|
|
|
|
// function ajax_earning_rate(){ |
|
|
|
// $.post(bts().ajax_url, { // POST request |
|
|
|
// _ajax_nonce: bts().nonce, // nonce |
|
|
|
// action: "earnings_rate", // action |
|
|
|
// }, function(response, status, xhr){ |
|
|
|
// bts().earnings_rate = response; |
|
|
|
// console.log("%o", bts().earnings_rate); |
|
|
|
// }); |
|
|
|
// } |
|
|
|
|
|
|
|
init_ts(); |
|
|
|
|
|
|
|
|
|
|
|
/*________________________________________________________________________*/ |
|
|
|
}); |
|
|
|
})(jQuery); |