780 lines
33 KiB
JavaScript
780 lines
33 KiB
JavaScript
let searchParams;
|
|
|
|
$(document).ready(async function () {
|
|
searchParams = new URLSearchParams(window.location.search);
|
|
event_id = searchParams.get('event_id');
|
|
await EventBilling.setup(event_id);
|
|
});
|
|
|
|
EventBilling = (function () {
|
|
let templates = {};
|
|
let event = {};
|
|
let billing_states = {};
|
|
let event_min_billing_state = {};
|
|
let pending_requests = [];
|
|
|
|
let setup = async function (event_id) {
|
|
await load_templates();
|
|
await load_event(event_id);
|
|
await setup_pagination();
|
|
let pathname = window.location.pathname;
|
|
if (pathname === "/portal/eb/event") {
|
|
await event_view.show_action_buttons();
|
|
} else if (pathname === "/portal/eb/close_event") {
|
|
await close_event_view.setup();
|
|
} else if (pathname === "/portal/eb/edit_times") {
|
|
await edit_times_view.setup();
|
|
} else if (pathname === "/portal/eb/personnel_billing") {
|
|
await personnel_billing_view.setup();
|
|
} else if (pathname === "/portal/eb/approve") {
|
|
await approve_view.setup();
|
|
}
|
|
};
|
|
let run_pending_requests = async function (success_callback) {
|
|
//Run all pending requests:
|
|
await Promise.all(pending_requests.map(req => $.ajax(req))).then(async function (values) {
|
|
pending_requests = []; //Clear pending requests
|
|
let error_occured = false;
|
|
for (let i = 0; i < values.length; i++) {
|
|
let val = values[i];
|
|
if (!is_ok(val)) {
|
|
error_occured = true;
|
|
}
|
|
}
|
|
if (!error_occured) {
|
|
success_callback();
|
|
}
|
|
}, function () {
|
|
//Failure
|
|
});
|
|
};
|
|
let setup_pagination = async function () {
|
|
await Promise.all([load_billing_states(), load_min_billing_states_for_event(event.entity_id)]).then(function (res) {
|
|
billing_states = res[0];
|
|
event_min_billing_state = res[1];
|
|
});
|
|
|
|
let progressbar = {};
|
|
progressbar.billing_states = billing_states;
|
|
progressbar.event_id = event.entity_id;
|
|
|
|
$(".nav-progressbar").html(templates.progressbar(progressbar));
|
|
$(".action_btn").html(templates.eb_action_buttons({event: event, states: billing_states}));
|
|
$(".progressbar > li").css("width", (100 / (3 + billing_states.length)) + "%");
|
|
//Mark active
|
|
if (event.state >= 4) {
|
|
$(".progress_event_closed").addClass("active");
|
|
}
|
|
if (event.state >= 6) {
|
|
$(".progress_times_confirmed").addClass("active");
|
|
}
|
|
if (event.state >= 7) {
|
|
$(".progress_personnel_billing").addClass("active");
|
|
|
|
if(event_min_billing_state) {
|
|
for (let state of billing_states) {
|
|
$(".progress_approve_" + state.entity_id).addClass("active");
|
|
if (state.entity_id === event_min_billing_state) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
let load_billing_states = async function () {
|
|
const res = $.ajax({
|
|
url: '/api/billing_states',
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
return res;
|
|
}
|
|
};
|
|
let load_min_billing_states_for_event = async function (event_id) {
|
|
const res = await $.ajax({
|
|
url: '/api/events/' + event_id + '/billing_states/min',
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if(res == null){
|
|
return null;
|
|
}
|
|
if(typeof res !== 'object'){
|
|
return res;
|
|
}
|
|
if('error' in res){
|
|
return null;
|
|
}else{
|
|
return res;
|
|
}
|
|
};
|
|
let load_templates = async function () {
|
|
const progressbar = $.get("/templates/progressbar.hbs");
|
|
const eb_action_buttons = $.get("/templates/eb_action_buttons.hbs");
|
|
await Promise.all([progressbar, eb_action_buttons]).then(function (res) {
|
|
templates.progressbar = Handlebars.compile(res[0]);
|
|
templates.eb_action_buttons = Handlebars.compile(res[1]);
|
|
});
|
|
|
|
};
|
|
let load_event = async function (event_id) {
|
|
await $.ajax({
|
|
url: '/api/events/' + event_id,
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
success: function (data) {
|
|
if (is_ok(data)) {
|
|
event = data;
|
|
}
|
|
},
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
};
|
|
let load_eu_instances = async function () {
|
|
const res = $.ajax({
|
|
url: '/api/events/' + event.entity_id + '/instances',
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
return res;
|
|
} else {
|
|
throw res;
|
|
}
|
|
};
|
|
let load_eu_instance_positions = async function (instances) {
|
|
let queue = [];
|
|
for (let instance of instances) {
|
|
queue.push(load_positions_for_instance_new(instance.instance_id));
|
|
}
|
|
await Promise.all(queue).then(function (res) {
|
|
for (let i = 0; i < instances.length; i++) {
|
|
instances[i].positions = res[i];
|
|
}
|
|
});
|
|
};
|
|
let update_position_instance = function (data) {
|
|
pending_requests.push(({
|
|
type: "PATCH",
|
|
url: "/api/events/position_instances/" + data.position_instance_id,
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
data: JSON.stringify(data),
|
|
}));
|
|
};
|
|
|
|
//TODO: only call if instance really changed
|
|
let save_eu_instance = function (data) {
|
|
pending_requests.push(({
|
|
type: "PATCH",
|
|
url: "/api/events/" + event_id + "/instances/" + data.instance_id,
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
data: JSON.stringify(data),
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten.");
|
|
},
|
|
}));
|
|
};
|
|
let event_view = (function () {
|
|
let show_action_buttons = async function () {
|
|
//Show action button
|
|
if (event.state < 4) {
|
|
$(".goto_close_event").show();
|
|
} else if (event.state === 4) {
|
|
$(".goto_edit_times").show();
|
|
} else if (event.state === 6) {
|
|
$(".goto_personnel_billing").show();
|
|
} else if (event.state >= 7) {
|
|
if (!event_min_billing_state) {
|
|
$(".goto_approve_" + billing_states[0].entity_id).show();
|
|
}
|
|
|
|
//Show next approval step (billing_state) button
|
|
for (let i = 0; i < billing_states.length - 1; i++) {
|
|
if (billing_states[i].entity_id === event_min_billing_state) {
|
|
$(".goto_approve_" + billing_states[i+1].entity_id).show();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
return {
|
|
show_action_buttons
|
|
}
|
|
}());
|
|
let close_event_view = (function () {
|
|
let setup = function () {
|
|
$(".close_event_btn").off("click").on("click", async function () {
|
|
try {
|
|
await close_event();
|
|
window.location = "/portal/eb/edit_times?event_id=" + event.entity_id;
|
|
} catch (e) {
|
|
//TODO: proper error reporting
|
|
}
|
|
});
|
|
};
|
|
let close_event = async function () {
|
|
const res = $.ajax({
|
|
url: '/api/events/' + event.entity_id + '/close',
|
|
type: 'PUT',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
return res;
|
|
} else {
|
|
throw res;
|
|
}
|
|
}
|
|
return {
|
|
setup
|
|
}
|
|
}());
|
|
let edit_times_view = (function () {
|
|
let eu_instances = {};
|
|
let load_local_templates = async function () {
|
|
const eu_instance_card = $.get("/templates/eb_eu_instance_card.hbs");
|
|
const new_position_instance = $.get("/templates/eb_eu_instance_card_new_position_instance.hbs");
|
|
await Promise.all([eu_instance_card, new_position_instance]).then(function (res) {
|
|
templates.eu_instance_card = Handlebars.compile(res[0]);
|
|
templates.new_position_instance = Handlebars.compile(res[1]);
|
|
Handlebars.registerPartial('new_position_instance', templates.new_position_instance);
|
|
});
|
|
};
|
|
let setup = async function () {
|
|
await load_local_templates();
|
|
eu_instances = await load_eu_instances(event.entity_id);
|
|
await load_eu_instance_positions(eu_instances);
|
|
|
|
$(".eu_instances_container").empty();
|
|
|
|
for (let instance of eu_instances) {
|
|
if (instance.planned_start_time && instance.planned_end_time) {
|
|
instance.planned_time = combine_start_end_time(instance.planned_start_time, instance.planned_end_time);
|
|
}
|
|
|
|
for (let position of instance.positions) {
|
|
if (position.taken_by) {
|
|
let member = await get_member(position.taken_by);
|
|
position.taken_by_member = member.firstname + " " + member.lastname;
|
|
}
|
|
}
|
|
|
|
$(".eu_instances_container").append(templates.eu_instance_card(instance));
|
|
|
|
}
|
|
|
|
Search2.setup(); //Setup searchbars
|
|
|
|
$(".eb_eu_instance_save_btn").off("click").on("click", save);
|
|
|
|
//Apply remove/restore position_instance button listeners
|
|
$(".remove_position_instance_button").off("click").on("click", delete_position_btn);
|
|
$(".restore_position_instance_button").off("click").on("click", restore_position_btn);
|
|
|
|
$(".approve_times_btn").off("click").on("click", approve_times);
|
|
$(".qsf").off("change").on("change", function () { //Show save button if instance changed
|
|
$(this).closest(".position_instance").addClass("modified");
|
|
$(this).closest(".instance").find(".eb_eu_instance_save_btn").show();
|
|
});
|
|
|
|
let add_new_position_instance_listener = function(){
|
|
$(this).closest(".new_position_instances").append(templates.new_position_instance);
|
|
$(".new_position_instance").off("click");
|
|
$(".new_position_instance:last-child").on("click", add_new_position_instance_listener);
|
|
$(".remove_new_position_instance_button").off("click").on("click", function () {
|
|
$(this).closest(".card").remove();
|
|
$(".new_position_instance").off("click");
|
|
$(".new_position_instance:last-child").on("click", add_new_position_instance_listener);
|
|
});
|
|
}
|
|
|
|
$(".new_position_instance:last-child").off("click").on("click", function(){
|
|
add_new_position_instance_listener(this);
|
|
});
|
|
$(".remove_new_position_instance_button").off("click").on("click", function () {
|
|
$(this).closest(".card").remove();
|
|
});
|
|
};
|
|
let save = async function () {
|
|
//TODO: use global save_pending_requests()
|
|
//TODO: send requests after each step. Otherwise request to delete something get's executed before request to edit same thing
|
|
pending_requests = [];
|
|
|
|
let parent = $(this).closest(".instance");
|
|
let save_btn = $(this);
|
|
|
|
//Save basic instance data:
|
|
let instance_patch = {};
|
|
instance_patch.instance_id = parent.data("instance-id") || undefined; //undefined = do not transmit at all
|
|
instance_patch.real_start_time = parent.find(".eb_eu_instance_real_start_time").val() || null; //null = set to null in database
|
|
instance_patch.real_end_time = parent.find(".eb_eu_instance_real_end_time").val() || null;
|
|
save_eu_instance(instance_patch);
|
|
|
|
//Save newly added positions:
|
|
let npi = $(".new_position_instance");
|
|
for (let i = 0; i < npi.length; i++) {
|
|
let new_pos = $(npi[i]);
|
|
let position = new_pos.find(".search_new_position_instance_position").data("value-id") || undefined;
|
|
let member = new_pos.find(".search_new_position_instance_member").data("value-id") || undefined;
|
|
console.log("member:" + member + " position:" + position);
|
|
//Skip new position if position or member isn't set
|
|
// TODO: simplify
|
|
if (!position || !member || position.trim() === "" || member.trim() === "") {
|
|
//Report error if new position missing either position or member (but not both)
|
|
if ((!position || position.trim() === "") && member) {
|
|
alert("Der neuen Personalposition fehlt die Positionsangabe!");
|
|
return;
|
|
}
|
|
if ((!member || member.trim() === "") && position) {
|
|
alert("Der neuen Personalposition fehlt ein Mitglied!");
|
|
return;
|
|
}
|
|
|
|
//Skip empty new positions
|
|
continue;
|
|
}
|
|
|
|
let new_position_instance = {};
|
|
new_position_instance.instance_id = parent.data("instance-id") || undefined;
|
|
new_position_instance.position_id = position || undefined;
|
|
new_position_instance.taken_by = member || undefined;
|
|
new_position_instance.real_start_time = new_pos.find(".new_position_instance_real_start_time").val() || undefined;
|
|
new_position_instance.real_end_time = new_pos.find(".new_position_instance_real_end_time").val() || undefined;
|
|
|
|
add_position_to_position_instances(new_position_instance);
|
|
}
|
|
|
|
//Remove position instances which are marked for removal:
|
|
let to_removed = $(".marked-for-delete");
|
|
|
|
for (i = 0; i < to_removed.length; i++) {
|
|
let element = $(to_removed[i]);
|
|
let position_instance_id = element.closest(".position_instance").data("position-instance-id");
|
|
console.log("removing: " + position_instance_id);
|
|
delete_position_instance(position_instance_id);
|
|
to_removed[i].remove();
|
|
}
|
|
|
|
//Update changed position instances:
|
|
let to_updated = $(".position_instance.modified");
|
|
for (i = 0; i < to_updated.length; i++) {
|
|
let element = $(to_updated[i]);
|
|
let update_set = {};
|
|
|
|
update_set.position_instance_id = element.data("position-instance-id") || undefined;
|
|
update_set.taken_by = element.find(".search_instance_position_instance").data("value-id") || null;
|
|
update_set.real_start_time = element.find(".eb_eu_instance_position_real_start_time").val() || null;
|
|
update_set.real_end_time = element.find(".eb_eu_instance_position_real_end_time").val() || null;
|
|
console.log(update_set);
|
|
update_position_instance(update_set);
|
|
}
|
|
|
|
//Run all pending requests:
|
|
await Promise.all(pending_requests.map(req => $.ajax(req))).then(async function (values) {
|
|
let error_occured = false;
|
|
for (let i = 0; i < values.length; i++) {
|
|
let val = values[i];
|
|
if (!is_ok(val)) {
|
|
error_occured = true;
|
|
}
|
|
}
|
|
if (!error_occured) {
|
|
save_btn.hide();
|
|
parent.find(".marked-for-delete").remove();
|
|
parent.find(".modified").removeClass("modified");
|
|
}
|
|
}, function () {
|
|
//Failure
|
|
});
|
|
|
|
pending_requests = []; //Clear pending requests
|
|
};
|
|
let add_position_to_position_instances = function (data) {
|
|
pending_requests.push(({
|
|
type: "POST",
|
|
url: "/api/events/instances/" + data.instance_id + "/positions/" + data.position_id,
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
data: JSON.stringify(data),
|
|
}));
|
|
};
|
|
let delete_position_instance = function (position_instance_id) {
|
|
pending_requests.push(({
|
|
type: "DELETE",
|
|
url: "/api/events/position_instances/" + position_instance_id,
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
}));
|
|
};
|
|
let delete_position_btn = function () {
|
|
let position = $(this).closest(".card");
|
|
|
|
$(this).closest(".instance").find(".eb_eu_instance_save_btn").show(); //Show save button
|
|
|
|
//Hide delete button and show restore button
|
|
$(this).hide();
|
|
position.find(".restore_position_instance_button").show();
|
|
|
|
$(position).addClass("marked-for-delete");
|
|
};
|
|
let restore_position_btn = function () {
|
|
let position = $(this).closest(".card");
|
|
|
|
//Hide restore button and show delete button
|
|
$(this).hide();
|
|
position.find(".remove_position_instance_button").show();
|
|
|
|
$(position).removeClass("marked-for-delete");
|
|
};
|
|
let approve_times = async function () {
|
|
let save_btns = $(".eb_eu_instance_save_btn:visible");
|
|
if (save_btns.length !== 0) {
|
|
alert("Es gibt ungespeicherte Änderungen. Bitte speichere alle Änderungen bevor zu die Einsatzzeiten bestätigst.");
|
|
} else {
|
|
|
|
const res = $.ajax({
|
|
url: '/api/events/' + event.entity_id + '/approve_times',
|
|
type: 'PUT',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
setTimeout(function(){
|
|
window.location.href = "/portal/eb/personnel_billing?event_id=" + event.entity_id;
|
|
}, 500);
|
|
} else {
|
|
throw res;
|
|
}
|
|
}
|
|
};
|
|
return {
|
|
setup
|
|
}
|
|
}());
|
|
let personnel_billing_view = (function () {
|
|
let eu_instances = {};
|
|
let setup = async function () {
|
|
await load_local_templates();
|
|
eu_instances = await load_eu_instances();
|
|
await load_eu_instance_positions(eu_instances);
|
|
let billing_rates = await load_personnel_billing_rates();
|
|
|
|
$(".eu_instances_container").empty();
|
|
|
|
for (let instance of eu_instances) {
|
|
if (instance.planned_start_time && instance.planned_end_time) {
|
|
instance.planned_time = combine_start_end_time(instance.planned_start_time, instance.planned_end_time);
|
|
}
|
|
if (instance.real_start_time && instance.real_end_time) {
|
|
instance.real_time = combine_start_end_time(instance.real_start_time, instance.real_end_time);
|
|
}
|
|
|
|
instance.billing_rates = JSON.parse(JSON.stringify(billing_rates)); //Clone array (not copy with reference) to set selected rate
|
|
|
|
for (let rate of instance.billing_rates) {
|
|
if (rate.billing_rate_id === instance.billing_rate_id) {
|
|
rate.selected = true;
|
|
}
|
|
}
|
|
|
|
for (let position of instance.positions) {
|
|
if (position.taken_by) {
|
|
let member = await get_member(position.taken_by);
|
|
position.taken_by_member = member.firstname + " " + member.lastname;
|
|
}
|
|
position.real_time = combine_start_end_time(position.real_start_time, position.real_end_time);
|
|
if (position.billable === null) {
|
|
//If billable is set to null in database set it to true (default) in UI
|
|
position.billable = true;
|
|
}
|
|
}
|
|
|
|
$(".eu_instances_container").append(templates.personnel_instance_card(instance));
|
|
|
|
//When non-billable is active disable billable and manual billing checkboxes
|
|
$(".instance_select_billing_rate").each(function () {
|
|
if ($(this).val() === "non-billable") {
|
|
$(this).closest(".instance").find(".eb_personnel_position_instance_is_billable").prop("checked", false).prop("disabled", true);
|
|
$(this).closest(".instance").find(".eb_personnel_position_instance_manual_billing_check").prop("checked", false).prop("disabled", true);
|
|
}
|
|
})
|
|
|
|
console.log(instance); //TODO: remove when testing done
|
|
}
|
|
|
|
$(".instance_select_billing_rate").on("change", function () {
|
|
let val = $(this).val();
|
|
let instance = $(this).closest(".instance");
|
|
|
|
if (val === "non-billable") {
|
|
instance.find(".eb_personnel_position_instance_is_billable").prop("checked", false).prop("disabled", true);
|
|
instance.find(".eb_personnel_position_instance_manual_billing_check").prop("checked", false).prop("disabled", true);
|
|
} else {
|
|
instance.find(".eb_personnel_position_instance_is_billable").prop("disabled", false);
|
|
instance.find(".eb_personnel_position_instance_manual_billing_check").prop("disabled", false);
|
|
}
|
|
});
|
|
$(".eb_personnel_position_instance_manual_billing_check").on("change", function () {
|
|
let personal_instance = $(this).closest(".position_instance");
|
|
if ($(this).prop("checked")) {
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_money_for_time_container").show();
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_lump_sum_container").show();
|
|
} else {
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_money_for_time_container").hide();
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_money_for_time").val("0.00");
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_lump_sum_container").hide();
|
|
personal_instance.find(".eb_personnel_position_instance_manual_billing_lump_sum").val("0.00");
|
|
}
|
|
});
|
|
$(".qsf").on("change", function () {
|
|
let instance = $(this).closest(".instance");
|
|
instance.find(".eb_personnel_instance_save_btn").show();
|
|
$(this).addClass("modified");
|
|
});
|
|
$(".eb_personnel_instance_save_btn").on("click", save);
|
|
$(".check_personnel_billing_btn").on("click", async function () {
|
|
await finish_personnel_billing();
|
|
window.location = "/portal/eb/approve?event_id=" + event.entity_id + "&stage=" + billing_states[0].entity_id;
|
|
})
|
|
};
|
|
let load_local_templates = async function () {
|
|
const personnel_instance_card = $.get("/templates/eb_personnel_instance_card.hbs");
|
|
await Promise.all([personnel_instance_card]).then(function (res) {
|
|
templates.personnel_instance_card = Handlebars.compile(res[0]);
|
|
});
|
|
};
|
|
let load_personnel_billing_rates = async function () {
|
|
const res = $.ajax({
|
|
url: '/api/personnel_billing_rates',
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
return res;
|
|
}
|
|
};
|
|
let save = async function () {
|
|
let instance = $(this).closest(".instance");
|
|
pending_requests = [];
|
|
|
|
//Save Instance:
|
|
|
|
let instance_patch = {};
|
|
instance_patch.instance_id = instance.data("instance-id") || undefined;
|
|
|
|
let billing_rate = instance.find(".instance_select_billing_rate").val();
|
|
|
|
//Remove personnel billing entries if billing_rate was set to non-billable
|
|
if (billing_rate === "non-billable") {
|
|
instance.find(".position_instance").each(function () {
|
|
remove_personnel_billing_entry($(this).data("position-instance-id"));
|
|
});
|
|
instance_patch.billing_rate_id = null;
|
|
} else {
|
|
instance_patch.billing_rate_id = billing_rate;
|
|
}
|
|
save_eu_instance(instance_patch);
|
|
run_pending_requests(function () {
|
|
});
|
|
|
|
//Save position instances:
|
|
for (let position_instance of instance.find(".position_instance")) {
|
|
let position_instance_id = $(position_instance).data("position-instance-id") || undefined;
|
|
|
|
//Patch eu_position_instance table
|
|
let position_instance_patch = {};
|
|
position_instance_patch.position_instance_id = position_instance_id;
|
|
if (billing_rate === "non-billable") {
|
|
position_instance_patch.billable = false;
|
|
} else {
|
|
position_instance_patch.billable = $(position_instance).find(".eb_personnel_position_instance_is_billable").prop("checked");
|
|
}
|
|
update_position_instance(position_instance_patch)
|
|
}
|
|
run_pending_requests(function () {
|
|
});
|
|
|
|
for (let position_instance of instance.find(".position_instance")) {
|
|
let position_instance_id = $(position_instance).data("position-instance-id") || undefined;
|
|
|
|
if ($(position_instance).find(".eb_personnel_position_instance_manual_billing_check").prop("checked")) {
|
|
//manual billing
|
|
let personnel_billing_patch = {};
|
|
personnel_billing_patch.position_instance_id = position_instance_id;
|
|
personnel_billing_patch.money_from_lump_sum = $(position_instance).find(".eb_personnel_position_instance_manual_billing_lump_sum").val() || undefined;
|
|
personnel_billing_patch.money_for_time = $(position_instance).find(".eb_personnel_position_instance_manual_billing_money_for_time").val() || undefined;
|
|
add_personnel_billing_entry_manual(personnel_billing_patch);
|
|
} else {
|
|
if (billing_rate !== "non-billable" && $(position_instance).find(".eb_personnel_position_instance_is_billable").prop("checked")) {
|
|
//Add personnel_billing entry. Overwrites existing entries
|
|
add_personnel_billing_entry(position_instance_id, billing_rate);
|
|
}
|
|
}
|
|
}
|
|
run_pending_requests(function () {
|
|
instance.find(".eb_personnel_instance_save_btn").hide();
|
|
instance.find(".modified").removeClass("modified");
|
|
});
|
|
|
|
};
|
|
let remove_personnel_billing_entry = function (position_instance_id) {
|
|
pending_requests.push(({
|
|
type: "DELETE",
|
|
url: "/api/personnel_billing/" + position_instance_id,
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
}));
|
|
};
|
|
let add_personnel_billing_entry = function (position_instance_id2, billing_rate_id2) {
|
|
let data = {
|
|
position_instance_id: position_instance_id2,
|
|
billing_rate_id: billing_rate_id2
|
|
};
|
|
pending_requests.push(({
|
|
type: "POST",
|
|
url: "/api/personnel_billing/",
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
data: JSON.stringify(data)
|
|
}));
|
|
};
|
|
let add_personnel_billing_entry_manual = function (data) {
|
|
pending_requests.push(({
|
|
type: "POST",
|
|
url: "/api/personnel_billing/",
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
data: JSON.stringify(data),
|
|
}));
|
|
};
|
|
let finish_personnel_billing = async function () {
|
|
const res = $.ajax({
|
|
url: '/api/events/' + event.entity_id + '/finish_personnel_billing',
|
|
type: 'PUT',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
if (is_ok(res)) {
|
|
return res;
|
|
} else {
|
|
throw res;
|
|
}
|
|
}
|
|
return {
|
|
setup
|
|
}
|
|
}());
|
|
let approve_view = (function () {
|
|
let setup = async function () {
|
|
await load_local_templates();
|
|
|
|
let instances = await load_eu_instances();
|
|
await load_eu_instance_positions(instances);
|
|
|
|
let total_sum = 0;
|
|
|
|
for (let instance of instances) {
|
|
instance.instance_total_sum = 0;
|
|
for (let pos of instance.positions) {
|
|
let val = await load_personnel_billing(pos.position_instance_id);
|
|
if (val) {
|
|
val.total_money = Number(val.total_money).toFixed(2);
|
|
instance.instance_total_sum = Number(Number(instance.instance_total_sum) + Number(val.total_money)).toFixed(2);
|
|
val.money_from_lump_sum = Number(val.money_from_lump_sum).toFixed(2);
|
|
val.money_for_time = Number(val.money_for_time).toFixed(2);
|
|
pos.personnel_billing = val;
|
|
}
|
|
if (pos.taken_by) {
|
|
let member = await get_member(pos.taken_by);
|
|
pos.taken_by_member = member.firstname + " " + member.lastname;
|
|
}
|
|
|
|
pos.real_time = combine_start_end_time(pos.real_start_time, pos.real_end_time);
|
|
}
|
|
|
|
total_sum = Number(Number(total_sum) + Number(instance.instance_total_sum)).toFixed(2);
|
|
|
|
$(".eu_approve_summary").append(templates.approve_instance_card(instance));
|
|
}
|
|
console.log("Gesamt gesamt:" + total_sum);
|
|
$(".eu_approve_summary").append(templates.approve_total_sum({total_sum}));
|
|
$(".approve_btn").on("click", async function () {
|
|
let current_state = searchParams.get('stage') || undefined;
|
|
if (is_ok(await approve(current_state))) {
|
|
window.location = "/portal/eb/event?event_id=" + event.entity_id;
|
|
}
|
|
})
|
|
|
|
};
|
|
let load_local_templates = async function () {
|
|
const approve_instance_card = $.get("/templates/eb_approve_instance_card.hbs");
|
|
const approve_total_sum = $.get("/templates/eb_approve_total_sum.hbs");
|
|
await Promise.all([approve_instance_card, approve_total_sum]).then(function (res) {
|
|
templates.approve_instance_card = Handlebars.compile(res[0]);
|
|
templates.approve_total_sum = Handlebars.compile(res[1]);
|
|
});
|
|
};
|
|
let load_personnel_billing = async function (position_instance_id) {
|
|
const data = await $.ajax({
|
|
url: '/api/personnel_billing/' + position_instance_id,
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
});
|
|
if (!is_ok(data)) {
|
|
show_error(data)
|
|
} else {
|
|
return data;
|
|
}
|
|
};
|
|
let approve = async function (stage_id) {
|
|
const res = $.ajax({
|
|
url: '/api/events/' + event.entity_id + '/approve?stage=' + stage_id,
|
|
type: 'PUT',
|
|
contentType: 'application/json',
|
|
timeout: 3000,
|
|
error: function () {
|
|
alert("Es ist ein Fehler aufgetreten!");
|
|
}
|
|
});
|
|
return res;
|
|
}
|
|
return {
|
|
setup
|
|
}
|
|
}());
|
|
return {
|
|
setup
|
|
}
|
|
}()); |