/* Authors : Carlos C. Corrada-Bravo David J. Ortiz-Rivera Organization : Centro de Desarrollo y Consultoria Computacional Project : OPASO Material Registry File : laboratory.js Description : Generate and display laboratory inventory */ /* save inventory data globaly */ var controlTimeout,control,total,r,next,transaction,row,form,admin var active = false; var sort_key = "mat_name"; let lab_id = get_arg("lab_id"); /* set listeners when document is ready */ $(document).ready(function(){ link_gen(); laboratory(); }); function display_form(type,transaction){ let f = `.${type}-form`; let s = `#${type}-submit`; $(".form-shader").addClass("fade-in") $(f).addClass("c-form"); $(f).addClass("slide-down"); $(s).attr("value",transaction); } /* hide_form() - hide form */ function hide_form(){ $(".c-form").removeClass("slide-down"); setTimeout(function(){ $(".form-shader").removeClass("fade-in"); },250); } /* main_transaction() - handle main transactions */ function main_transaction(){ /* extract args */ let s = `#${r}`; let amount = parseFloat($("#transaction").val()); var uom = $(s).find("td[value=uom]").text(); var mat_id = $(s).find("td[value=mat_name]").attr("mat_id"); var man_id = $(s).find("td[value=man_name]").attr("man_id"); let capacity = parseFloat($(s).find("td[value=capacity]").text()); /* calculate material left */ if(transaction === "add"){ total += amount; } else{ total -= amount; } /* query server */ hide_form(); $.post("/scripts/opaso",{query: 9,lab_id: lab_id,mat_id: mat_id,man_id: man_id,capacity: capacity,transaction: transaction,total: total,amount: amount,uom: uom},function(data){ // console.log(data); /* extract response */ let response = JSON.parse(data); let status = response["status"]; /* handle by status */ switch(status){ case "success": /* on success, update total/quantity */ if(total < 1){ $(s).remove(); $(".table-total").text($(".inventory-body tr").length); } /* update quantity */ else{ $("#total").val(total); $("#transaction").val(0); let containers = total/capacity; $(s).find("td[value=quantity]").text(Math.ceil(containers)); $(s).find("td[value=total]").text(total); } set_alert(status,"Transaction complete"); break; case "expired": /* on expired, redirect to index */ window.location.href = "/?error=session_expired"; break; default: /* on error, display message */ set_alert(status,response["message"]); break; } }); } /* add_material() - add material to inventory */ function add_material(){ /* generate material entries */ row = {}; form = {}; row[next] = {}; /* populate entries */ $(".material-input").each(function(){ /* extract field name */ var field = $(this).attr("name"); /* generate inventory row */ switch(field){ case "quantity": /* calculate total */ row[next][field] = $(this).val(); let mtotal = parseFloat(form["capacity"]) * parseFloat($(this).val()); form["total"] = mtotal; row[next]["total"] = mtotal; break; case "mat_name": case "man_name": case "capacity": case "uom": case "location": row[next][field] = $(this).val(); break; } /* set field entry */ form[field] = $(this).val(); }); /* query server */ hide_form(); $.post("/scripts/opaso",{query: 10,lab_id: lab_id,data: JSON.stringify(form)},function(data){ // console.log(data); /* extract response */ let response = JSON.parse(data); let status = response["status"]; /* handle by status */ switch(status){ case "expired": /* on expired, redirect to index */ window.location.href = "/?error=session_expired"; break; case "success": /* on success, update inventory */ // console.log(row); /* extract args */ let mat_id = response["mat_id"]; let man_id = response["man_id"]; let s_uom = form["uom"].toLowerCase(); let s_total = parseFloat(form["total"]); let s_capacity = parseFloat(form["capacity"]); let s_man_name = form["man_name"].toLowerCase(); /* verify if material exists */ var flag = true; let s = `td[mat_id=${mat_id}]`; $(s).each(function(){ /* extract args */ var capacity = parseFloat($(this).parent().find("td[value=capacity]").text()); var man_name = $(this).parent().find("td[value=man_name]").text().toLowerCase(); var uom = $(this).parent().find("td[value=uom]").text().toLowerCase(); /* update quantities */ if((capacity === s_capacity) && (man_name === s_man_name) && (uom === s_uom)){ var ntotal = parseFloat($(this).parent().find("td[value=total]").text()) + s_total; var containers = ntotal/capacity; $(this).parent().find("td[value=total]").text(ntotal); $(this).parent().find("td[value=quantity]").text(Math.ceil(containers)); flag = false; } }); /* generate table row */ if(flag){ let tr = element_gen("tr",{class: "entry-row",id: next}); for(var r in row){ for(var field in row[r]){ /* identify material */ if(field === "mat_name"){ var attributes = {class: "entry-cell",mat_id: mat_id,text: row[r][field],value: field}; } /* identify material */ else if(field === "man_name"){ if(!row[r][field]){ row[r][field] = "-"; } var attributes = {class: "entry-cell",man_id: man_id,text: row[r][field],value: field}; } else{ if(!row[r][field]){ row[r][field] = "-"; } var attributes = {class: "entry-cell",text: row[r][field],value: field}; } var td = element_gen("td",attributes); tr.append(td); } let actions = {add:{class: "t-icon material-icons",icon: "add"},use: {class: "t-icon material-icons",icon: "remove"},offer: {class: "t-icon material-icons",icon: "redeem"},discard: {class: "t-icon material-icons",icon: "delete"}}; var td = element_gen("td",{class: "actions-cell"}); for(var action in actions){ var icon = element_gen("i",{class: actions[action]["class"],text: actions[action]["icon"]}); var button = element_gen("button",{class: "button action",id: action,title: action,childs: {icon}}); td.append(button); } } /* append */ tr.append(td); $(".inventory-body").append(tr); /* sort table */ next += 1; full_sort(next,sort_key); $(".table-total").text(`Total: ${next}`); } default: /* on success/error, display message */ set_alert(status,response["message"]); break; } }); } /* transaction - handle material transactions */ function transaction(){ /* extract args */ transaction = $(this).attr("id"); r = $(this).parent().parent().attr("id"); let s = `#${r}`; total = parseFloat($(s).find("td[value=total]").text()); uom = $(s).find("td[value=uom]").text(); let header = `${transaction} material (${uom})`; $(".main-header").text(header); /* hide total capacity */ if(transaction === "add"){ $(".total").hide(); } /* set total quantity */ else{ $("#total").val(total); $(".total").show(); } $("#transaction").val(0); $(".transaction-label").text(transaction); display_form("main",transaction); } /* fetch_material() - fetch material data */ function fetch_material(){ /* extract key */ let mat_name = $(this).text(); let mat_id = $(this).attr("mat_id"); let uom = $(this).parent().find("td[value=uom]").text(); let man_id = $(this).parent().find("td[value=man_name]").attr("man_id"); let capacity = $(this).parent().find("td[value=capacity]").text(); $.post("/scripts/opaso",{query: 12,lab_id: lab_id,mat_id: mat_id,man_id: man_id,capacity: capacity,uom: uom},function(data){ // console.log(data); /* extract response */ let response = JSON.parse(data); let status = response["status"]; /* handle by status */ switch(status){ case "success": /* on success, generate material data */ let material = response["material"]; $("h5[value=mat_name]").text(mat_name); var href = `/materials?mat_id=${mat_id}`; $(".material-link").attr("href",href); for(var a in material){ let s = `span[value=${a}]`; if(a === "sds" && material[a]){ var icon = element_gen("i",{class: "fas fa-link"}); var link = element_gen("a",{href: decodeURIComponent(material[a]),target: "_blank",rel: "noopener noreferrer",childs: {icon}}); $(s).html(link); } else{ /* correct null values */ if(!material[a]){ material[a] = "-"; } $(s).text(material[a]); } } $(".material-data-shader").addClass("slide-right"); break; case "expired": /* on expired, redirect to index */ window.location.href = "/?error=session_expired"; break; default: /* on error, display message */ set_alert(status,response["message"]); break; } }); } /* set_listeners() - listen for events */ function set_listeners(){ /* sort table */ $(".sort").click(function(){ sort_key = $(this).attr("value"); if(sort_key === "mat_name"){ $(".sort-material").show(); $(".sort-alt").hide(); } else{ $(".sort-alt").show(); $(".sort-material").hide(); } full_sort(next,sort_key); }); /* add/use material */ $("tbody").on("click",".action",transaction); /* add material to inventory */ $(".add-material").click(function(){ display_form("add","add-material"); }); /* handle popover */ $("tbody td[value=mat_name]").click(fetch_material); /* handle form submit */ $(".submit").click(function(){ /* add material */ transaction = $(this).attr("value"); if(transaction === "add-material"){ /* verify null fields */ var valid = true; $(".material-input").each(function(){ var field = $(this).attr("name"); /* highlight */ if(!$(this).val()){ valid = false; $(this).addClass("invalid"); } /* unhighlight */ else{ $(this).removeClass("invalid"); } }); /* valid form */ if(valid){ set_confirm("Do you wish to add entry to inventory?",transaction); } /* invalid form */ else{ set_alert("warning","All fields required"); } } /* main transactions */ else{ /* validate amount */ let amount = parseFloat($("#transaction").val()); if((transaction === "add" || amount <= total) && amount > 0){ /* generate message */ let s = `#${r}`; let uom = $(s).find("td[value=uom]").text(); let material = $(s).find("td[value=mat_name]").text(); let verb = transaction.charAt(0).toUpperCase() + transaction.slice(1); let message = `${verb} ${amount}${uom} of ${material}. Is this correct?`; /* configure alert */ set_confirm(message,transaction); } /* amount not valid */ else{ set_alert("error","Please correct transaction amount"); } } }); /* handle query submit */ $("#yes").click(function(){ transaction = $(this).attr("value"); /* add material */ if(transaction === "add-material"){ add_material(); } /* main transactions */ else{ main_transaction(transaction); } hide_confirm(); }); /* handle query cancel */ $(".hide-confirm").click(function(element){ /* prevent child propagation */ if(element.target === element.currentTarget){ hide_confirm(); } }); /* close form */ $(".close-form").click(function(element){ if(element.target === element.currentTarget){ hide_form(); } }); /* hide material data */ $(".hide-material-data").click(function(element){ if(element.target === element.currentTarget){ $(".material-data-shader").removeClass("slide-right"); } }); /* download file */ $(".download-option").click(function(){ /* extract args */ $("html").addClass("wait"); let download_type = $(this).attr("value"); /* generate file */ $.post("/scripts/opaso",{query: 24,download_type: download_type,lab_id: get_arg("lab_id")},function(data){ // console.log(data); /* extract response */ let response = JSON.parse(data); let status = response["status"]; /* handle by status */ switch(status){ case "success": /* on success, generate table */ var link=element_gen("a",{href: response["url"],download: response["file_name"]}); link.click(); break; case "expired": /* on expired, redirect to index */ window.location.href = "/?error=session_expired"; break; default: /* on error, display message */ set_alert(status,response["message"]); break; } $("html").removeClass("wait"); }); }); } /* table_gen(data: dictionary) - generate table body */ function table_gen(data){ for(var d in data){ /* generate table row */ let tr = element_gen("tr",{class: "entry-row",id: d}); let fields = data[d]; for(var field in fields){ /* identify material */ if(field === "material"){ var attributes = {class: "entry-cell",mat_id: fields[field]["mat_id"],text: fields[field]["mat_name"],value: "mat_name"}; } /* identify material */ else if(field === "manufacturer"){ if(!fields[field]["man_name"]){ fields[field]["man_name"] = "-"; } var attributes = {class: "entry-cell",man_id: fields[field]["man_id"],text: fields[field]["man_name"],value: "man_name"}; } else{ /* correct null entries */ if(!fields[field]){ fields[field] = "-"; } var attributes = {class: "entry-cell",text: fields[field],value: field}; } /* generate cell */ var td = element_gen("td",attributes); tr.append(td); } let actions = {add:{class: "t-icon material-icons",icon: "add"},use: {class: "t-icon material-icons",icon: "remove"},offer: {class: "t-icon material-icons",icon: "redeem"},discard: {class: "t-icon material-icons",icon: "delete"}}; var td = element_gen("td",{class: "actions-cell"}); for(var action in actions){ var icon = element_gen("i",{class: actions[action]["class"],text: actions[action]["icon"]}); var button = element_gen("button",{class: "button action",id: action,title: action,childs: {icon}}); td.append(button); } /* append */ tr.append(td); $(".inventory-body").append(tr); } $(".processing").hide(); setTimeout(function(){ $(".main-wrapper").show(); },250); } /* laboratory() - fetch lab inventory */ function laboratory(){ /* avoid null queries */ if(is_valid(lab_id)){ $.post("/scripts/opaso",{query: 3,lab_id: lab_id},function(data){ // console.log(data); /* extract response */ let response = JSON.parse(data) let status = response["status"]; /* handle by status */ switch(status){ case "success": /* on success, generate inventory */ let inventory = response["lab"]["inventory"]; let personnel = response["lab"]["personnel"]; /* generate personnel table */ for(var p in personnel){ var name = element_gen("td",{class: "entry-cell person-name",text: personnel[p]["person_name"]}); var access_level = element_gen("td",{class: "entry-cell access-level",text: personnel[p]["access_level"]}); var person = element_gen("tr",{class: "personnel-row",childs:{name,access_level}}); $(".personnel-body").append(person); } table_gen(inventory); set_listeners(); next = Object.keys(inventory).length; $(".table-total").text(`Total: ${next}`); break; case "expired": /* on expired, redirect to index */ window.location.href = "/?error=session_expired"; break; default: /* on error, display message */ /* display alert */ set_alert(status,response["message"]); break; } }); } /* missing arg */ else{ set_alert(status,"One or more arguments are missing"); } }