CVE-2023-2553 (published 2023-05-05T20:15Z)

Cross-site Scripting (XSS) - Stored in GitHub repository unilogies/bumsys prior to 2.2.0.

CVSS v3 base score: 5.4, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-79
cwe_name: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
extended_description: 
            Cross-site scripting (XSS) vulnerabilities occur when:
            
               Untrusted data enters a web application, typically from a web request.
               The web application dynamically generates a web page that contains this untrusted data.
               During page generation, the application does not prevent the data from containing content that is executable by a web browser, such as JavaScript, HTML tags, HTML attributes, mouse events, Flash, ActiveX, etc.
               A victim visits the generated web page through a web browser, which contains malicious script that was injected using the untrusted data.
               Since the script comes from a web page that was sent by the web server, the victim's web browser executes the malicious script in the context of the web server's domain.
               This effectively violates the intention of the web browser's same-origin policy, which states that scripts in one domain should not be able to access resources or run code in a different domain.
            
            There are three main kinds of XSS:
            
               
                  Type 1: Reflected XSS (or Non-Persistent) - 
         			The server reads data directly from the HTTP request and reflects it back in the HTTP response. Reflected XSS exploits occur when an attacker causes a victim to supply dangerous content to a vulnerable web application, which is then reflected back to the victim and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or e-mailed directly to the victim. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces a victim to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the victim, the content is executed by the victim's browser.
               
                  Type 2: Stored XSS (or Persistent) - 
               The application stores dangerous data in a database, message forum, visitor log, or other trusted data store. At a later time, the dangerous data is subsequently read back into the application and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user. For example, the attacker might inject XSS into a log message, which might not be handled properly when an administrator views the logs.
            
               
                  Type 0: DOM-Based XSS - 
               In DOM-based XSS, the client performs the injection of XSS into the page; in the other types, the server performs the injection. DOM-based XSS generally involves server-controlled, trusted script that is sent to the client, such as Javascript that performs sanity checks on a form before the user submits it. If the server-supplied script processes user-supplied data and then injects it back into the web page (such as with dynamic HTML), then DOM-based XSS is possible.
            
            
            Once the malicious script is injected, the attacker can perform a variety of malicious activities. The attacker could transfer private information, such as cookies that may include session information, from the victim's machine to the attacker. The attacker could send malicious requests to a web site on behalf of the victim, which could be especially dangerous to the site if the victim has administrator privileges to manage that site. Phishing attacks could be used to emulate trusted web sites and trick the victim into entering a password, allowing the attacker to compromise the victim's account on that web site. Finally, the script could exploit a vulnerability in the web browser itself possibly taking over the victim's machine, sometimes referred to as "drive-by hacking."
            In many cases, the attack can be launched without the victim even being aware of it. Even with careful users, attackers frequently use a variety of methods to encode the malicious portion of the attack, such as URL encoding or Unicode, so the request looks less suspicious.
         
         

Fix information:
repo_url: https://github.com/unilogies/bumsys
commit_details: repo_url: https://github.com/unilogies/bumsys
author: Khurshid Alam
author_date: 2023-04-28 15:00:55+06:00
msg: Fix security issue
repository: repo_url: https://github.com/unilogies/bumsys
repo_name: unilogies/bumsys
description: An open sources project called Business Management System
owner: unilogies
file_changes: filename: bms.js
change_type: ModificationType.MODIFY
diff: @@ -863,7 +863,7 @@ BMS.FUNCTIONS = {
         var noResults = "";
         if ( $(selector).attr("select2-create-new-url") === undefined  ) {
 
-            noResults = "<?php echo __('Nothing found')?>";
+            noResults = "<?php echo __('Nothing found'); ?>";
 
         } else {
 
@@ -907,12 +907,22 @@ BMS.FUNCTIONS = {
                 },
                 cache: true
             },
+            templateSelection: function(state) {
+
+                if(!state.id) {
+                    return state.text;
+                } else {
+                    return $("<div>").text(state.text).html();
+                }
+
+                // console.log(state.text);
+            },
             templateResult: function(state) {
                 
                 if(!state.id) {
                     return state.text;
                 }
-            
+        
                 
                 if (typeof state.text === "object" ) {
 
@@ -940,7 +950,8 @@ BMS.FUNCTIONS = {
 
                 } else {
 
-                    return state.text;
+                    // return state.text;
+                    return $("<div>").text(state.text).html();
 
                 }
 

programming_language: JavaScript
filename: bms.min.js
change_type: ModificationType.MODIFY
diff: @@ -1 +1 @@
-"use strict";var updateSDPTimeout,BMS=BMS||{};BMS.FUNCTIONS={getDateTime:function(){var t=new Date;return t.getFullYear()+"-"+t.getMonth()+"-"+t.getDay()+"-"+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds()},calculateDiscount:function(t,e=null){return""===e||null===e||"null"===e||0===e?parseFloat(Number(t)):"string"==typeof e&&e.indexOf("%")>0?parseFloat(Number(t)-Number(e.replace("%",""))/100*Number(t)):parseFloat(Number(t)-Number(e))},calculateTarifCharges:function(t,e=null){return""===e||null===e||"null"===e||0===e?0:"string"==typeof e&&e.indexOf("%")>0?(Number(e.replace("%",""))/100*Number(t)).toFixed(2):Number(e).toFixed(2)},datePicker:function({selector:t=".datePicker",format:e="YYYY-MM-DD",timePicker:a=!1}=""){$(t).daterangepicker({autoUpdateInput:!1,singleDatePicker:!0,showDropdowns:!0,timePicker:a,timePicker24Hour:!0,autoApply:!0,parentEl:"div.dynamic-container",drops:"auto",locale:{format:e,cancelLabel:"Clear"}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},dateRangePicker:function({selector:t=".dateRangePicker",format:e="YYYY-MM-DD",timePicker:a=!1}=""){$(t).daterangepicker({autoUpdateInput:!1,showDropdowns:!0,drops:"auto",linkedCalendars:!1,timePicker:a,timePicker24Hour:!0,parentEl:"div.dynamic-container",locale:{format:e,cancelLabel:"Clear"}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e)+" - "+a.endDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},dateRangePickerPreDefined:function({selector:t=".dateRangePickerPreDefined",format:e="YYYY-MM-DD",timePicker:a=!1,ranges:r={}}=""){$(t).daterangepicker({autoUpdateInput:!1,showDropdowns:!0,drops:"auto",alwaysShowCalendars:!0,linkedCalendars:!1,timePicker:a,timePicker24Hour:!0,parentEl:"div.dynamic-container",locale:{format:e,cancelLabel:"Clear"},ranges:Object.keys(r).length>0?r:{Today:[moment(),moment()],"This Month":[moment().startOf("month"),moment().endOf("month")],"Last Month":[moment().subtract(1,"month").startOf("month"),moment().subtract(1,"month").endOf("month")],"This Year":[moment().startOf("year"),moment().endOf("year")],"Last Year":[moment().subtract(1,"year").startOf("year"),moment().subtract(1,"year").endOf("year")],All:[moment(0),moment().subtract("year").endOf("day")]}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e)+" - "+a.endDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},multiDatePicker:function({selector:t=".multiDatePicker",format:e="yyyy-mm-dd"}=""){$(t).datepicker({multidate:!0,multidateSeparator:", ",format:e,todayHighlight:!0})},getCookie:function(t){var e=decodeURIComponent(`; ${document.cookie}`).split(`; ${t}=`);if(e.length>1)return e[1].split("; ")[0]},copy:function(t){var e=$(t);e.select(),navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([e.html()],{type:"text/html"})})])},_n:function(t){let e=BMS.fn.getCookie("lang"),a={bn_BD:"bn-BD"};return void 0!==e?new Intl.NumberFormat(a[e]).format(t):t},createNewSelect2Item:function(t){var e=$(t).attr("select2-create-new-url"),a=$(".select2-search__field").val(),r=encodeURIComponent(a);console.log(t),$("body").trigger("mousedown"),$("#modalDefault").modal("show").find(".modal-content").load(e+"&val="+r),$("#modalDefault").on("hidden.bs.modal",(function(e){BMS.fn.select2(t,"",a)}))},play:function(t,e=!1){var a=`${full_website_address}/assets/sounds/${t}.mp3`,r=new window.Audio(a);$(document).on("pauseAudio",(function(){r.pause()})),r.loop=e,r.play()},pause:function(){$(document).trigger("pauseAudio")},startTimer(t="#timer"){var e=(new Date).getTime();return setInterval((function(){var a=((new Date).getTime()-e)/1e3,r=Math.floor(a%60).toString().padStart(2,0),o=Math.floor(a%3600/60).toString().padStart(2,0),n=Math.floor(a/3600).toString().padStart(2,0);$(t).html(`${n}:${o}:${r}`)}),1e3)},stopTimer:function(t){clearInterval(t)},notify:function(t){Swal.fire({toast:!0,position:"top-right",timer:5e3,timerProgressBar:!0,iconHtml:'<i class="fa fa-bell"></i>',didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),this.play("beep")},title:`<span style="padding: 10px 0; font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},desktopNotify:function(t,e="",a=""){"granted"!==Notification.permission?Notification.requestPermission():new Notification(t,{icon:e,body:a}).onclick=function(){window.focus(),this.close()}},alertError:function(t){Swal.fire({toast:!0,position:"top-right",icon:"error",timer:5e3,timerProgressBar:!0,didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),this.play("warning")},title:`<span style="font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},alertSuccess:function(t,e=!0){Swal.fire({toast:!0,position:"top-right",icon:"success",timer:5e3,timerProgressBar:!0,didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),e&&this.play("warning")},title:`<span style="font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},dTable:function(t){var e="";e=void 0!==$(t).attr("dt-data-url")?$(t).attr("dt-data-url"):DataTableAjaxPostUrl;var a=!0;void 0!==$(t).attr("dt-disable-on-type-search")&&(a=!1);var r=void 0!==$(".defaultOrder").html()?[[$("th.defaultOrder").index(),"desc"]]:[1,"desc"],o="undefined"!=typeof defaultiDisplayLength?defaultiDisplayLength:15,n=void 0!==$(t).attr("dt-height")?$(t).attr("dt-height"):"60vh",s=$(t).DataTable({processing:!0,serverSide:!0,responsive:!0,scrollX:!0,scrollY:n,scrollCollapse:!0,stateSave:!0,search:{return:!0},initComplete:function(t,e){if(a){var r=new $.fn.dataTable.Api(t);$(".dataTables_filter input").unbind(),$(".dataTables_filter input").bind("keyup",(function(t){13==(t.keyCode||t.which)&&r.search(this.value).draw()}))}},stateSaveParams:function(t,e){var a=this.api();e.search.search="",e.length=15,e.order=r,e.columns.forEach(((t,r)=>{var o=a.column(r).footer(),n=$(o).find("select");n.length>0&&(e.columns[r].search.text=$(n).find(":selected").text())}))},order:r,select:{style:"multi+shift",selector:"td:first-child"},language:Object.keys(language).length>0?language:{processing:"<i style='color: #3c8dbc;' class='fa fa-spinner fa-2x fa-spin fa-fw'></i><span style='margin-left: 10px;'>Processing...</span>"},aLengthMenu:[[15,100,500,1500,5e3,-1],[15,100,500,1500,5e3,"All"]],iDisplayLength:o,ajax:{url:e,type:"post"},columnDefs:[{targets:"countTotal",className:"text-right",render:$.fn.dataTable.render.number(",",".",2)},{targets:"highlightWithCountTotal",className:"text-right highlight",render:$.fn.dataTable.render.number(",",".",2)},{targets:"text-right",className:"text-right"},{targets:"sort",orderable:!0,searchable:!0},{targets:"no-sort",orderable:!1},{targets:0,orderable:!1,checkboxes:{selectRow:!0}},{targets:"px85",className:"px85"},{targets:"px120",className:"px120"},{targets:"px160",className:"px160"},{targets:"px180",className:"px180"},{targets:"px200",className:"px200"},{targets:"px220",className:"px220"},{targets:"px320",className:"px320"},{visible:!1,targets:"hideit"},{targets:"dtDescription",className:"dtDescription"},{targets:"highlight",className:"highlight"}],footerCallback:function(t,e,a,r,o){this.api().columns(".countTotal, .highlightWithCountTotal",{page:"current"}).every((function(){var t=this.data().reduce((function(t,e){return(parseFloat(t)||0)+(parseFloat(e)||0)}),0);$(this.footer()).html(t.toFixed(2).replace(/\d(?=(\d{3})+\.)/g,"$&,"))}))}}),l=s.state.loaded();l=null!==l?l.columns:void 0,s.columns().every((function(t){var e=this,a=$("select, textarea, input:not(.notThisValueFilter)",this.footer());if(void 0!==l&&a.length>0){var r=l[t].search.search,o=void 0!==l[t].search.text?l[t].search.text:"";"SELECT"===a[0].nodeName?($(a).find("option[value='"+r+"']").remove(),$(a).append($(`<option selected="selected" value="${r}">${o}</option>`))):$(a).val(r)}$("input, select, textarea",this.footer()).on("enter change clear apply.daterangepicker cancel.daterangepicker",(function(){var t,a=$(this).closest("th").find(".notThisValueFilter");t=a.length>0&&"!="===$(a).val()&&""!==this.value?JSON.stringify({operator:"!=",search:this.value}):this.value,e.search()!==this.value&&e.search(t).draw()}))}));var c=new Date,i=`${c.getDate()}-${c.getMonth()+1}-${c.getFullYear()} ${c.getHours()}:${c.getMinutes()}:${c.getSeconds()}`;$(".printButtonPosition").length>0&&(new $.fn.dataTable.Buttons(s,{buttons:[{extend:"print",text:'<i class="fa fa-print"></i> <?= __("Print"); ?>',titleAttr:"Print",className:"btn btn-default btn-sm",messageTop:"<b>Printed On:</b> "+i,title:"",footer:!0,autoPrint:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){return void 0!==$("#DtExportTopMessage").html()?$("#DtExportTopMessage").html():"<h2 class='text-center'>"+document.title+"</h2><br/> <p class='text-center'> <strong>Printed On: </strong> "+i+" </p> <br/>"}},{extend:"copy",text:'<i class="fa fa-files-o"></i> <?= __("Copy"); ?>',titleAttr:"Copy",className:"btn btn-default btn-sm",footer:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}}},{extend:"excel",text:'<i class="fa fa-file-excel-o"></i> <?= __("Export to Excel"); ?>',titleAttr:"Excel",className:"btn btn-default btn-sm",footer:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){if(void 0!==$("#DtExportTopMessage").html())return $("#DtExportTopMessage").html()}},{extend:"pdf",text:'<i class="fa fa-file-pdf-o"></i> <?= __("Export to PDF"); ?>',titleAttr:"PDF",className:"btn btn-default btn-sm",exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){if(void 0!==$("#DtExportTopMessage").html())return $("#DtExportTopMessage").html()}},{extend:"colvis",text:'<i class="fa fa-columns"></i> <?= __("Hide"); ?>',className:"btn btn-default btn-sm",collectionLayout:"fixed"}]}),s.buttons().container().appendTo(".printButtonPosition")),$("#dataTableWithAjaxExtend tbody").on("click",".has-child-row",(function(){var t=$(this).closest("tr"),e=s.row(t),a=$(this).attr("data-parent-product-id"),r=$("#productReportWarehouseSelection").select2("data")[0].id,o=$(this).text(),n=this;e.child.isShown()?(e.child.hide(),t.removeClass("shown")):($(n).html(`${o} <i style='margin-left: 5px;' class='fa fa-spinner fa-spin'></i>`),BMS.fn.get(`getChildProductData&pid=${a}&wid=${r}`,(function(a){0==a?BMS.fn.alertError("Sorry! no item found."):(e.child(function(t){var e=s.columns().visible(),a="";return t.forEach((t=>{a+='<tr class="childRow" style="display: none; background-color: #f2fcff;">',t.forEach(((t,r)=>{var o=s.columns().header()[r].className;a+=e[r]?`<td class='${o}'>${t}</td>`:""})),a+="</tr>"})),$(a).toArray()}(a)).show(),t.addClass("shown"),$("tr.childRow").fadeIn("slow")),$(n).html(`${o}`)})))}))},select2:function(t,e="",a=""){var r=$(t).attr("select2-ajax-url"),o=$(t).attr("select2-minimum-input-length"),n="true"===$(t).attr("select2-tag"),s="false"!==$(t).attr("closeOnSelect"),l="";l=void 0===$(t).attr("select2-create-new-url")?"<?php echo __('Nothing found')?>":`<span class="createNewSelect2Item" onClick="BMS.fn.createNewSelect2Item('#${$(t).attr("id")}')" style="cursor: pointer; display: block;"> <i class="fa fa-plus"></i> <?php echo __("Create new..."); ?></span>`,$(document).on("keyup",".select2-search__field",(function(t){"Enter"===t.key&&$(".createNewSelect2Item").click()}));var c=$(t).select2({placeholder:$(t).children("option:first").html()?$(t).children("option:first").html():"Select Options",allowClear:!0,closeOnSelect:s,tags:n,minimumInputLength:o,language:{noResults:function(){return l}},escapeMarkup:function(t){return t},ajax:{url:r,dataType:"json",delay:400,processResults:function(t){return{results:t}},cache:!0},templateResult:function(t){if(!t.id)return t.text;if("object"==typeof t.text){var e=t.text,a="";return a+=` <div style="width: 98%;" class='row'>\n <div class='col-md-5'>${e[0]}</div>\n <div class='col-md-1'>Cost</div>\n <div class='col-md-1'>Price</div>\n <div class='col-md-2'>Stock</div>\n <div class='col-md-3 adjustFormGroupPaddingRight'>Brand</div>\n </div>\n `,a+=` <div style="width: 98%;" class='row'>\n <div class='col-md-5'>${e[1]}</div>\n <div class='col-md-1'>${e[2]}</div>\n <div class='col-md-1'>${e[3]}</div>\n <div class='col-md-2'>${e[4]}</div>\n <div class='col-md-3 adjustFormGroupPaddingRight'>${e[5]}</div>\n </div>\n `}return t.text}});if(""!==a&&""===e)$.ajax({type:"get",url:r+"&q="+a}).then((function(t){if(void 0!==(t=JSON.parse(t)[0])){var e=new Option(t.text,t.id,!0,!0);c.append(e).trigger("change")}}));else if(""!==e&&c.find(":selected").val()!==e){var i=new Option(a,e,!0,!0);c.append(i).trigger("change")}},get:function(t,e){$.ajax({url:full_website_address+`/info/?module=data&page=${t}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,a){e(t)},error:function(){e("")}})}},BMS.fn=BMS.FUNCTIONS,BMS.MAIN={printPage:function(t,e,a=function(){}){e.preventDefault(),$(".dynamic-container > iframe").remove();var r=document.createElement("iframe");r.onload=function(){this.contentWindow.focus(),this.contentWindow.print(),a(!0)},r.style.position="fixed",r.style.right="0",r.style.bottom="0",r.style.width="0",r.style.height="0",r.style.border="0",r.src=t,$(".dynamic-container").append(r)},addTariffChargesRow:function(t){$(t).append(`<div class="row"><br/> \n <div class="col-md-7"> \n <select name="tariffChargesName[]" class="form-control select2Ajax tariffChargesName" select2-ajax-url="${full_website_address}/info/?module=select2&page=tariffCharges"> \n <option value="">Select Tariff/Charges</option> \n </select> \n </div> \n <div class="col-md-4"> \n <input type="number" name="tariffChargesAmount[]" class="form-control tariffChargesAmount" step="any"> \n </div> \n <div class="col-md-1"> \n <i style="cursor: pointer; padding-top: 9px;" class="fa fa-trash-o removeThisTariffCharges"></i> \n </div> \n </div>`)}},BMS.PRODUCT={isExists:function(t,e=".productID"){return $(e).filter((function(){return this.value===t})).length>0},validationCheck:function(t,e,a){if(this.isExists(t.pid))return alert(`The product (${t.pn}) is already in the list.`);if(void 0===t.pv)return a(t);var r="",o={},n=[],s={};$.each(t.pv,(function(t,e){Array.isArray(o[e.mk])?o[e.mk].includes(e.mv)||o[e.mk].push(e.mv):o[e.mk]=[e.mv],"DV"===e.t?n.push(e.mv):Array.isArray(s[e.id])?s[e.id].push(e.mv):s[e.id]=[e.mv]})),$.each(o,(function(t,e){r+=`<div id="variationSelection" class="form-group row text-left">\n <label class="col-sm-4">${t}:</label>\n <div class="col-sm-8">\n <select class="form-control">\n <option value="">Select ${t}...</option>`,$.each(e,(function(t,e){r+="<option "+(n.includes(e)?"selected":"")+` value="${e}">${e}</option>`})),r+=" </select>\n </div>\n </div>"})),Swal.fire({title:"<strong>Select Variation</strong>",html:"for "+t.pn+" <br/><br/>"+r,showCloseButton:!0,showCancelButton:!0,focusConfirm:!1,confirmButtonText:"Ok"}).then((t=>{if(t.isConfirmed){var a=$("#variationSelection select"),r=[];$.each(a,(function(){""!==this.value&&r.push(this.value)}));var o="";$.each(s,(function(t,e){if(r.every((t=>e.includes(t))))return o=t,!1})),""===o||0===r.length?Swal.fire("Sorry! no product found"):e.addProduct(o)}}))},parseProductList:function({category:t="",brand:e="",edition:a="",generic:r="",author:o=""},n){$.ajax({url:full_website_address+`/info/?module=data&page=productList&catId=${t}&brand=${e}&edition=${a}&generic=${r}&author=${o}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){n(t)}})},showProduct:function({container:t="#productListContainer",category:e="",brand:a="",edition:r="",generic:o="",author:n=""}=""){this.parseProductList({category:e,brand:a,edition:r,generic:o,author:n},(e=>{if(null!=e){var a="";e.forEach((t=>{var e=full_website_address;t.v&&t.v>0?e+="/images/?for=products&id="+t.id+"&q=YTozOntzOjI6Iml3IjtpOjIwMDtzOjI6ImloIjtpOjIyMDtzOjI6ImlxIjtpOjcwO30=&v="+t.v:e+="/assets/images/noimage.png",a+="<button type='button' value='"+t.id+"' title='"+t.name+"' data-toggle='tooltip' class='productButton btn-product btn-default'> <img src='"+e+"' style='width:60px; height:60px;' alt='"+t.name+"'> <span> "+t.name+" </span> </button> "})),$(t).html(a)}else $(t).html("<div class='alert alert-danger'>Sorry! No products found in this criteria.</div>")}))},getDetails:function(t,e){$.ajax({url:full_website_address+`/info/?module=data&page=productDetails&product_id=${t}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,a){e(t)}})},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?this.getDetails(a,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{if("1"!==t.hed){var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr>\n <input type="hidden" name="bgProductID[]" class="productID" value="${t.pid}">\n <td class="col-md-5">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="bgProductQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-2">${t.pu}</td>\n <td class="text-right col-md-2 gbProductPrice"><input onclick = "this.select()" type="text" name="bgProductSalePrice[]" value="${t.sp}" class="productSalePrice form-control text-center" step="any"></td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}else BMS.fn.alertError("Sorry! The product which have expiry date or batch number, can not be added in sub/bundle product.")})),$("#selectProduct").empty()})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select()})):alert("Please select a product")},getListByGeneric:function(t){BMS.fn.select2("#productGenericFilter",t,t)},productUnitCheck:function(t){this.getDetails({product_id:$(t).closest("tr").find(".productID").val(),unit:$(t).val()},(e=>{$(t).closest("tr").find(".productSalePrice").val(e[0].sp)}))}},BMS.POS={clearScreen:function(){$(".dynamic-container").slideUp(350,(function(){var t=new Date;$("#salesDate").val(t.toISOString().split("T")[0]),$("#tariffCharges .row").not("div:first").remove(),$(".tariffChargesName").val("").change();$(".paymentMethodBox").html('<div style="margin: 0;" class="row">\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Amount</label>\n <input type="number" onclick="this.select();" name="posSalePaymentAmount[]" class="form-control posSalePaymentAmount" step="any">\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Reference/Info</label>\n <input type="text" name="posSalePaymentReference[]" class="form-control">\n </div>\n <div style="display: none;" class="posSalePaymentBankAccount form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Bank Account</label>\n <select name="posSalePaymentBankAccount[]" class="form-control pull-left select2Ajax" \n select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=accountList" style="width: 100%;">\n <option value=""><?php echo __("Select Account"); ?>....</option>\n </select>\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Payment Method</label>\n <select name="posSalePaymentMethod[]" class="posSalePaymentMethod form-control">\n <option value="Cash"><?php echo __("Cash"); ?></option>\n <option value="Bank Transfer"><?php echo __("Bank Transfer"); ?></option>\n <option value="Cheque"><?php echo __("Cheque"); ?></option>\n <option value="Card"><?php echo __("Card"); ?></option>\n <option value="Others"><?php echo __("Others"); ?></option>\n </select>\n </div>\n </div>'),$("#orderDiscountValue, #shippingCharge, .posSalePaymentAmount, #adjustAmount, #salesNote").val(""),$("#shippingCharge").removeClass("shippingChargeEdited"),$(".posSalePaymentAmount").removeClass("disablePaymentAmountAutoChange"),$("#productTable > tbody").html(""),$("#editSalesId").remove(),$("#payment .modal-footer").html('\n <button type="button" class="btn btn-default pull-left" data-dismiss="modal"><?= __("Close"); ?></button>\n <button name="posAction" value="sale_is_confirmed" style="visibility: hidden;" type="submit"></button>\n <button name="posAction" value="sale_is_hold" type="submit" class="posSubmit btn btn-warning"><i class="fa fa-pause-circle"></i> <?= __("Hold"); ?></button>\n <button name="posAction" value="sale_is_confirmed" type="submit" class="posSubmit btn btn-success"><i class="fa fa-check-circle"></i> <?= __("Confirm"); ?></button>\n '),$("input:radio, input:checkbox").prop("checked",!1),BMS.fn.select2("#customers",1,"Walk-in Customer"),BMS.POS.grandTotal(),BMS.POS.disableEnableWCSelect()})).slideDown(500)},getProductDetails:function({product_id:t,warehouse_id:e,customer_id:a="",qnt:r="",batch:o="",packet:n=""},s){$.ajax({url:full_website_address+`/info/?module=data&page=productDetailsForPos&product_id=${t}&warehouse_id=${e}&cid=${a}&pqnt=${r}&batch=${o}&packet=${n}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){s(t)}})},disableEnableWCSelect:function(){$(".productQnt").length>0?$("#customers, #warehouse").prop("disabled",!0):$("#customers, #warehouse").prop("disabled",!1)},grandTotal:function(t=""){var e=0,a=0;$(".productQnt").each((function(){e+=Number($(this).val()),a+=1})),$(".totalItemAndQnt").html(a+" ("+e+")");var r=0;$(".subtotalCol").each((function(){r+=Number($(this).html())})),$(".totalAmount").html(r.toFixed(2));var o=$("#orderDiscountValue").val(),n=BMS.FUNCTIONS.calculateDiscount(r,o);$(".totalOrderDiscountAmount").html("(-) "+(r-n).toFixed(2));var s=0;if($("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(n,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),s+=Number(e)})),$(".totalTariffChargesAmount").html("(+) "+s.toFixed(2)),!0===$("#payment").hasClass("in")){if(!1===$("#shippingCharge").is(":focus")&&($("#totalPackets").is(":focus")||$("#packetShippingRate").is(":focus"))){var l=$("#totalPackets").val()*$("#packetShippingRate").val();$("#shippingCharge").val(l)}}else{var c=0;$(".productPacket").each((function(){c+=Number($(this).val())})),$(".displayTotalPackets").html(c.toFixed(2)),$("#totalPackets").val(Math.round(c));l=$("#totalPackets").val()*$("#packetShippingRate").val();$("#shippingCharge").val(l)}var i=(Number(s)+Number(n)).toFixed(2);$(".netTotalAmount").html(i),$("#finalizeSale > tbody > tr:nth-child(1) > td:nth-child(3)").html(i);var d=Number($("#shippingCharge").val()),u=Number(i)+d;"1"===config.posSaleAutoAdjustAmount&&$("#adjustAmount:not(.disableAdjustAmountAutoChange)").val(parseFloat(parseFloat(u).toFixed()-u).toFixed(2));var p=Number($("#adjustAmount").val());u=parseFloat(Number(i)+d+Number(p)).toFixed(2);if("1"===config.posSaleAutoMarkAsPaid){var m=sumInputs(".disablePaymentAmountAutoChange"),h=0;(u>0&&u>m||u<0&&u<m)&&(h=u-m),$(".posSalePaymentAmount:not(.disablePaymentAmountAutoChange)").first().val(parseFloat(h).toFixed(2))}var f=sumInputs(".posSalePaymentAmount"),v=u<f?f-u:0,g=u>f?u-f:0;$("#finalizeSale > tbody > tr:nth-child(4) > td:nth-child(2)").html(u),$("#finalizeSale > tbody > tr:nth-child(6) > td:nth-child(2)").html(v),$("#finalizeSale > tbody > tr:nth-child(7) > td:nth-child(2)").html(g),$("#quickPayableAmount").html(u),!0===$("#payment").hasClass("in")&&(u>0&&u<f||u<0&&u>f)&&(Swal.fire({title:"Paid amount can not be more then Grand total.",icon:"error"}),$(".posSalePaymentAmount").last().val(0))},editProductItemDetails:function(t,e){$("#productSaleDetails .modal-title").html(e),$("#productSaleDetails .rowId").val(t);var a=$(`#${t}`);$("#productSaleDetails #productSaleItemPrice").val(a.find(".netSalesPrice").val()),$("#productSaleDetails #productSaleItemDiscount").val(a.find(".productDiscount").val()),$("#productSaleDetails #productSaleItemPacket").val(a.find(".productPacket").val()),$("#productSaleDetails #productSaleItemDetails").val(a.find(".productItemDetails").val())},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?($("#selectProduct").val()>0&&$("#selectProduct").html("<option value=''>Search Product....</option>"),this.getProductDetails({product_id:a,warehouse_id:$("#warehouseId").val(),customer_id:$("#customersId").val()},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=0,r=t.iq?parseFloat(t.iq).toFixed(0):1;t.pq>0&&(e=(r/Number(t.pq)).toFixed(2));var o=t.pd?t.pd:"0",n=BMS.FUNCTIONS.calculateDiscount(t.sp,o),s="";s=Number(n)===Number(t.sp)?parseFloat(t.sp).toFixed(2):"<span>"+parseFloat(n).toFixed(2)+"</span><span><del><small>"+parseFloat(t.sp).toFixed(2)+"</small></del></span>";var l=Date.now()+t.pid,c=null===t.gn?"":`<small style="cursor: zoom-in;" onClick="BMS.PRODUCT.getListByGeneric('${t.gn}')"><i>${t.gn}</i></small>`,i=`<tr ${t.so?'style="background-color: pink;"':""} id=${l}> \n <td class="col-md-7">\n <span data-toggle="modal" data-target="#modalDefault" href="${full_website_address}/xhr/?module=reports&page=totalPurchasedQuantityOfThisCustomer&cid=${$("#customersId").val()}&pid=${a}"> <i class="fa fa-info-circle productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails('${l}', '${t.pn}')" data-target="#productSaleDetails">${t.pn}</a>\n ${c}\n </td> \n <td class="col-md-2 displayProductPrice text-right">${s}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="${r}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${t.pu}</td> \n <td class="col-md-3 subtotalCol text-right">${parseFloat(Number(n)*Number(r)).toFixed(2)}</td> \n <td style="width: 25px !important;"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t.pid}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productSO" value="${t.so}"> \n <input type="hidden" name="productDiscount[]" value="${o}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="">\n <input type="hidden" name="productHasExpiryDate[]" value="${t.hed}"> \n <input type="hidden" name="productPacket[]" value="${e}" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(i)}))})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),this.disableEnableWCSelect()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})}))):alert("Please select a product")},addReturnProduct:function(t,e,a,r,o,n,s,l,c,i){if(!BMS.PRODUCT.isExists(t)||confirm(`The product (${e}) is already in the list. Do you want to add it again?`)){var d=Date.now()+t,u=`<tr id=${d}> \n <td class="col-md-7">\n <span> <i class="fa fa-undo productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails(${d}, '${e}')" data-target="#productSaleDetails">${e}</a>\n ${null===a?"":`<small style="cursor: zoom-in;" onClick="BMS.PRODUCT.getListByGeneric('${a}')"><i>${a}</i></small>`}\n </td> \n <td class="col-md-2 displayProductPrice text-right">${l}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="-${c}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${o}</td> \n <td class="col-md-3 subtotalCol text-right">-${i}</td> \n <td style="width: 25px; !important"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${l}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${l}"> \n <input type="hidden" name="productDiscount[]" value="${s}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="${r}">\n <input type="hidden" name="productHasExpiryDate[]" value="${n}"> \n <input type="hidden" name="productPacket[]" value="0" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(u),this.grandTotal()}},productQntCheck:function(t,e){var a=$(t).closest("tr").find(".netSalesPrice").val(),r=$(t).val(),o=$(t).closest("tr").find(".productDiscount").val(),n=$(t).closest("tr").find("td.subtotalCol"),s=$(t).closest("tr").find(".productPacket"),l=t;0==r&&(Swal.fire({title:"Error!",text:"Product qunatity can not be zero (0)",icon:"error"}),$(t).val(1),r=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#warehouseId").val(),qnt:r,unit:$(t).closest("tr").find(".productItemUnit").val()},(e=>{void 0!==e.error&&!0===e.error&&($(l).val(e.stq),r=e.stq,Swal.fire({title:"Error!",text:e.msg,icon:"error"})),(e=e[0]?e[0]:e).so?$(t).closest("tr").css("background-color","pink"):$(t).closest("tr").css("background-color","white"),$(n).html((BMS.FUNCTIONS.calculateDiscount(a,o)*r).toFixed(2));var c=0;Number(e.pq)>0&&(c=(r/Number(e.pq)).toFixed(2)),s.val(c),this.grandTotal()}))},productPacketCheck:function(){var t=$(selector).closest("tr").find(".netSalesPrice").val(),e=$(selector).val(),a=$(selector).closest("tr").find(".productDiscount").val(),r=$(selector).closest("tr").find("td.subtotalCol"),o=$(selector).closest("tr").find(".productQnt"),n=$(selector).closest("tr").find(".productPacket");this.getProductDetails({product_id:$(selector).closest("tr").find(".productID").val(),warehouse_id:$("#warehouseId").val(),packet:e},(s=>{if(void 0!==s.error&&!0===s.error){$(o).val(s.having_item_quantity),$(r).html((BMS.FUNCTIONS.calculateDiscount(t,a)*s.having_item_quantity).toFixed(2));var l=0;Number(s.product_packet_quantity)>0&&(l=(s.having_item_quantity/Number(s.product_packet_quantity)).toFixed(2)),n.val(l),Swal.fire({title:"Error!",text:s.msg,icon:"error"})}else{var c=Math.round(Number(s.product_packet_quantity)*e);c>0&&($(o).val(c),$(r).html((BMS.FUNCTIONS.calculateDiscount(t,a)*c).toFixed(2)))}this.grandTotal()}))},productDiscountCheck:function(t){var e=$("#productSaleItemPrice").val(),a=$("#productSaleItemDiscount").val();"Enter"===t.key&&a.indexOf("%")>1&&a.replace("%","")>=100?(Swal.fire({title:"Error!",text:"Discount Must be below of 100%",icon:"error"}),$("#productSaleItemDiscount").val(""),$("#productSaleItemDiscount").select(),t.preventDefault()):"Enter"===t.key&&Number(a)>=Number(e)&&a.indexOf("%")<1&&($("#productSaleItemDiscount").val(""),$("#productSaleItemDiscount").select(),"Enter"===t.key&&t.preventDefault(),Swal.fire({title:"Error!",text:"Discount Must be below of product sale price",icon:"error"}),t.preventDefault())},orderDiscountCheck:function(t,e){var a=$(".totalAmount").text(),r=$(t).val();r.indexOf("%")>1&&r.replace("%","")>=100?(Swal.fire({title:"Error!",text:"Discount Must be below of 100%",icon:"error"}),$(t).val(0),e.preventDefault()):Number(a)<0&&Number(r)>0?(Swal.fire({title:"Error!",text:"Discount must be a negative amount in case of negative total amount.",icon:"error"}),$(t).val(-Number(r)),e.preventDefault()):Number(a)<0&&(Number(r)>0||Math.abs(Number(r))>=Math.abs(Number(a)))||Number(a)>0&&Number(r)>=Number(a)&&r.indexOf("%")<1?(Swal.fire({title:"Error!",text:"Discount Must be below of total amount.",icon:"error"}),$(t).val(0),e.preventDefault()):!0!==this.isGivenDiscountPermitted(t)&&(Swal.fire({title:"Error!",text:`You do not have permission to give ${r} discount.`,icon:"error"}),$(t).val(0),e.preventDefault()),this.grandTotal()},isGivenDiscountPermitted:function(t){var e=$(".totalAmount").text(),a=$(t).val();if(""!=get_options("maxDiscount")){var r=e-BMS.FUNCTIONS.calculateDiscount(e,get_options("maxDiscount")),o=e-BMS.FUNCTIONS.calculateDiscount(e,a);return Math.abs(r)>=Math.abs(o)}return!0}},BMS.PURCHASE={getProductDetails:BMS.PRODUCT.getDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#purchaseDiscountValue").val());$(".totalPurchaseDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#purchaseNetTotal").val(o);var n=Number(o)+Number($("#purchaseShipping").val());$("#purchaseGrandTotal").val(n);var s=Number($("#purchasePaidAmount").val()),l=n<=s?0:n-s,c=n>=s?0:s-n;$("#purchaseChangeAmount").val(c),$("#purchaseDueAmount").val(l)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return isNaN(a)?(alert("Product quantity must be a valid number."),void $(t).closest("tr").find(".productQnt").val(1)):a<1&&"Ordered"!==$("#purchaseStatus").val()?(alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?this.getProductDetails(a,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&"Ordered"!==$("#purchaseStatus").val()&&(e=`<select name="productBatch[]" id="productBatchFor${t.pid}" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="stock_col" style="width: 155px;"><span>${t.alertq}</span> <span>${t.soldq}</span> <span>${t.stockq}</span></td>\n <td><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td>${t.pu}</td>\n <td class="text-right"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" class="productMainPurchasePrice" value="${t.pp}" step="any">\n <td class="text-right"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="0" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${t.pp}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),$("#selectProduct").empty()})):alert("Please select a product")},productUnitCheck:function(t){var e=$(t).closest("tr").find(".productID").val(),a=this;$.ajax({url:full_website_address+"/info/?module=data&page=productUnitDetails&product_id="+e+"&unit="+$(t).val(),contentType:"application/json; charset=utf-8",dataType:"json",success:function(e,r){"success"==r&&($(t).closest("tr").find(".productPurchasePrice").val(e.pp),$(t).closest("tr").find(".productMainPurchasePrice").val(e.pp),a.calculateEachProduct(t),a.grandTotal())}})}},BMS.ORDER=Object.assign({},BMS.POS),BMS.ORDER.addProduct=function(t=""){var e=""===t?$("#selectProduct").val():t;""!==e?($("#selectProduct").val()>0&&$("#selectProduct").html("<option value=''>Search Product....</option>"),BMS.PRODUCT.getDetails(e,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var a=0,r=t.iq?parseFloat(t.iq).toFixed(0):1;t.pq>0&&(a=(r/Number(t.pq)).toFixed(2));var o=t.pd?t.pd:"0",n=BMS.FUNCTIONS.calculateDiscount(t.sp,o),s="";s=Number(n)===Number(t.sp)?parseFloat(t.sp).toFixed(2):"<span>"+n+"</span><span><del><small>"+parseFloat(t.sp).toFixed(2)+"</small></del></span>";var l=Date.now()+t.pid,c=`<tr ${t.so?'style="background-color: pink;"':""} id=${l}> \n <td class="col-md-7">\n <span data-toggle="modal" data-target="#modalDefault" href="${full_website_address}/xhr/?module=reports&page=totalPurchasedQuantityOfThisCustomer&cid=${$("#customersId").val()}&pid=${e}"> <i class="fa fa-info-circle productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails('${l}', '${t.pn}')" data-target="#productSaleDetails">${t.pn}</a>\n </td> \n <td class="col-md-2 displayProductPrice text-right">${s}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="${r}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${t.pu}</td> \n <td class="col-md-3 subtotalCol text-right">${parseFloat(Number(n)*Number(r)).toFixed(2)}</td> \n <td style="width: 25px !important;"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t.pid}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productSO" value="${t.so}"> \n <input type="hidden" name="productDiscount[]" value="${o}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="">\n <input type="hidden" name="productHasExpiryDate[]" value="${t.hed}"> \n <input type="hidden" name="productPacket[]" value="${a}" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(c)}))})),$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),this.disableEnableWCSelect()}))):alert("Please select a product")},BMS.ORDER.productQntCheck=function(t,e){var a=$(t).closest("tr").find(".netSalesPrice").val(),r=$(t).val(),o=$(t).closest("tr").find(".productDiscount").val(),n=$(t).closest("tr").find("td.subtotalCol");0==r&&(Swal.fire({title:"Error!",text:"Product qunatity can not be zero (0)",icon:"error"}),$(t).val(1),r=1),$(n).html((BMS.FUNCTIONS.calculateDiscount(a,o)*r).toFixed(2)),this.grandTotal()},BMS.STOCK_TRANSFER={getProductDetails:BMS.POS.getProductDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2))},disableEnableWarehouseSelect:function(){$(".productQnt").length>0?$("#stockTransferFromWarehouse, #stockTransferToWarehouse").prop("disabled",!0):$("#stockTransferFromWarehouse, #stockTransferToWarehouse").prop("disabled",!1)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return a<1?(alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t,r=$("#stockTransferFromWarehouseId").val();""!==r?""!==a?this.getProductDetails({product_id:a,warehouse_id:r,qnt:1},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(e=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td class="col-md-1"> ${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" value="${t.pp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${parseFloat(t.pp*a).toFixed(2)}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),this.grandTotal(),this.disableEnableWarehouseSelect(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")},productUnitCheck:function(t){var e=t;this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#stockTransferFromWarehouseId").val(),qnt:$(t).closest("tr").find(".productQnt").val(),unit:$(t).val()},(t=>{void 0!==t.error&&!0===t.error&&(console.log(t.stq),$(e).closest("tr").find(".productQnt").val(t.stq),Swal.fire({title:"Error!",text:t.msg,icon:"error"})),$(e).closest("tr").find(".productPurchasePrice").val(parseFloat(t.pp).toFixed(2)),this.calculateEachProduct(e),this.grandTotal()}))},productQntCheck:function(t){var e=$(t).val(),a=$(t);isNaN(e)&&(alert("Product quantity must be a valid number."),$(t).val(1),e=1),e<1&&(Swal.fire({title:"Error!",text:"Product qunatity must be at least one",icon:"error"}),$(t).val(1),e=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#stockTransferFromWarehouseId").val(),qnt:e,unit:$(t).closest("tr").find(".productItemUnit").val()},(t=>{void 0!==t.error&&!0===t.error&&($(a).val(t.stq),Swal.fire({title:"Error!",text:t.msg,icon:"error"})),this.calculateEachProduct(a),this.grandTotal()}))}},BMS.STOCK_ENTRY={getProductDetails:BMS.PRODUCT.getDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2))},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return a<1&&"Production"===$("#stockEntryType").val()?(alert("Negative quantity is not valid for Production of stock."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t;""!==$("#stockTransferFromWarehouseId").val()?""!==e?this.getProductDetails(e,(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(e=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td class="col-md-1"> ${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" value="${t.pp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${parseFloat(t.pp*a).toFixed(2)}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),this.grandTotal(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")}},BMS.RETURN={getProductReturnDetails:function({product_id:t,customer_id:e},a){$.ajax({url:full_website_address+"/info/?module=data&page=productDetailsForReturn&product_id="+t+"&customer_id="+e,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){a(t)}})},grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalReturnPrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#returnDiscountValue").val());$(".totalReturnDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#returnNetTotal").val(o);var n=$("#returnShipping").val(),s=Number(o)+Number(n)-Number($("#returnSurcharge").val());$("#returnGrandTotal").val(s);var l=Number($("#returnPaidAmount").val()),c=s<=l?0:s-l,i=s>=l?0:l-s;$("#returnChangeAmount").val(i),$("#returnDueAmount").val(c)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productReturnPrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productReturnDiscount").val(),o=$(t).closest("tr").find(".subTotal");if(a<1)return alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1);""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productReturnPrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?alert("Discount Must be below of 100%"):Number(r)>Number(e)&&r.indexOf("%")<1?alert("Discount Must be below of product return price"):$(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2))},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t,a=$("#returnCustomer").val();""!==a?""!==e?this.getProductReturnDetails({product_id:e,customer_id:a},(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.pd?t.pd:"0",a=parseFloat(BMS.FUNCTIONS.calculateDiscount(t.sp,e)).toFixed(2),r="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(r=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var o=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4 productDetails">${t.pn}<br/>(<i>Purchased: ${t.prq} Returned: ${t.rtq}</i>)</td>\n <td class="col-md-2">${r}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="1" class="productQnt form-control text-center"></td>\n <td class="col-md-1">${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productReturnPrice[]" value="${t.sp}" class="productReturnPrice form-control text-center" step="any"></td>\n <input type="hidden" name="productReturnMainPrice[]" value="${t.sp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productReturnDiscount[]" value="${e}" placeholder="10% or 10" class="productReturnDiscount form-control text-center"></td>\n <td class="text-right subTotal">${a}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(o)}))})),this.grandTotal(),$("#selectProduct").empty()})):alert("Please select a product"):alert("Please select the customer")},productUnitCheck:function(t){var e=t;this.getProductReturnDetails({product_id:$(t).closest("tr").find(".productID").val(),customer_id:$("#returnCustomer").val(),unit:$(t).val()},(t=>{var a=t[0];$(e).closest("tr").find(".productReturnPrice").val(parseFloat(a.sp).toFixed(2));var r=a.pn+"<br/>(<i>Purchased: "+parseFloat(a.prq).toFixed(2)+", Returned: "+parseFloat(a.rtq).toFixed(2)+")";$(e).closest("tr").find(".productDetails").html(r),this.calculateEachProduct(e),this.grandTotal()}))}},BMS.WASTAGE_SALE={grandTotal:function(){var t=0;$(".wastageSaleItemQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".wastageSaleItemQnt").length+"("+t+")");var e=0;$(".wastageSaleItemSubtotal").each((function(){e+=Number($(this).text())})),$(".totalWastageSalePrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#wastageSaleDiscountValue").val());$(".totalWastageSaleDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#wastageSaleNetTotal").val(o);var n=$("#wastageSalePaidAmount").val(),s=n<o?o-n:0;$("#wastageSaleDue").val(s.toFixed(2))},addWastageSaleItem:function(){$("#productTable > tbody").append('<tr> <td class="col-md-5"> <input type="text" name="wastageSaleItem[]" placeholder="Enter Item name and details" class="wastageSaleItem form-control" required> </td> <td class="col-md-2"> <input type="number" step="any" name="wastageSaleItemQnt[]" class="wastageSaleItemQnt form-control" required> </td> <td class="col-md-2"> <input type="number" step="any" name="wastageSaleItemPrice[]" class="wastageSaleItemPrice form-control" required> </td> <td class="text-right wastageSaleItemSubtotal">0.00</td> <td style="width: 30px; !important"> <i style="cursor: pointer;" class="fa fa-trash-o removeThisItem"></i> </td> </tr>'),$(".wastageSaleItem").focus(),this.grandTotal()}},BMS.SPECIMEN_COPY={getProductDetails:BMS.POS.getProductDetails,disableEnableWarehouseSelect:function(){$(".productQnt").length>0?$("#scTransferWarehouse").prop("disabled",!0):$("#scTransferWarehouse").prop("disabled",!1)},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t,a=$("#scTransferWarehouse").val();""!==a?""!==e?this.getProductDetails({product_id:e,warehouse_id:a},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr> <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-6">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="productQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-3">${t.pu}</td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}))})),this.disableEnableWarehouseSelect(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")},productUnitCheck:function(t){this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#scTransferWarehouse").val(),qnt:$(t).closest("tr").find(".productQnt").val(),unit:$(t).val()},(e=>{void 0!==e.error&&!0===e.error&&($(t).closest("tr").find(".productQnt").val(e.stq),Swal.fire({title:"Error!",text:e.msg,icon:"error"}))}))},productQntCheck:function(t){var e=$(t).val();isNaN(e)&&(alert("Product quantity must be a valid number."),$(t).val(1),e=1),e<1&&(Swal.fire({title:"Error!",text:"Product qunatity must be at least one",icon:"error"}),$(t).val(1),e=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#scTransferWarehouse").val(),qnt:e,unit:$(t).closest("tr").find(".productItemUnit").val()},(e=>{void 0!==e.error&&!0===e.error&&($(t).val(e.stq),Swal.fire({title:"Error!",text:e.msg,icon:"error"}))}))}},BMS.SC_DISTRIBUTION={getProductDetails:BMS.PRODUCT.getDetails,addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t;""!==e?this.getProductDetails(e,(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-6">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="productQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-3">${t.pu}</td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}))})),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product")}},BMS.CHAT={showChatBox:function(t,e){""!==t&&t.preventDefault(),$.ajax({url:full_website_address+"/info/?module=chat&page=getChatUserData",type:"post",data:{userId:e},success:function(t,a){t=JSON.parse(t);console.log(t);var r="";""!==t.latest_msg&&t.latest_msg.forEach((t=>{t.from_user!=e?r+=`<div class="direct-chat-msg">\n <div class="direct-chat-info clearfix">\n <span class="direct-chat-name pull-left">${t.from_username}</span>\n <span class="direct-chat-timestamp pull-right">${t.datetime}</span>\n </div>\n <img class="direct-chat-img" src="${full_website_address}/images/?for=employees&id=${t.from_user}">\n <div class="direct-chat-text">\n ${t.msg_text}\n </div>\n </div>`:r+=`<div class="direct-chat-msg right">\n <div class="direct-chat-info clearfix">\n <span class="direct-chat-name pull-right">${t.from_username}</span>\n <span class="direct-chat-timestamp pull-left">${t.datetime}</span>\n </div>\n <img class="direct-chat-img" src="${full_website_address}/images/?for=employees&id=${t.from_user}">\n <div class="direct-chat-text">\n ${t.msg_text}\n </div>\n </div>`}));var o=`<div class="chatBoxItem chatBoxForUser${e}">\n <input type="hidden" value=${e} class="userId">\n <div class="header">\n <img width='40px' height='40px' src='${full_website_address}/images/?for=employees&id=${e}' class='img-circle' />\n <div class="card" >\n <p class="name">${t.name}</p>\n <p>${t.position}</p>\n </div>\n <div class="action">\n <span class="close-chat">\n <i class="fa fa-close"></i>\n </span>\n </div>\n </div>\n <div class="direct-chat direct-chat-warning">\n \n <div class="direct-chat-messages">\n ${r}\n </div>\n </div>\n <div class="composer">\n <label for="chatAttachment${e}">\n <span title="Attach file" class="attachment">\n <i class="fa fa-plus"></i>\n </span>\n </label>\n <input style="display: none;" type="file" class="chat-attachment" id="chatAttachment${e}">\n <input type="text" placeholder="Type message and press enter to send ..." class="form-control message-composer">\n </div>\n </div>`;$(".chatBox").prepend(o).ready((function(){var t=$(`.chatBoxForUser${e}`).find(".direct-chat-messages"),a=$(t).get(0).scrollHeight;$(t).animate({scrollTop:a},0),$(t).closest(".chatBox").find(".message-composer").focus()}))}})},send:function(t,e){wss.send(JSON.stringify({type:"message",toUser:e,msg:t}))}};
\ No newline at end of file
+"use strict";var updateSDPTimeout,BMS=BMS||{};BMS.FUNCTIONS={getDateTime:function(){var t=new Date;return t.getFullYear()+"-"+t.getMonth()+"-"+t.getDay()+"-"+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds()},calculateDiscount:function(t,e=null){return""===e||null===e||"null"===e||0===e?parseFloat(Number(t)):"string"==typeof e&&e.indexOf("%")>0?parseFloat(Number(t)-Number(e.replace("%",""))/100*Number(t)):parseFloat(Number(t)-Number(e))},calculateTarifCharges:function(t,e=null){return""===e||null===e||"null"===e||0===e?0:"string"==typeof e&&e.indexOf("%")>0?(Number(e.replace("%",""))/100*Number(t)).toFixed(2):Number(e).toFixed(2)},datePicker:function({selector:t=".datePicker",format:e="YYYY-MM-DD",timePicker:a=!1}=""){$(t).daterangepicker({autoUpdateInput:!1,singleDatePicker:!0,showDropdowns:!0,timePicker:a,timePicker24Hour:!0,autoApply:!0,parentEl:"div.dynamic-container",drops:"auto",locale:{format:e,cancelLabel:"Clear"}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},dateRangePicker:function({selector:t=".dateRangePicker",format:e="YYYY-MM-DD",timePicker:a=!1}=""){$(t).daterangepicker({autoUpdateInput:!1,showDropdowns:!0,drops:"auto",linkedCalendars:!1,timePicker:a,timePicker24Hour:!0,parentEl:"div.dynamic-container",locale:{format:e,cancelLabel:"Clear"}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e)+" - "+a.endDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},dateRangePickerPreDefined:function({selector:t=".dateRangePickerPreDefined",format:e="YYYY-MM-DD",timePicker:a=!1,ranges:r={}}=""){$(t).daterangepicker({autoUpdateInput:!1,showDropdowns:!0,drops:"auto",alwaysShowCalendars:!0,linkedCalendars:!1,timePicker:a,timePicker24Hour:!0,parentEl:"div.dynamic-container",locale:{format:e,cancelLabel:"Clear"},ranges:Object.keys(r).length>0?r:{Today:[moment(),moment()],"This Month":[moment().startOf("month"),moment().endOf("month")],"Last Month":[moment().subtract(1,"month").startOf("month"),moment().subtract(1,"month").endOf("month")],"This Year":[moment().startOf("year"),moment().endOf("year")],"Last Year":[moment().subtract(1,"year").startOf("year"),moment().subtract(1,"year").endOf("year")],All:[moment(0),moment().subtract("year").endOf("day")]}}),$(t).on("apply.daterangepicker",(function(t,a){$(this).val(a.startDate.format(e)+" - "+a.endDate.format(e))})),$(t).on("cancel.daterangepicker",(function(t,e){$(this).val("")}))},multiDatePicker:function({selector:t=".multiDatePicker",format:e="yyyy-mm-dd"}=""){$(t).datepicker({multidate:!0,multidateSeparator:", ",format:e,todayHighlight:!0})},getCookie:function(t){var e=decodeURIComponent(`; ${document.cookie}`).split(`; ${t}=`);if(e.length>1)return e[1].split("; ")[0]},copy:function(t){var e=$(t);e.select(),navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([e.html()],{type:"text/html"})})])},_n:function(t){let e=BMS.fn.getCookie("lang"),a={bn_BD:"bn-BD"};return void 0!==e?new Intl.NumberFormat(a[e]).format(t):t},createNewSelect2Item:function(t){var e=$(t).attr("select2-create-new-url"),a=$(".select2-search__field").val(),r=encodeURIComponent(a);console.log(t),$("body").trigger("mousedown"),$("#modalDefault").modal("show").find(".modal-content").load(e+"&val="+r),$("#modalDefault").on("hidden.bs.modal",(function(e){BMS.fn.select2(t,"",a)}))},play:function(t,e=!1){var a=`${full_website_address}/assets/sounds/${t}.mp3`,r=new window.Audio(a);$(document).on("pauseAudio",(function(){r.pause()})),r.loop=e,r.play()},pause:function(){$(document).trigger("pauseAudio")},startTimer(t="#timer"){var e=(new Date).getTime();return setInterval((function(){var a=((new Date).getTime()-e)/1e3,r=Math.floor(a%60).toString().padStart(2,0),o=Math.floor(a%3600/60).toString().padStart(2,0),n=Math.floor(a/3600).toString().padStart(2,0);$(t).html(`${n}:${o}:${r}`)}),1e3)},stopTimer:function(t){clearInterval(t)},notify:function(t){Swal.fire({toast:!0,position:"top-right",timer:5e3,timerProgressBar:!0,iconHtml:'<i class="fa fa-bell"></i>',didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),this.play("beep")},title:`<span style="padding: 10px 0; font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},desktopNotify:function(t,e="",a=""){"granted"!==Notification.permission?Notification.requestPermission():new Notification(t,{icon:e,body:a}).onclick=function(){window.focus(),this.close()}},alertError:function(t){Swal.fire({toast:!0,position:"top-right",icon:"error",timer:5e3,timerProgressBar:!0,didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),this.play("warning")},title:`<span style="font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},alertSuccess:function(t,e=!0){Swal.fire({toast:!0,position:"top-right",icon:"success",timer:5e3,timerProgressBar:!0,didOpen:t=>{t.addEventListener("mouseenter",Swal.stopTimer),t.addEventListener("mouseleave",Swal.resumeTimer),e&&this.play("warning")},title:`<span style="font-size: 16px;"> ${t} </span>`,showConfirmButton:!1,onClose:$("body").css("padding","0px")})},dTable:function(t){var e="";e=void 0!==$(t).attr("dt-data-url")?$(t).attr("dt-data-url"):DataTableAjaxPostUrl;var a=!0;void 0!==$(t).attr("dt-disable-on-type-search")&&(a=!1);var r=void 0!==$(".defaultOrder").html()?[[$("th.defaultOrder").index(),"desc"]]:[1,"desc"],o="undefined"!=typeof defaultiDisplayLength?defaultiDisplayLength:15,n=void 0!==$(t).attr("dt-height")?$(t).attr("dt-height"):"60vh",s=$(t).DataTable({processing:!0,serverSide:!0,responsive:!0,scrollX:!0,scrollY:n,scrollCollapse:!0,stateSave:!0,search:{return:!0},initComplete:function(t,e){if(a){var r=new $.fn.dataTable.Api(t);$(".dataTables_filter input").unbind(),$(".dataTables_filter input").bind("keyup",(function(t){13==(t.keyCode||t.which)&&r.search(this.value).draw()}))}},stateSaveParams:function(t,e){var a=this.api();e.search.search="",e.length=15,e.order=r,e.columns.forEach(((t,r)=>{var o=a.column(r).footer(),n=$(o).find("select");n.length>0&&(e.columns[r].search.text=$(n).find(":selected").text())}))},order:r,select:{style:"multi+shift",selector:"td:first-child"},language:Object.keys(language).length>0?language:{processing:"<i style='color: #3c8dbc;' class='fa fa-spinner fa-2x fa-spin fa-fw'></i><span style='margin-left: 10px;'>Processing...</span>"},aLengthMenu:[[15,100,500,1500,5e3,-1],[15,100,500,1500,5e3,"All"]],iDisplayLength:o,ajax:{url:e,type:"post"},columnDefs:[{targets:"countTotal",className:"text-right",render:$.fn.dataTable.render.number(",",".",2)},{targets:"highlightWithCountTotal",className:"text-right highlight",render:$.fn.dataTable.render.number(",",".",2)},{targets:"text-right",className:"text-right"},{targets:"sort",orderable:!0,searchable:!0},{targets:"no-sort",orderable:!1},{targets:0,orderable:!1,checkboxes:{selectRow:!0}},{targets:"px85",className:"px85"},{targets:"px120",className:"px120"},{targets:"px160",className:"px160"},{targets:"px180",className:"px180"},{targets:"px200",className:"px200"},{targets:"px220",className:"px220"},{targets:"px320",className:"px320"},{visible:!1,targets:"hideit"},{targets:"dtDescription",className:"dtDescription"},{targets:"highlight",className:"highlight"}],footerCallback:function(t,e,a,r,o){this.api().columns(".countTotal, .highlightWithCountTotal",{page:"current"}).every((function(){var t=this.data().reduce((function(t,e){return(parseFloat(t)||0)+(parseFloat(e)||0)}),0);$(this.footer()).html(t.toFixed(2).replace(/\d(?=(\d{3})+\.)/g,"$&,"))}))}}),l=s.state.loaded();l=null!==l?l.columns:void 0,s.columns().every((function(t){var e=this,a=$("select, textarea, input:not(.notThisValueFilter)",this.footer());if(void 0!==l&&a.length>0){var r=l[t].search.search,o=void 0!==l[t].search.text?l[t].search.text:"";"SELECT"===a[0].nodeName?($(a).find("option[value='"+r+"']").remove(),$(a).append($(`<option selected="selected" value="${r}">${o}</option>`))):$(a).val(r)}$("input, select, textarea",this.footer()).on("enter change clear apply.daterangepicker cancel.daterangepicker",(function(){var t,a=$(this).closest("th").find(".notThisValueFilter");t=a.length>0&&"!="===$(a).val()&&""!==this.value?JSON.stringify({operator:"!=",search:this.value}):this.value,e.search()!==this.value&&e.search(t).draw()}))}));var i=new Date,c=`${i.getDate()}-${i.getMonth()+1}-${i.getFullYear()} ${i.getHours()}:${i.getMinutes()}:${i.getSeconds()}`;$(".printButtonPosition").length>0&&(new $.fn.dataTable.Buttons(s,{buttons:[{extend:"print",text:'<i class="fa fa-print"></i> <?= __("Print"); ?>',titleAttr:"Print",className:"btn btn-default btn-sm",messageTop:"<b>Printed On:</b> "+c,title:"",footer:!0,autoPrint:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){return void 0!==$("#DtExportTopMessage").html()?$("#DtExportTopMessage").html():"<h2 class='text-center'>"+document.title+"</h2><br/> <p class='text-center'> <strong>Printed On: </strong> "+c+" </p> <br/>"}},{extend:"copy",text:'<i class="fa fa-files-o"></i> <?= __("Copy"); ?>',titleAttr:"Copy",className:"btn btn-default btn-sm",footer:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}}},{extend:"excel",text:'<i class="fa fa-file-excel-o"></i> <?= __("Export to Excel"); ?>',titleAttr:"Excel",className:"btn btn-default btn-sm",footer:!0,exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){if(void 0!==$("#DtExportTopMessage").html())return $("#DtExportTopMessage").html()}},{extend:"pdf",text:'<i class="fa fa-file-pdf-o"></i> <?= __("Export to PDF"); ?>',titleAttr:"PDF",className:"btn btn-default btn-sm",exportOptions:{columns:":visible:not(.no-print):not(.dt-checkboxes-cell)",format:{footer:function(t,e,a){return $(a).prop("outerHTML").indexOf("no-print")>0?t.replace(t,""):t}}},messageTop:function(){if(void 0!==$("#DtExportTopMessage").html())return $("#DtExportTopMessage").html()}},{extend:"colvis",text:'<i class="fa fa-columns"></i> <?= __("Hide"); ?>',className:"btn btn-default btn-sm",collectionLayout:"fixed"}]}),s.buttons().container().appendTo(".printButtonPosition")),$("#dataTableWithAjaxExtend tbody").on("click",".has-child-row",(function(){var t=$(this).closest("tr"),e=s.row(t),a=$(this).attr("data-parent-product-id"),r=$("#productReportWarehouseSelection").select2("data")[0].id,o=$(this).text(),n=this;e.child.isShown()?(e.child.hide(),t.removeClass("shown")):($(n).html(`${o} <i style='margin-left: 5px;' class='fa fa-spinner fa-spin'></i>`),BMS.fn.get(`getChildProductData&pid=${a}&wid=${r}`,(function(a){0==a?BMS.fn.alertError("Sorry! no item found."):(e.child(function(t){var e=s.columns().visible(),a="";return t.forEach((t=>{a+='<tr class="childRow" style="display: none; background-color: #f2fcff;">',t.forEach(((t,r)=>{var o=s.columns().header()[r].className;a+=e[r]?`<td class='${o}'>${t}</td>`:""})),a+="</tr>"})),$(a).toArray()}(a)).show(),t.addClass("shown"),$("tr.childRow").fadeIn("slow")),$(n).html(`${o}`)})))}))},select2:function(t,e="",a=""){var r=$(t).attr("select2-ajax-url"),o=$(t).attr("select2-minimum-input-length"),n="true"===$(t).attr("select2-tag"),s="false"!==$(t).attr("closeOnSelect"),l="";l=void 0===$(t).attr("select2-create-new-url")?"<?php echo __('Nothing found'); ?>":`<span class="createNewSelect2Item" onClick="BMS.fn.createNewSelect2Item('#${$(t).attr("id")}')" style="cursor: pointer; display: block;"> <i class="fa fa-plus"></i> <?php echo __("Create new..."); ?></span>`,$(document).on("keyup",".select2-search__field",(function(t){"Enter"===t.key&&$(".createNewSelect2Item").click()}));var i=$(t).select2({placeholder:$(t).children("option:first").html()?$(t).children("option:first").html():"Select Options",allowClear:!0,closeOnSelect:s,tags:n,minimumInputLength:o,language:{noResults:function(){return l}},escapeMarkup:function(t){return t},ajax:{url:r,dataType:"json",delay:400,processResults:function(t){return{results:t}},cache:!0},templateSelection:function(t){return t.id?$("<div>").text(t.text).html():t.text},templateResult:function(t){if(!t.id)return t.text;if("object"==typeof t.text){var e=t.text,a="";return a+=` <div style="width: 98%;" class='row'>\n <div class='col-md-5'>${e[0]}</div>\n <div class='col-md-1'>Cost</div>\n <div class='col-md-1'>Price</div>\n <div class='col-md-2'>Stock</div>\n <div class='col-md-3 adjustFormGroupPaddingRight'>Brand</div>\n </div>\n `,a+=` <div style="width: 98%;" class='row'>\n <div class='col-md-5'>${e[1]}</div>\n <div class='col-md-1'>${e[2]}</div>\n <div class='col-md-1'>${e[3]}</div>\n <div class='col-md-2'>${e[4]}</div>\n <div class='col-md-3 adjustFormGroupPaddingRight'>${e[5]}</div>\n </div>\n `}return $("<div>").text(t.text).html()}});if(""!==a&&""===e)$.ajax({type:"get",url:r+"&q="+a}).then((function(t){if(void 0!==(t=JSON.parse(t)[0])){var e=new Option(t.text,t.id,!0,!0);i.append(e).trigger("change")}}));else if(""!==e&&i.find(":selected").val()!==e){var c=new Option(a,e,!0,!0);i.append(c).trigger("change")}},get:function(t,e){$.ajax({url:full_website_address+`/info/?module=data&page=${t}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,a){e(t)},error:function(){e("")}})}},BMS.fn=BMS.FUNCTIONS,BMS.MAIN={printPage:function(t,e,a=function(){}){e.preventDefault(),$(".dynamic-container > iframe").remove();var r=document.createElement("iframe");r.onload=function(){this.contentWindow.focus(),this.contentWindow.print(),a(!0)},r.style.position="fixed",r.style.right="0",r.style.bottom="0",r.style.width="0",r.style.height="0",r.style.border="0",r.src=t,$(".dynamic-container").append(r)},addTariffChargesRow:function(t){$(t).append(`<div class="row"><br/> \n <div class="col-md-7"> \n <select name="tariffChargesName[]" class="form-control select2Ajax tariffChargesName" select2-ajax-url="${full_website_address}/info/?module=select2&page=tariffCharges"> \n <option value="">Select Tariff/Charges</option> \n </select> \n </div> \n <div class="col-md-4"> \n <input type="number" name="tariffChargesAmount[]" class="form-control tariffChargesAmount" step="any"> \n </div> \n <div class="col-md-1"> \n <i style="cursor: pointer; padding-top: 9px;" class="fa fa-trash-o removeThisTariffCharges"></i> \n </div> \n </div>`)}},BMS.PRODUCT={isExists:function(t,e=".productID"){return $(e).filter((function(){return this.value===t})).length>0},validationCheck:function(t,e,a){if(this.isExists(t.pid))return alert(`The product (${t.pn}) is already in the list.`);if(void 0===t.pv)return a(t);var r="",o={},n=[],s={};$.each(t.pv,(function(t,e){Array.isArray(o[e.mk])?o[e.mk].includes(e.mv)||o[e.mk].push(e.mv):o[e.mk]=[e.mv],"DV"===e.t?n.push(e.mv):Array.isArray(s[e.id])?s[e.id].push(e.mv):s[e.id]=[e.mv]})),$.each(o,(function(t,e){r+=`<div id="variationSelection" class="form-group row text-left">\n <label class="col-sm-4">${t}:</label>\n <div class="col-sm-8">\n <select class="form-control">\n <option value="">Select ${t}...</option>`,$.each(e,(function(t,e){r+="<option "+(n.includes(e)?"selected":"")+` value="${e}">${e}</option>`})),r+=" </select>\n </div>\n </div>"})),Swal.fire({title:"<strong>Select Variation</strong>",html:"for "+t.pn+" <br/><br/>"+r,showCloseButton:!0,showCancelButton:!0,focusConfirm:!1,confirmButtonText:"Ok"}).then((t=>{if(t.isConfirmed){var a=$("#variationSelection select"),r=[];$.each(a,(function(){""!==this.value&&r.push(this.value)}));var o="";$.each(s,(function(t,e){if(r.every((t=>e.includes(t))))return o=t,!1})),""===o||0===r.length?Swal.fire("Sorry! no product found"):e.addProduct(o)}}))},parseProductList:function({category:t="",brand:e="",edition:a="",generic:r="",author:o=""},n){$.ajax({url:full_website_address+`/info/?module=data&page=productList&catId=${t}&brand=${e}&edition=${a}&generic=${r}&author=${o}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){n(t)}})},showProduct:function({container:t="#productListContainer",category:e="",brand:a="",edition:r="",generic:o="",author:n=""}=""){this.parseProductList({category:e,brand:a,edition:r,generic:o,author:n},(e=>{if(null!=e){var a="";e.forEach((t=>{var e=full_website_address;t.v&&t.v>0?e+="/images/?for=products&id="+t.id+"&q=YTozOntzOjI6Iml3IjtpOjIwMDtzOjI6ImloIjtpOjIyMDtzOjI6ImlxIjtpOjcwO30=&v="+t.v:e+="/assets/images/noimage.png",a+="<button type='button' value='"+t.id+"' title='"+t.name+"' data-toggle='tooltip' class='productButton btn-product btn-default'> <img src='"+e+"' style='width:60px; height:60px;' alt='"+t.name+"'> <span> "+t.name+" </span> </button> "})),$(t).html(a)}else $(t).html("<div class='alert alert-danger'>Sorry! No products found in this criteria.</div>")}))},getDetails:function(t,e){$.ajax({url:full_website_address+`/info/?module=data&page=productDetails&product_id=${t}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,a){e(t)}})},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?this.getDetails(a,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{if("1"!==t.hed){var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr>\n <input type="hidden" name="bgProductID[]" class="productID" value="${t.pid}">\n <td class="col-md-5">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="bgProductQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-2">${t.pu}</td>\n <td class="text-right col-md-2 gbProductPrice"><input onclick = "this.select()" type="text" name="bgProductSalePrice[]" value="${t.sp}" class="productSalePrice form-control text-center" step="any"></td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}else BMS.fn.alertError("Sorry! The product which have expiry date or batch number, can not be added in sub/bundle product.")})),$("#selectProduct").empty()})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select()})):alert("Please select a product")},getListByGeneric:function(t){BMS.fn.select2("#productGenericFilter",t,t)},productUnitCheck:function(t){this.getDetails({product_id:$(t).closest("tr").find(".productID").val(),unit:$(t).val()},(e=>{$(t).closest("tr").find(".productSalePrice").val(e[0].sp)}))}},BMS.POS={clearScreen:function(){$(".dynamic-container").slideUp(350,(function(){var t=new Date;$("#salesDate").val(t.toISOString().split("T")[0]),$("#tariffCharges .row").not("div:first").remove(),$(".tariffChargesName").val("").change();$(".paymentMethodBox").html('<div style="margin: 0;" class="row">\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Amount</label>\n <input type="number" onclick="this.select();" name="posSalePaymentAmount[]" class="form-control posSalePaymentAmount" step="any">\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Reference/Info</label>\n <input type="text" name="posSalePaymentReference[]" class="form-control">\n </div>\n <div style="display: none;" class="posSalePaymentBankAccount form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Bank Account</label>\n <select name="posSalePaymentBankAccount[]" class="form-control pull-left select2Ajax" \n select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=accountList" style="width: 100%;">\n <option value=""><?php echo __("Select Account"); ?>....</option>\n </select>\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Payment Method</label>\n <select name="posSalePaymentMethod[]" class="posSalePaymentMethod form-control">\n <option value="Cash"><?php echo __("Cash"); ?></option>\n <option value="Bank Transfer"><?php echo __("Bank Transfer"); ?></option>\n <option value="Cheque"><?php echo __("Cheque"); ?></option>\n <option value="Card"><?php echo __("Card"); ?></option>\n <option value="Others"><?php echo __("Others"); ?></option>\n </select>\n </div>\n </div>'),$("#orderDiscountValue, #shippingCharge, .posSalePaymentAmount, #adjustAmount, #salesNote").val(""),$("#shippingCharge").removeClass("shippingChargeEdited"),$(".posSalePaymentAmount").removeClass("disablePaymentAmountAutoChange"),$("#productTable > tbody").html(""),$("#editSalesId").remove(),$("#payment .modal-footer").html('\n <button type="button" class="btn btn-default pull-left" data-dismiss="modal"><?= __("Close"); ?></button>\n <button name="posAction" value="sale_is_confirmed" style="visibility: hidden;" type="submit"></button>\n <button name="posAction" value="sale_is_hold" type="submit" class="posSubmit btn btn-warning"><i class="fa fa-pause-circle"></i> <?= __("Hold"); ?></button>\n <button name="posAction" value="sale_is_confirmed" type="submit" class="posSubmit btn btn-success"><i class="fa fa-check-circle"></i> <?= __("Confirm"); ?></button>\n '),$("input:radio, input:checkbox").prop("checked",!1),BMS.fn.select2("#customers",1,"Walk-in Customer"),BMS.POS.grandTotal(),BMS.POS.disableEnableWCSelect()})).slideDown(500)},getProductDetails:function({product_id:t,warehouse_id:e,customer_id:a="",qnt:r="",batch:o="",packet:n=""},s){$.ajax({url:full_website_address+`/info/?module=data&page=productDetailsForPos&product_id=${t}&warehouse_id=${e}&cid=${a}&pqnt=${r}&batch=${o}&packet=${n}`,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){s(t)}})},disableEnableWCSelect:function(){$(".productQnt").length>0?$("#customers, #warehouse").prop("disabled",!0):$("#customers, #warehouse").prop("disabled",!1)},grandTotal:function(t=""){var e=0,a=0;$(".productQnt").each((function(){e+=Number($(this).val()),a+=1})),$(".totalItemAndQnt").html(a+" ("+e+")");var r=0;$(".subtotalCol").each((function(){r+=Number($(this).html())})),$(".totalAmount").html(r.toFixed(2));var o=$("#orderDiscountValue").val(),n=BMS.FUNCTIONS.calculateDiscount(r,o);$(".totalOrderDiscountAmount").html("(-) "+(r-n).toFixed(2));var s=0;if($("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(n,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),s+=Number(e)})),$(".totalTariffChargesAmount").html("(+) "+s.toFixed(2)),!0===$("#payment").hasClass("in")){if(!1===$("#shippingCharge").is(":focus")&&($("#totalPackets").is(":focus")||$("#packetShippingRate").is(":focus"))){var l=$("#totalPackets").val()*$("#packetShippingRate").val();$("#shippingCharge").val(l)}}else{var i=0;$(".productPacket").each((function(){i+=Number($(this).val())})),$(".displayTotalPackets").html(i.toFixed(2)),$("#totalPackets").val(Math.round(i));l=$("#totalPackets").val()*$("#packetShippingRate").val();$("#shippingCharge").val(l)}var c=(Number(s)+Number(n)).toFixed(2);$(".netTotalAmount").html(c),$("#finalizeSale > tbody > tr:nth-child(1) > td:nth-child(3)").html(c);var d=Number($("#shippingCharge").val()),u=Number(c)+d;"1"===config.posSaleAutoAdjustAmount&&$("#adjustAmount:not(.disableAdjustAmountAutoChange)").val(parseFloat(parseFloat(u).toFixed()-u).toFixed(2));var p=Number($("#adjustAmount").val());u=parseFloat(Number(c)+d+Number(p)).toFixed(2);if("1"===config.posSaleAutoMarkAsPaid){var m=sumInputs(".disablePaymentAmountAutoChange"),h=0;(u>0&&u>m||u<0&&u<m)&&(h=u-m),$(".posSalePaymentAmount:not(.disablePaymentAmountAutoChange)").first().val(parseFloat(h).toFixed(2))}var f=sumInputs(".posSalePaymentAmount"),v=u<f?f-u:0,g=u>f?u-f:0;$("#finalizeSale > tbody > tr:nth-child(4) > td:nth-child(2)").html(u),$("#finalizeSale > tbody > tr:nth-child(6) > td:nth-child(2)").html(v),$("#finalizeSale > tbody > tr:nth-child(7) > td:nth-child(2)").html(g),$("#quickPayableAmount").html(u),!0===$("#payment").hasClass("in")&&(u>0&&u<f||u<0&&u>f)&&(Swal.fire({title:"Paid amount can not be more then Grand total.",icon:"error"}),$(".posSalePaymentAmount").last().val(0))},editProductItemDetails:function(t,e){$("#productSaleDetails .modal-title").html(e),$("#productSaleDetails .rowId").val(t);var a=$(`#${t}`);$("#productSaleDetails #productSaleItemPrice").val(a.find(".netSalesPrice").val()),$("#productSaleDetails #productSaleItemDiscount").val(a.find(".productDiscount").val()),$("#productSaleDetails #productSaleItemPacket").val(a.find(".productPacket").val()),$("#productSaleDetails #productSaleItemDetails").val(a.find(".productItemDetails").val())},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?($("#selectProduct").val()>0&&$("#selectProduct").html("<option value=''>Search Product....</option>"),this.getProductDetails({product_id:a,warehouse_id:$("#warehouseId").val(),customer_id:$("#customersId").val()},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=0,r=t.iq?parseFloat(t.iq).toFixed(0):1;t.pq>0&&(e=(r/Number(t.pq)).toFixed(2));var o=t.pd?t.pd:"0",n=BMS.FUNCTIONS.calculateDiscount(t.sp,o),s="";s=Number(n)===Number(t.sp)?parseFloat(t.sp).toFixed(2):"<span>"+parseFloat(n).toFixed(2)+"</span><span><del><small>"+parseFloat(t.sp).toFixed(2)+"</small></del></span>";var l=Date.now()+t.pid,i=null===t.gn?"":`<small style="cursor: zoom-in;" onClick="BMS.PRODUCT.getListByGeneric('${t.gn}')"><i>${t.gn}</i></small>`,c=`<tr ${t.so?'style="background-color: pink;"':""} id=${l}> \n <td class="col-md-7">\n <span data-toggle="modal" data-target="#modalDefault" href="${full_website_address}/xhr/?module=reports&page=totalPurchasedQuantityOfThisCustomer&cid=${$("#customersId").val()}&pid=${a}"> <i class="fa fa-info-circle productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails('${l}', '${t.pn}')" data-target="#productSaleDetails">${t.pn}</a>\n ${i}\n </td> \n <td class="col-md-2 displayProductPrice text-right">${s}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="${r}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${t.pu}</td> \n <td class="col-md-3 subtotalCol text-right">${parseFloat(Number(n)*Number(r)).toFixed(2)}</td> \n <td style="width: 25px !important;"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t.pid}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productSO" value="${t.so}"> \n <input type="hidden" name="productDiscount[]" value="${o}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="">\n <input type="hidden" name="productHasExpiryDate[]" value="${t.hed}"> \n <input type="hidden" name="productPacket[]" value="${e}" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(c)}))})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),this.disableEnableWCSelect()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})}))):alert("Please select a product")},addReturnProduct:function(t,e,a,r,o,n,s,l,i,c){if(!BMS.PRODUCT.isExists(t)||confirm(`The product (${e}) is already in the list. Do you want to add it again?`)){var d=Date.now()+t,u=`<tr id=${d}> \n <td class="col-md-7">\n <span> <i class="fa fa-undo productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails(${d}, '${e}')" data-target="#productSaleDetails">${e}</a>\n ${null===a?"":`<small style="cursor: zoom-in;" onClick="BMS.PRODUCT.getListByGeneric('${a}')"><i>${a}</i></small>`}\n </td> \n <td class="col-md-2 displayProductPrice text-right">${l}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="-${i}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${o}</td> \n <td class="col-md-3 subtotalCol text-right">-${c}</td> \n <td style="width: 25px; !important"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${l}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${l}"> \n <input type="hidden" name="productDiscount[]" value="${s}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="${r}">\n <input type="hidden" name="productHasExpiryDate[]" value="${n}"> \n <input type="hidden" name="productPacket[]" value="0" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(u),this.grandTotal()}},productQntCheck:function(t,e){var a=$(t).closest("tr").find(".netSalesPrice").val(),r=$(t).val(),o=$(t).closest("tr").find(".productDiscount").val(),n=$(t).closest("tr").find("td.subtotalCol"),s=$(t).closest("tr").find(".productPacket"),l=t;0==r&&(Swal.fire({title:"Error!",text:"Product qunatity can not be zero (0)",icon:"error"}),$(t).val(1),r=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#warehouseId").val(),qnt:r,unit:$(t).closest("tr").find(".productItemUnit").val()},(e=>{void 0!==e.error&&!0===e.error&&($(l).val(e.stq),r=e.stq,Swal.fire({title:"Error!",text:e.msg,icon:"error"})),(e=e[0]?e[0]:e).so?$(t).closest("tr").css("background-color","pink"):$(t).closest("tr").css("background-color","white"),$(n).html((BMS.FUNCTIONS.calculateDiscount(a,o)*r).toFixed(2));var i=0;Number(e.pq)>0&&(i=(r/Number(e.pq)).toFixed(2)),s.val(i),this.grandTotal()}))},productPacketCheck:function(){var t=$(selector).closest("tr").find(".netSalesPrice").val(),e=$(selector).val(),a=$(selector).closest("tr").find(".productDiscount").val(),r=$(selector).closest("tr").find("td.subtotalCol"),o=$(selector).closest("tr").find(".productQnt"),n=$(selector).closest("tr").find(".productPacket");this.getProductDetails({product_id:$(selector).closest("tr").find(".productID").val(),warehouse_id:$("#warehouseId").val(),packet:e},(s=>{if(void 0!==s.error&&!0===s.error){$(o).val(s.having_item_quantity),$(r).html((BMS.FUNCTIONS.calculateDiscount(t,a)*s.having_item_quantity).toFixed(2));var l=0;Number(s.product_packet_quantity)>0&&(l=(s.having_item_quantity/Number(s.product_packet_quantity)).toFixed(2)),n.val(l),Swal.fire({title:"Error!",text:s.msg,icon:"error"})}else{var i=Math.round(Number(s.product_packet_quantity)*e);i>0&&($(o).val(i),$(r).html((BMS.FUNCTIONS.calculateDiscount(t,a)*i).toFixed(2)))}this.grandTotal()}))},productDiscountCheck:function(t){var e=$("#productSaleItemPrice").val(),a=$("#productSaleItemDiscount").val();"Enter"===t.key&&a.indexOf("%")>1&&a.replace("%","")>=100?(Swal.fire({title:"Error!",text:"Discount Must be below of 100%",icon:"error"}),$("#productSaleItemDiscount").val(""),$("#productSaleItemDiscount").select(),t.preventDefault()):"Enter"===t.key&&Number(a)>=Number(e)&&a.indexOf("%")<1&&($("#productSaleItemDiscount").val(""),$("#productSaleItemDiscount").select(),"Enter"===t.key&&t.preventDefault(),Swal.fire({title:"Error!",text:"Discount Must be below of product sale price",icon:"error"}),t.preventDefault())},orderDiscountCheck:function(t,e){var a=$(".totalAmount").text(),r=$(t).val();r.indexOf("%")>1&&r.replace("%","")>=100?(Swal.fire({title:"Error!",text:"Discount Must be below of 100%",icon:"error"}),$(t).val(0),e.preventDefault()):Number(a)<0&&Number(r)>0?(Swal.fire({title:"Error!",text:"Discount must be a negative amount in case of negative total amount.",icon:"error"}),$(t).val(-Number(r)),e.preventDefault()):Number(a)<0&&(Number(r)>0||Math.abs(Number(r))>=Math.abs(Number(a)))||Number(a)>0&&Number(r)>=Number(a)&&r.indexOf("%")<1?(Swal.fire({title:"Error!",text:"Discount Must be below of total amount.",icon:"error"}),$(t).val(0),e.preventDefault()):!0!==this.isGivenDiscountPermitted(t)&&(Swal.fire({title:"Error!",text:`You do not have permission to give ${r} discount.`,icon:"error"}),$(t).val(0),e.preventDefault()),this.grandTotal()},isGivenDiscountPermitted:function(t){var e=$(".totalAmount").text(),a=$(t).val();if(""!=get_options("maxDiscount")){var r=e-BMS.FUNCTIONS.calculateDiscount(e,get_options("maxDiscount")),o=e-BMS.FUNCTIONS.calculateDiscount(e,a);return Math.abs(r)>=Math.abs(o)}return!0}},BMS.PURCHASE={getProductDetails:BMS.PRODUCT.getDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#purchaseDiscountValue").val());$(".totalPurchaseDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#purchaseNetTotal").val(o);var n=Number(o)+Number($("#purchaseShipping").val());$("#purchaseGrandTotal").val(n);var s=Number($("#purchasePaidAmount").val()),l=n<=s?0:n-s,i=n>=s?0:s-n;$("#purchaseChangeAmount").val(i),$("#purchaseDueAmount").val(l)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return isNaN(a)?(alert("Product quantity must be a valid number."),void $(t).closest("tr").find(".productQnt").val(1)):a<1&&"Ordered"!==$("#purchaseStatus").val()?(alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t;""!==a?this.getProductDetails(a,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&"Ordered"!==$("#purchaseStatus").val()&&(e=`<select name="productBatch[]" id="productBatchFor${t.pid}" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="stock_col" style="width: 155px;"><span>${t.alertq}</span> <span>${t.soldq}</span> <span>${t.stockq}</span></td>\n <td><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td>${t.pu}</td>\n <td class="text-right"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" class="productMainPurchasePrice" value="${t.pp}" step="any">\n <td class="text-right"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="0" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${t.pp}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),!1===e&&$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),$("#selectProduct").empty()})):alert("Please select a product")},productUnitCheck:function(t){var e=$(t).closest("tr").find(".productID").val(),a=this;$.ajax({url:full_website_address+"/info/?module=data&page=productUnitDetails&product_id="+e+"&unit="+$(t).val(),contentType:"application/json; charset=utf-8",dataType:"json",success:function(e,r){"success"==r&&($(t).closest("tr").find(".productPurchasePrice").val(e.pp),$(t).closest("tr").find(".productMainPurchasePrice").val(e.pp),a.calculateEachProduct(t),a.grandTotal())}})}},BMS.ORDER=Object.assign({},BMS.POS),BMS.ORDER.addProduct=function(t=""){var e=""===t?$("#selectProduct").val():t;""!==e?($("#selectProduct").val()>0&&$("#selectProduct").html("<option value=''>Search Product....</option>"),BMS.PRODUCT.getDetails(e,(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var a=0,r=t.iq?parseFloat(t.iq).toFixed(0):1;t.pq>0&&(a=(r/Number(t.pq)).toFixed(2));var o=t.pd?t.pd:"0",n=BMS.FUNCTIONS.calculateDiscount(t.sp,o),s="";s=Number(n)===Number(t.sp)?parseFloat(t.sp).toFixed(2):"<span>"+n+"</span><span><del><small>"+parseFloat(t.sp).toFixed(2)+"</small></del></span>";var l=Date.now()+t.pid,i=`<tr ${t.so?'style="background-color: pink;"':""} id=${l}> \n <td class="col-md-7">\n <span data-toggle="modal" data-target="#modalDefault" href="${full_website_address}/xhr/?module=reports&page=totalPurchasedQuantityOfThisCustomer&cid=${$("#customersId").val()}&pid=${e}"> <i class="fa fa-info-circle productDescription"></i> </span> \n <a href="#" data-toggle="modal" onclick="BMS.POS.editProductItemDetails('${l}', '${t.pn}')" data-target="#productSaleDetails">${t.pn}</a>\n </td> \n <td class="col-md-2 displayProductPrice text-right">${s}</td> \n <td class="col-md-2"><input onclick = "this.select()" type="text" name="productQnt[]" value="${r}" class="productQnt form-control text-center" autoComplete="off"></td>\n <td class="col-md-2">${t.pu}</td> \n <td class="col-md-3 subtotalCol text-right">${parseFloat(Number(n)*Number(r)).toFixed(2)}</td> \n <td style="width: 25px !important;"> \n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i> \n </td> \n <input type="hidden" name="productID[]" class="productID" value="${t.pid}"> \n <input type="hidden" class="netSalesPrice" name="productSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productMainSalePirce" name="productMainSalePirce[]" value="${t.sp}"> \n <input type="hidden" class="productSO" value="${t.so}"> \n <input type="hidden" name="productDiscount[]" value="${o}" class="productDiscount" autoComplete="off"> \n <input type="hidden" name="productBatch[]" value="">\n <input type="hidden" name="productHasExpiryDate[]" value="${t.hed}"> \n <input type="hidden" name="productPacket[]" value="${a}" class="productPacket"> \n <input type="hidden" name="productItemDetails[]" class="productItemDetails" value=""> \n </tr>`;$("#productTable > tbody").append(i)}))})),$("#productTable > tbody tr:last").find(".productQnt").select(),this.grandTotal(),this.disableEnableWCSelect()}))):alert("Please select a product")},BMS.ORDER.productQntCheck=function(t,e){var a=$(t).closest("tr").find(".netSalesPrice").val(),r=$(t).val(),o=$(t).closest("tr").find(".productDiscount").val(),n=$(t).closest("tr").find("td.subtotalCol");0==r&&(Swal.fire({title:"Error!",text:"Product qunatity can not be zero (0)",icon:"error"}),$(t).val(1),r=1),$(n).html((BMS.FUNCTIONS.calculateDiscount(a,o)*r).toFixed(2)),this.grandTotal()},BMS.STOCK_TRANSFER={getProductDetails:BMS.POS.getProductDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2))},disableEnableWarehouseSelect:function(){$(".productQnt").length>0?$("#stockTransferFromWarehouse, #stockTransferToWarehouse").prop("disabled",!0):$("#stockTransferFromWarehouse, #stockTransferToWarehouse").prop("disabled",!1)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return a<1?(alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t="",e=!1){var a=""===t?$("#selectProduct").val():t,r=$("#stockTransferFromWarehouseId").val();""!==r?""!==a?this.getProductDetails({product_id:a,warehouse_id:r,qnt:1},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(e=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td class="col-md-1"> ${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" value="${t.pp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${parseFloat(t.pp*a).toFixed(2)}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),this.grandTotal(),this.disableEnableWarehouseSelect(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")},productUnitCheck:function(t){var e=t;this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#stockTransferFromWarehouseId").val(),qnt:$(t).closest("tr").find(".productQnt").val(),unit:$(t).val()},(t=>{void 0!==t.error&&!0===t.error&&(console.log(t.stq),$(e).closest("tr").find(".productQnt").val(t.stq),Swal.fire({title:"Error!",text:t.msg,icon:"error"})),$(e).closest("tr").find(".productPurchasePrice").val(parseFloat(t.pp).toFixed(2)),this.calculateEachProduct(e),this.grandTotal()}))},productQntCheck:function(t){var e=$(t).val(),a=$(t);isNaN(e)&&(alert("Product quantity must be a valid number."),$(t).val(1),e=1),e<1&&(Swal.fire({title:"Error!",text:"Product qunatity must be at least one",icon:"error"}),$(t).val(1),e=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#stockTransferFromWarehouseId").val(),qnt:e,unit:$(t).closest("tr").find(".productItemUnit").val()},(t=>{void 0!==t.error&&!0===t.error&&($(a).val(t.stq),Swal.fire({title:"Error!",text:t.msg,icon:"error"})),this.calculateEachProduct(a),this.grandTotal()}))}},BMS.STOCK_ENTRY={getProductDetails:BMS.PRODUCT.getDetails,grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalPurchasePrice").html(e.toFixed(2))},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productPurchasePrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productPurchaseDiscount").val(),o=$(t).closest("tr").find(".subTotal");return a<1&&"Production"===$("#stockEntryType").val()?(alert("Negative quantity is not valid for Production of stock."),void $(t).closest("tr").find(".productQnt").val(1)):(""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productPurchasePrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of 100%")):Number(r)>Number(e)&&r.indexOf("%")<1?($(t).closest("tr").find(".productPurchaseDiscount").val(0),void alert("Discount Must be below of product purchase price")):void $(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2)))},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t;""!==$("#stockTransferFromWarehouseId").val()?""!==e?this.getProductDetails(e,(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(e=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-create-new-url="<?php echo full_website_address(); ?>/xhr/?tooltip=true&module=stock-management&page=newBatchForSelectedProduct&pid=${t.pid}" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var a=t.iq?parseFloat(t.iq).toFixed(0):1,r=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4">${t.pn}</td>\n <td class="col-md-2">${e}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="${a}" class="productQnt form-control text-center"></td>\n <td class="col-md-1"> ${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchasePrice[]" value="${t.pp}" class="productPurchasePrice form-control text-center" step="any"></td>\n <input type="hidden" name="productMainPurchasePrice[]" value="${t.pp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productPurchaseDiscount[]" value="" placeholder="10% or 10" class="productPurchaseDiscount form-control text-center"></td>\n <td class="text-right subTotal">${parseFloat(t.pp*a).toFixed(2)}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(r)}))})),this.grandTotal(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")}},BMS.RETURN={getProductReturnDetails:function({product_id:t,customer_id:e},a){$.ajax({url:full_website_address+"/info/?module=data&page=productDetailsForReturn&product_id="+t+"&customer_id="+e,contentType:"application/json; charset=utf-8",dataType:"json",success:function(t,e){a(t)}})},grandTotal:function(){var t=0;$(".productQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".productQnt").length+"("+t+")");var e=0;$(".subTotal").each((function(){e+=Number($(this).html())})),$(".totalReturnPrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#returnDiscountValue").val());$(".totalReturnDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#returnNetTotal").val(o);var n=$("#returnShipping").val(),s=Number(o)+Number(n)-Number($("#returnSurcharge").val());$("#returnGrandTotal").val(s);var l=Number($("#returnPaidAmount").val()),i=s<=l?0:s-l,c=s>=l?0:l-s;$("#returnChangeAmount").val(c),$("#returnDueAmount").val(i)},calculateEachProduct:function(t){var e=$(t).closest("tr").find(".productReturnPrice").val(),a=$(t).closest("tr").find(".productQnt").val(),r=$(t).closest("tr").find(".productReturnDiscount").val(),o=$(t).closest("tr").find(".subTotal");if(a<1)return alert("Product quantity must be minimum of 1."),void $(t).closest("tr").find(".productQnt").val(1);""!==e&&null!==e&&"null"!==e||(e=0,$(t).closest("tr").find(".productReturnPrice").val(0)),r.indexOf("%")>1&&r.replace("%","")>=100?alert("Discount Must be below of 100%"):Number(r)>Number(e)&&r.indexOf("%")<1?alert("Discount Must be below of product return price"):$(o).html((BMS.FUNCTIONS.calculateDiscount(e,r)*a).toFixed(2))},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t,a=$("#returnCustomer").val();""!==a?""!==e?this.getProductReturnDetails({product_id:e,customer_id:a},(t=>{t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.pd?t.pd:"0",a=parseFloat(BMS.FUNCTIONS.calculateDiscount(t.sp,e)).toFixed(2),r="<input type='hidden' name='productBatch[]' value=''>";void 0!==t.hed&&"1"===t.hed&&(r=`<select name="productBatch[]" id="productBatch" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=batchList&pid=${t.pid}" required>\n <option value=""><?= __("Select Batch"); ?>....</option>\n </select>`);var o=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-4 productDetails">${t.pn}<br/>(<i>Purchased: ${t.prq} Returned: ${t.rtq}</i>)</td>\n <td class="col-md-2">${r}</td>\n <td class="col-md-1"><input onclick = "this.select()" type="text" name="productQnt[]" value="1" class="productQnt form-control text-center"></td>\n <td class="col-md-1">${t.pu}</td>\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productReturnPrice[]" value="${t.sp}" class="productReturnPrice form-control text-center" step="any"></td>\n <input type="hidden" name="productReturnMainPrice[]" value="${t.sp}" step="any">\n <td class="text-right col-md-1"><input onclick = "this.select()" type="text" name="productReturnDiscount[]" value="${e}" placeholder="10% or 10" class="productReturnDiscount form-control text-center"></td>\n <td class="text-right subTotal">${a}</td>\n <td style="width: 30px; !important">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(o)}))})),this.grandTotal(),$("#selectProduct").empty()})):alert("Please select a product"):alert("Please select the customer")},productUnitCheck:function(t){var e=t;this.getProductReturnDetails({product_id:$(t).closest("tr").find(".productID").val(),customer_id:$("#returnCustomer").val(),unit:$(t).val()},(t=>{var a=t[0];$(e).closest("tr").find(".productReturnPrice").val(parseFloat(a.sp).toFixed(2));var r=a.pn+"<br/>(<i>Purchased: "+parseFloat(a.prq).toFixed(2)+", Returned: "+parseFloat(a.rtq).toFixed(2)+")";$(e).closest("tr").find(".productDetails").html(r),this.calculateEachProduct(e),this.grandTotal()}))}},BMS.WASTAGE_SALE={grandTotal:function(){var t=0;$(".wastageSaleItemQnt").each((function(){t+=Number($(this).val())})),$("#totalItems").html($(".wastageSaleItemQnt").length+"("+t+")");var e=0;$(".wastageSaleItemSubtotal").each((function(){e+=Number($(this).text())})),$(".totalWastageSalePrice").html(e.toFixed(2));var a=BMS.FUNCTIONS.calculateDiscount(e,$("#wastageSaleDiscountValue").val());$(".totalWastageSaleDiscount").html("(-) "+(e-a).toFixed(2));var r=0;$("#tariffCharges > .row").each((function(){var t=$(this).closest(".row").find(".tariffChargesName").val().split(": ")[1],e=BMS.FUNCTIONS.calculateTarifCharges(a,t);$(this).closest(".row").find(".tariffChargesAmount").val(e),r+=Number(e)})),$(".totalTariffCharges").html("(+) "+r.toFixed(2));var o=(Number(r)+Number(a)).toFixed(2);$(".netTotal").html(o),$("#wastageSaleNetTotal").val(o);var n=$("#wastageSalePaidAmount").val(),s=n<o?o-n:0;$("#wastageSaleDue").val(s.toFixed(2))},addWastageSaleItem:function(){$("#productTable > tbody").append('<tr> <td class="col-md-5"> <input type="text" name="wastageSaleItem[]" placeholder="Enter Item name and details" class="wastageSaleItem form-control" required> </td> <td class="col-md-2"> <input type="number" step="any" name="wastageSaleItemQnt[]" class="wastageSaleItemQnt form-control" required> </td> <td class="col-md-2"> <input type="number" step="any" name="wastageSaleItemPrice[]" class="wastageSaleItemPrice form-control" required> </td> <td class="text-right wastageSaleItemSubtotal">0.00</td> <td style="width: 30px; !important"> <i style="cursor: pointer;" class="fa fa-trash-o removeThisItem"></i> </td> </tr>'),$(".wastageSaleItem").focus(),this.grandTotal()}},BMS.SPECIMEN_COPY={getProductDetails:BMS.POS.getProductDetails,disableEnableWarehouseSelect:function(){$(".productQnt").length>0?$("#scTransferWarehouse").prop("disabled",!0):$("#scTransferWarehouse").prop("disabled",!1)},addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t,a=$("#scTransferWarehouse").val();""!==a?""!==e?this.getProductDetails({product_id:e,warehouse_id:a},(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr> <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-6">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="productQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-3">${t.pu}</td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}))})),this.disableEnableWarehouseSelect(),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product"):alert("Please select an warehouse to add product")},productUnitCheck:function(t){this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#scTransferWarehouse").val(),qnt:$(t).closest("tr").find(".productQnt").val(),unit:$(t).val()},(e=>{void 0!==e.error&&!0===e.error&&($(t).closest("tr").find(".productQnt").val(e.stq),Swal.fire({title:"Error!",text:e.msg,icon:"error"}))}))},productQntCheck:function(t){var e=$(t).val();isNaN(e)&&(alert("Product quantity must be a valid number."),$(t).val(1),e=1),e<1&&(Swal.fire({title:"Error!",text:"Product qunatity must be at least one",icon:"error"}),$(t).val(1),e=1),this.getProductDetails({product_id:$(t).closest("tr").find(".productID").val(),warehouse_id:$("#scTransferWarehouse").val(),qnt:e,unit:$(t).closest("tr").find(".productItemUnit").val()},(e=>{void 0!==e.error&&!0===e.error&&($(t).val(e.stq),Swal.fire({title:"Error!",text:e.msg,icon:"error"}))}))}},BMS.SC_DISTRIBUTION={getProductDetails:BMS.PRODUCT.getDetails,addProduct:function(t=""){var e=""===t?$("#selectProduct").val():t;""!==e?this.getProductDetails(e,(t=>{void 0===t.error||!0!==t.error?(t.forEach((t=>{BMS.PRODUCT.validationCheck(t,this,(t=>{var e=t.iq?parseFloat(t.iq).toFixed(0):1,a=`<tr>\n <input type="hidden" name="productID[]" class="productID" value="${t.pid}">\n <td class="col-md-6">${t.pn}</td>\n <td class="col-md-3"><input onclick = "this.select()" type="text" name="productQnt[]" value="${e}" class="productQnt form-control text-center"></td>\n <td class="col-md-3">${t.pu}</td>\n <td style="width: 28px !important;">\n <i style="cursor: pointer;" class="fa fa-trash-o removeThisProduct"></i>\n </td>\n </tr>`;$("#productTable > tbody").append(a)}))})),$("#selectProduct").empty()):Swal.fire({title:"Error!",text:t.msg,icon:"error"})})):alert("Please select a product")}},BMS.CHAT={showChatBox:function(t,e){""!==t&&t.preventDefault(),$.ajax({url:full_website_address+"/info/?module=chat&page=getChatUserData",type:"post",data:{userId:e},success:function(t,a){t=JSON.parse(t);console.log(t);var r="";""!==t.latest_msg&&t.latest_msg.forEach((t=>{t.from_user!=e?r+=`<div class="direct-chat-msg">\n <div class="direct-chat-info clearfix">\n <span class="direct-chat-name pull-left">${t.from_username}</span>\n <span class="direct-chat-timestamp pull-right">${t.datetime}</span>\n </div>\n <img class="direct-chat-img" src="${full_website_address}/images/?for=employees&id=${t.from_user}">\n <div class="direct-chat-text">\n ${t.msg_text}\n </div>\n </div>`:r+=`<div class="direct-chat-msg right">\n <div class="direct-chat-info clearfix">\n <span class="direct-chat-name pull-right">${t.from_username}</span>\n <span class="direct-chat-timestamp pull-left">${t.datetime}</span>\n </div>\n <img class="direct-chat-img" src="${full_website_address}/images/?for=employees&id=${t.from_user}">\n <div class="direct-chat-text">\n ${t.msg_text}\n </div>\n </div>`}));var o=`<div class="chatBoxItem chatBoxForUser${e}">\n <input type="hidden" value=${e} class="userId">\n <div class="header">\n <img width='40px' height='40px' src='${full_website_address}/images/?for=employees&id=${e}' class='img-circle' />\n <div class="card" >\n <p class="name">${t.name}</p>\n <p>${t.position}</p>\n </div>\n <div class="action">\n <span class="close-chat">\n <i class="fa fa-close"></i>\n </span>\n </div>\n </div>\n <div class="direct-chat direct-chat-warning">\n \n <div class="direct-chat-messages">\n ${r}\n </div>\n </div>\n <div class="composer">\n <label for="chatAttachment${e}">\n <span title="Attach file" class="attachment">\n <i class="fa fa-plus"></i>\n </span>\n </label>\n <input style="display: none;" type="file" class="chat-attachment" id="chatAttachment${e}">\n <input type="text" placeholder="Type message and press enter to send ..." class="form-control message-composer">\n </div>\n </div>`;$(".chatBox").prepend(o).ready((function(){var t=$(`.chatBoxForUser${e}`).find(".direct-chat-messages"),a=$(t).get(0).scrollHeight;$(t).animate({scrollTop:a},0),$(t).closest(".chatBox").find(".message-composer").focus()}))}})},send:function(t,e){wss.send(JSON.stringify({type:"message",toUser:e,msg:t}))}};
\ No newline at end of file

programming_language: JavaScript
filename: events.js
change_type: ModificationType.MODIFY
diff: @@ -1844,7 +1844,7 @@ $(document).on('dblclick', 'iledit', function (event) {
                         // Display changed items
                         if (type === 'select2' || type === 'select') {
 
-                            $thistd.html(`<iledit data-val='` + $(that).val() + `'>` + $("option:selected", that).text() + `</iledit>`);
+                            $thistd.html(`<iledit data-val='` + $(that).val() + `'>` + $("option:selected", that).html() + `</iledit>`);
 
                         } else {
 
@@ -1863,7 +1863,9 @@ $(document).on('dblclick', 'iledit', function (event) {
             // Display data items if not changed
             if (type === 'select2' || type === 'select') {
 
-                $thistd.html(`<iledit data-val='` + $(that).val() + `'>` + $("option:selected", that).text() + `</iledit>`);
+                console.log( $("option:selected", that).html() );
+
+                $thistd.html(`<iledit data-val='` + $(that).val() + `'>` + $("option:selected", that).html() + `</iledit>`);
 
             } else {
 

programming_language: JavaScript
filename: events.min.js
change_type: ModificationType.MODIFY
diff: @@ -1 +1 @@
-$(document).on("change","#productCategoryFilter, #productBrandFilter, #productEditionFilter, #productGenericFilter, #productAuthorFilter",(function(){BMS.PRODUCT.showProduct({category:$("#productCategoryFilter").val(),brand:$("#productBrandFilter").val(),edition:$("#productEditionFilter").val(),generic:$("#productGenericFilter").val(),author:$("#productAuthorFilter").val()})})),$(document).on("change","#customers",(function(){var e=$("#customers").val();$("#customersId").val(e),BMS.fn.get(`getCustomerData&cid=${e}`,(function(e){$("#orderDiscountValue").val(e.discount),$("#packetShippingRate").val(e.shipping_rate)}))})),$(document).on("change","#warehouse",(function(){var e=$("#warehouse").val();$("#warehouseId").val(e),$("#selectPosProduct").attr("select2-ajax-url",`${full_website_address}/info/?module=select2&page=productListForPos&wid=${e}`),BMS.fn.select2("#selectPosProduct")})),$(document).on("change","#stockTransferFromWarehouse, #stockTransferToWarehouse",(function(){var e=$("#stockTransferFromWarehouse").val(),t=$("#stockTransferToWarehouse").val();$("#stockTransferFromWarehouseId").val(e),$("#stockTransferToWarehouseId").val(t)})),$(document).on("change","#scTransferWarehouse",(function(){var e=$("#scTransferWarehouse").val();$("#scTransferWarehouseId").val(e)})),$(document).on("click","#addTariffChargesRow",(function(){BMS.MAIN.addTariffChargesRow("#tariffCharges")})),$(document).on("click",".productButton",(function(){isPosPage?BMS.POS.addProduct(this.value):isPurchasePage?BMS.PURCHASE.addProduct(this.value):isTransferStockPage?BMS.STOCK_TRANSFER.addProduct(this.value):isProductReturnPage?BMS.RETURN.addProduct(this.value):isSpecimenCopyPage?BMS.SPECIMEN_COPY.addProduct(this.value):isScDistributionPage?BMS.SC_DISTRIBUTION.addProduct(this.value):isAddProductPage?BMS.PRODUCT.addProduct(this.value):isStockEntryPage?BMS.STOCK_ENTRY.addProduct(this.value):isSaleOrderPage&&BMS.ORDER.addProduct(this.value)})),$(document).on("change","#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct",(function(){isPosPage?BMS.POS.addProduct(this.value):isPurchasePage?BMS.PURCHASE.addProduct(this.value):isTransferStockPage?BMS.STOCK_TRANSFER.addProduct(this.value):isProductReturnPage?BMS.RETURN.addProduct(this.value):isSpecimenCopyPage?BMS.SPECIMEN_COPY.addProduct(this.value):isScDistributionPage?BMS.SC_DISTRIBUTION.addProduct(this.value):isAddProductPage?BMS.PRODUCT.addProduct(this.value):isStockEntryPage?BMS.STOCK_ENTRY.addProduct(this.value):isSaleOrderPage&&BMS.ORDER.addProduct(this.value),$(this).html("<option value=''>Search Product....</option>")})),$(document).on("click","#addWastageSaleRow",(function(){BMS.WASTAGE_SALE.addWastageSaleItem()})),$(document).on("click",".removeThisProduct, .removeThisItem",(function(){$(this).closest("tr").css("background-color","red").hide("fast",(function(){$(this).closest("tr").remove(),isPosPage?(BMS.POS.grandTotal(),BMS.POS.disableEnableWCSelect()):isPurchasePage?BMS.PURCHASE.grandTotal():isTransferStockPage?(BMS.STOCK_TRANSFER.grandTotal(),BMS.STOCK_TRANSFER.disableEnableWarehouseSelect()):isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSpecimenCopyPage?BMS.SPECIMEN_COPY.disableEnableWarehouseSelect():isStockEntryPage?BMS.STOCK_ENTRY.grandTotal():isSaleOrderPage&&(BMS.ORDER.grandTotal(),BMS.POS.disableEnableWCSelect())}))})),$(document).on("click",".removeThisTariffCharges",(function(){$(this).closest(".row").css("background-color","whitesmoke").hide("fast",(function(){$(this).closest(".row").remove(),isPosPage?BMS.POS.grandTotal():isPurchasePage?BMS.PURCHASE.grandTotal():isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSaleOrderPage&&BMS.ORDER.grandTotal()}))})),$(document).on("change",".tariffChargesName",(function(){isPosPage?BMS.POS.grandTotal():isPurchasePage?BMS.PURCHASE.grandTotal():isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSaleOrderPage&&BMS.ORDER.grandTotal()})),$(document).on("keyup blur",".productQnt",(function(){isPosPage?BMS.POS.productQntCheck(this):isPurchasePage?(BMS.PURCHASE.calculateEachProduct(this),BMS.PURCHASE.grandTotal()):isTransferStockPage?BMS.STOCK_TRANSFER.productQntCheck(this):isProductReturnPage?(BMS.RETURN.grandTotal(),BMS.RETURN.calculateEachProduct(this)):isSpecimenCopyPage?BMS.SPECIMEN_COPY.productQntCheck(this):isStockEntryPage?(BMS.STOCK_ENTRY.calculateEachProduct(this),BMS.STOCK_ENTRY.grandTotal()):isSaleOrderPage&&BMS.ORDER.productQntCheck(this)})),$(document).on("keydown",".productQnt",(function(e){"Enter"===e.key&&($("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").hasClass("select2-hidden-accessible")||BMS.fn.select2("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct"),$("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").select2("open"))})),$(document).on("keydown","#purchaseDiscountValue",(function(e){"Enter"===e.key&&(e.preventDefault(),$("#purchaseDiscount").modal("hide"),$("#finalizePurchase").modal("show"))})),$(document).on("keydown","#shippingCharge",(function(e){"Enter"===e.key&&(e.preventDefault(),$("#adjustAmount").select())})),$(document).on("keydown","#adjustAmount",(function(e){$(this).addClass("disableAdjustAmountAutoChange"),"Enter"===e.key&&(e.preventDefault(),$(".posSalePaymentAmount").first().select(),$(".posSalePaymentAmount").first().addClass("disablePaymentAmountAutoChange"))})),$(document).on("keydown focus",".posSalePaymentAmount",(function(e){var t=$(this).closest(".row").next(".row").find("input.posSalePaymentAmount");$(this).addClass("disablePaymentAmountAutoChange"),1===t.length&&"Enter"===e.key&&(e.preventDefault(),t.addClass("disablePaymentAmountAutoChange"),t.select())})),$(document).on("keydown",".select2-search__field",(function(e){isPosPage&&"select2-selectPosProduct-results"===$(this).attr("aria-controls")&&""===this.value&&$(".productQnt").length>0&&"Enter"===e.key&&($("#selectPosProduct").select2("close"),$("#orderDiscount").modal("show")),isPurchasePage&&"select2-selectProduct-results"===$(this).attr("aria-controls")&&""===this.value&&$(".productQnt").length>0&&"Enter"===e.key&&($("#selectProduct").select2("close"),$("#purchaseDiscount").modal("show"))})),$(document).on("hide.bs.modal","#orderDiscount",(function(e){var t=$("#orderDiscountValue"),a=$(t).val();BMS.POS.isGivenDiscountPermitted(t)?($("#payment").modal("show"),BMS.POS.grandTotal()):(Swal.fire({title:"Error!",text:`You do not have permission to give ${a} discount.`,icon:"error"}),$(t).val(0),e.preventDefault())})),$(document).on("blur keyup",".wastageSaleItemQnt, .wastageSaleItemPrice",(function(){var e=$(this).closest("tr").find(".wastageSaleItemQnt").val(),t=$(this).closest("tr").find(".wastageSaleItemPrice").val();$(this).closest("tr").find(".wastageSaleItemSubtotal").html(parseFloat(e*t).toFixed(2)),BMS.WASTAGE_SALE.grandTotal()})),$(document).on("blur keyup","#wastageSaleDiscount, #wastageSalePaidAmount",(function(){BMS.WASTAGE_SALE.grandTotal()})),$(document).on("blur keyup",".productPurchaseDiscount, .productPurchasePrice",(function(){isPurchasePage?(BMS.PURCHASE.calculateEachProduct(this),BMS.PURCHASE.grandTotal()):isTransferStockPage&&(BMS.STOCK_TRANSFER.calculateEachProduct($(this)),BMS.STOCK_TRANSFER.grandTotal())})),$(document).on("blur keyup",".productReturnDiscount, .productReturnPrice",(function(){BMS.RETURN.calculateEachProduct(this),BMS.RETURN.grandTotal()})),$(document).on("keyup blur","#purchaseDiscount, #purchasePaidAmount, #purchaseShipping",(function(){BMS.PURCHASE.grandTotal()})),$(document).on("keyup blur","#returnDiscount, #returnShipping, #returnSurcharge, #returnPaidAmount",(function(){BMS.RETURN.grandTotal()})),$(document).on("keyup blur","#productSaleItemPacket",(function(){})),$(document).on("blur keydown","#productSaleItemDiscount",(function(e){BMS.POS.productDiscountCheck(e)})),$(document).on("keydown","#orderDiscountValue",(function(e){13===(e.keyCode||e.which)&&BMS.POS.orderDiscountCheck(this,e)})),$(document).on("keyup",".posSalePaymentAmount, #shippingCharge, #totalPackets, #packetShippingRate, #adjustAmount",(function(e){BMS.POS.grandTotal(e)})),$(document).on("submit","#posSale",(function(e){e.preventDefault();var t=0===$(".productQnt").length,a=$(".productSO").filter((function(){return 1==this.value})).length>0;if(""===$("#customersId").val())return BMS.fn.alertError("Please select the customer");var o=e.originalEvent.submitter;if("sale_is_hold"!==o.value||confirm("Are you sure to Hold this?"))if(t||a)Swal.fire({title:"Error!",html:t?"Please add a least one product":"Sorry! there have at least one out of stock product in selected warehouse, which are marked with <span style='Background-color:pink;'>Pink background</span>. Please remove them first.",icon:"error",onClose:$("body").css("padding","0px")});else{$(o).html("Submit &nbsp;&nbsp; <i class='fa fa-spin fa-refresh'></i>");var n=new FormData(this);n.append(o.name,o.value),$("#payment").find("button").prop("disabled",!0),$.ajax({url:full_website_address+"/info/?module=pos",type:"post",data:n,cache:!1,contentType:!1,processData:!1,success:function(t,a){if("success"==a){$(o).html("Printing...");var n=JSON.parse(t);"success"===n.saleStatus?BMS.MAIN.printPage(full_website_address+"/invoice-print/?invoiceType=posSale&id="+n.salesId,e,(function(){$("#payment").modal("hide"),BMS.POS.clearScreen(),$("#payment").find("button").prop("disabled",!1)})):($("#posErrorMsg").html('<div class="alert alert-danger">'+n.msg+"</div>"),$("#payment").find("button").prop("disabled",!1))}}})}})),$(document).on("submit","#productPurchase, #productStockTransfer, #productReturn, #specimenCopyForm, #scDistributionForm",(function(e){if($(".productQnt").length<1)return alert("Please add at least one product."),void e.preventDefault()})),$(document).on("submit","#wastageSaleForm",(function(e){return $(".wastageSaleItemQnt").length<1?(alert("Please add at least one item."),void e.preventDefault()):Number($("#wastageSalePaidAmount").val())>0&&""===$("#wastageSaleAccounts").val()?(alert("Please select the accounts."),void e.preventDefault()):void 0})),$(document).on("keypress","#posSale, #productPurchase, #productReturn, #productStockTransfer, #wastageSaleForm",(function(e){13===(e.keyCode||e.which)&&(!1===$("#payment, #finalizePurchase, #finalizeReturn, #finalizeWastageSale").hasClass("in")&&e.preventDefault(),isPosPage?(BMS.POS.grandTotal(),$("#orderDiscount").hasClass("in")?$("#orderDiscount").modal("hide"):$("#salesTariffCharges").hasClass("in")?$("#salesTariffCharges").modal("hide"):$("#productSaleDetails").hasClass("in")&&$("#productSaleDetails").modal("hide")):isPurchasePage?(BMS.PURCHASE.grandTotal(),$("#purchaseTariffCharges").hasClass("in")?$("#purchaseTariffCharges").modal("hide"):$("#purchaseDiscount").hasClass("in")&&$("#purchaseDiscount").modal("hide")):isProductReturnPage?(BMS.RETURN.grandTotal(),$("#returnTariffCharges").hasClass("in")?$("#returnTariffCharges").modal("hide"):$("#returnDiscount").hasClass("in")&&$("#returnDiscount").modal("hide")):isWastageSalePage&&(BMS.WASTAGE_SALE.grandTotal(),$("#wastageSaleTariffCharges").hasClass("in")?$("#wastageSaleTariffCharges").modal("hide"):$("#wastageSaleDiscount").hasClass("in")&&$("#wastageSaleDiscount").modal("hide")))})),$(document).on("shown.bs.modal","#orderDiscount, #purchaseDiscount, #returnDiscount, #wastageSaleDiscount, #payment",(function(){$("#purchaseDiscountValue, #purchasePaidAmount, #orderDiscountValue, #shippingCharge, #returnDiscountValue, #returnPaidAmount, #wastageSaleDiscountValue, #shippingCharge").select()})),$(document).on("show.bs.modal","#customerPurchaseList",(function(){BMS.fn.get(`customerPurchaseList&cid=${$("#customersId").val()}`,(e=>{if(""!=e){var t="";e.forEach((e=>{"Hold"===e.sales_status?t+=`<li class="item">\n <a href="${full_website_address}/sales/pos/?edit=${e.id}" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n <span style="font-size: 12px;" class="label label-warning">Hold</span>\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`:t+=`<li onClick="getPurchaseProductList(${e.id}, '${e.ref}');" class="item">\n <a href="javascript:void(0)" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`})),$("#showPurchaseList ul").html(t)}else $("#showPurchaseList ul").html('<li class="alert alert-danger">Sorry! No data found.</li>')}))})),$(document).on("keydown",".searchInvoiceInPos",(function(e){if("Enter"===e.key){$("body").toggleClass("wait");var t=encodeURIComponent($(this).val());BMS.fn.get(`customerPurchaseList&cid=${$("#customersId").val()}&s=${t}`,(e=>{if(""==e)return $("body").toggleClass("wait"),void $("#showPurchaseList ul").html('<li class="alert alert-danger">Sorry! No data found.</li>');var t="";e.forEach((e=>{"Hold"===e.sales_status?t+=`<li class="item">\n <a href="${full_website_address}/sales/pos/?edit=${e.id}" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n <span style="font-size: 12px;" class="label label-warning">Hold</span>\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`:t+=`<li onClick="getPurchaseProductList(${e.id}, '${e.ref}');" class="item">\n <a href="javascript:void(0)" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`})),$("#showPurchaseList ul").html(t),$("body").toggleClass("wait")}))}})),$(document).on("click",".quick-cash",(function(){var e=Number($(this).html());$(".posSalePaymentAmount").val(parseFloat(e).toFixed(2)),BMS.POS.grandTotal()})),$(document).on("hide.bs.modal","#productSaleDetails",(function(){var e=$("#productSaleDetails .rowId").val(),t=$("#productSaleDetails #productSaleItemPrice").val(),a=$("#productSaleDetails #productSaleItemDiscount").val(),o=$("#productSaleDetails #productSaleItemPacket").val(),n=$("#productSaleDetails #productSaleItemDetails").val(),s=$("tr#"+e);s.find(".netSalesPrice").val(t);var r=BMS.FUNCTIONS.calculateDiscount(t,a),l="";if(Number(r)===Number(t))l=parseFloat(t).toFixed(2);else l="<span>"+r+"</span><span><del><small>"+parseFloat(t).toFixed(2)+"</small></del></span>";s.find(".displayProductPrice").html(l),s.find(".productDiscount").val(a),s.find(".productItemDetails").val(n),s.find(".productPacket").val(o),s.find(".subtotalCol").html(r*s.find(".productQnt").val()),BMS.POS.grandTotal()})),$(document).on("focus",".productQnt",(function(){$(this)[0].scrollIntoView({behavior:"smooth",block:"nearest",inline:"start"})})),$(document).on("change","#ReturnMoney",(function(){$("#ReturnMoney").is(":checked")?$(".returnAmountAccountsDiv").show():$(".returnAmountAccountsDiv").hide()})),$(document).on("submit","#accountsLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=accountsLedger&account_id="+$("#accountSelection").val()+"&dateRange="+$("#accountsLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getAccountsInfo",{accountsId:$("#accountSelection").val()},(function(e,t){var a=JSON.parse(e);$("#accountsName").html(a.name),$("#accountsBalance").html(tsd(a.balance)),$("#accountsLedgerDates").html($("#accountsLedgerDateRange").val())}))})),$(document).on("submit","#employeeLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=employeeLedger&emp_id="+$("#employeeSelection").val()+"&dateRange="+$("#employeeLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getEmpSalaryData",{empId:$("#employeeSelection").val()},(function(e,t){var a=JSON.parse(e),o=Number(a.emp_payable_salary)+Number(a.emp_payable_overtime)+Number(a.emp_payable_bonus);$("#salaryInfo > tbody > tr > td:nth-child(1)").html(tsd(a.emp_payable_salary)),$("#salaryInfo > tbody > tr > td:nth-child(2)").html(tsd(a.emp_payable_overtime)),$("#salaryInfo > tbody > tr > td:nth-child(3)").html(tsd(a.emp_payable_bonus)),$("#salaryInfo > tbody > tr > td:nth-child(4)").html(tsd(o)),$("#employeeName").html(a.emp_firstname+" "+a.emp_lastname),$("#accountsLedgerDates").html($("#employeeLedgerDateRange").val())}))})),$(document).on("submit","#journalLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=journalLedger&journal_id="+$("#journalSelection").val()+"&dateRange="+$("#journalLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#customerLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=customerLedger&customer_id="+$("#customerSelection").val()+"&dateRange="+$("#customerLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#companyLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=companyLedger&company_id="+$("#companySelection").val()+"&dateRange="+$("#companyLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#advancePaymentLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=advancePaymentLedger&emp_id="+$("#employeeSelection").val()+"&dateRange="+$("#advancePaymentLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#productLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=productLedger&pid="+$("#productSelection").val()+"&wid="+$("#warehouseSelection").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#customerStatementReport",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=customerStatement&cid="+$("#customerSelection").val()+"&dateRange="+$("#customerStatementDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getCustomerStatementInfo",{customerId:$("#customerSelection").val(),dateRange:$("#customerStatementDateRange").val()},(function(e,t){var a=JSON.parse(e),o=Number(a.net_purchased)-(Number(a.total_product_returns)+Number(a.total_purchased_discount)),n=Number(a.advance_payments_amount)+Number(a.received_payments_amount)+Number(a.sales_payments_amount),s=n+Number(a.previous_balance)+Number(a.total_given_bonus)+Number(a.special_discounts_amount)-(o+Number(a.total_shipping)+Number(a.payments_return_amount));$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(2)").html(tsd(a.net_purchased)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(2)").html(tsd(a.total_purchased_discount)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(2)").html(tsd(a.total_shipping)),$("#paymentInfo > tbody > tr:nth-child(4) > td:nth-child(2)").html(tsd(a.total_product_returns)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(2)").html(tsd(o)),$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(4)").html(tsd(a.sales_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(4)").html(tsd(a.received_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(4)").html(tsd(a.advance_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(4)").html(tsd(n)),$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(6)").html(tsd(a.previous_balance)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(6)").html(tsd(a.total_given_bonus)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(6)").html(tsd(a.special_discounts_amount)),$("#paymentInfo > tbody > tr:nth-child(4) > td:nth-child(6)").html(tsd(a.payments_return_amount)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(6)").html(tsd(s)),$("#customerName").html(a.customer_name),$("#customerAddress").html(a.customer_address+", "+a.district_name),$("#customerStatementDates").html($("#customerStatementDateRange").val())}))})),$(document).on("submit","#locationWiseSaleReort",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=locationWiseSalesReport&pid="+$("#selectProductForLocationReport").val()+"&location="+$("#selectLocation").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("change","#paymentEmployee, #dontAdujctAdvance, .paymentsType",(function(){var e=$(this);$.post("<?php echo full_website_address(); ?>/info/?module=data&page=getEmpSalaryData",{empId:$("#paymentEmployee").val()},(function(t,a){$("#dontAdjustAdvance").is(":checked");var o=JSON.parse(t),n=Number(o.emp_payable_salary)+Number(o.emp_payable_overtime)+Number(o.emp_payable_bonus),s="Last taken loan: "+tsd(o.loan_amount)+"; Paid: "+tsd(o.loan_installment_paid_amount)+"; Monthly:"+tsd(o.loan_installment_amount);$("#salaryInfo > tbody > tr > td:nth-child(1)").html(tsd(o.emp_payable_salary)),$("#salaryInfo > tbody > tr > td:nth-child(2)").html(tsd(o.emp_payable_overtime)),$("#salaryInfo > tbody > tr > td:nth-child(3)").html(tsd(o.emp_payable_bonus)),$("#salaryInfo > tbody > tr > td:nth-child(4)").html(tsd(n)),$("#salaryInfo > tfoot > tr:nth-child(1) > th").html(s);var r=$(e).val();"Salary"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_salary).toFixed(0)):"Overtime"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_overtime).toFixed(0)):"Bonus"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_bonus).toFixed(0)):"Advance Salary"==r?$(e).closest(".row").find(".paymentAmount").val(0):$(".paymentAmount").val(Number(o.emp_payable_salary).toFixed(0))}))})),$(document).on("change","#paymentMethods",(function(){"Cheque"==$("#paymentMethods").val()?$("#hiddenItem").css("display","block"):$("#hiddenItem").css("display","none")})),$(document).off("click","#addSalaryPaymentRow"),$(document).on("click","#addSalaryPaymentRow",(function(){$("#salaryPaymentRow").append('<div class="row"> <div class="col-md-4"> <div class="form-group required"> <select name="paymentsType[]" class="paymentsType form-control" style="width: 100%;" required> <option value="Salary">Salary</option> <option value="Overtime">Overtime</option> <option value="Bonus">Bonus</option> </select> </div> </div> <div class="col-md-3"> <div class="form-group required"> <input type="number" name="paymentAmount[]" class="paymentAmount form-control" required> </div> </div> <div class="col-md-4"> <div class="form-group"> <input type="text" name="salaryPaymentNote[]" class="salaryPaymentNote form-control"> </div> </div> <div class="col-xs-1"> <i style="cursor: pointer; padding: 10px 5px 0 0;" class="fa fa-trash-o removeSalaryPaymentRow"></i> </div> </div>')})),$(document).on("click",".removeSalaryPaymentRow",(function(){$(this).closest(".row").css("background-color","whitesmoke").hide("slow",(function(){$(this).closest(".row").remove()}))})),$(document).on("focusin",".datePicker",(function(){BMS.FUNCTIONS.datePicker()})),$(document).on("focusin",".dateTimePicker",(function(){BMS.FUNCTIONS.datePicker({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".dateRangePicker",(function(){BMS.FUNCTIONS.dateRangePicker()})),$(document).on("focusin",".dateTimeRangePicker",(function(){BMS.FUNCTIONS.dateRangePicker({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".dateRangePickerPreDefined",(function(){BMS.FUNCTIONS.dateRangePickerPreDefined()})),$(document).on("focusin",".dateTimeRangePickerPreDefined",(function(){BMS.FUNCTIONS.dateRangePickerPreDefined({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".multiDatePicker",(function(){BMS.FUNCTIONS.multiDatePicker()})),$(document).on("change",".imageToUpload",(function(){var e=$(this).closest(".imageContainer").find(".photoErrorMessage");$(e).empty();var t=this.files[0],a=t.type,o=t.size;if(!1===["image/jpeg","image/png","image/jpg"].includes(a))return $(e).length<1?(BMS.fn.alertError("<?php echo __('Please select a valid image file'); ?>"),this.value=this.defaultValue):$(e).html("<div style='margin-bottom: 0;' class='alert alert-danger'><?php echo __('Please select a valid image file'); ?></div>"),!1;if("<?php echo $_SETTINGS['MAX_UPLOAD_SIZE'] * 1024 * 1024; ?>"<o)return $(e).length<1?(BMS.fn.alertError("<?php echo __('Max file size %d MB', $_SETTINGS['MAX_UPLOAD_SIZE']); ?>"),this.value=this.defaultValue):$(e).html("<div class='alert alert-danger'><?php echo __('Max file size %d MB', $_SETTINGS['MAX_UPLOAD_SIZE']); ?></div>"),!1;var n=$(this).val().replace(/\\/g,"/").replace(/.*\//,"");$(this).closest(".imageContainer").find(".imageNameShow").val(n);var s=$(this),r=new FileReader;r.onload=function(e){$(s).css("color","green"),$(s).closest(".imageContainer").find(".image_preview").css("display","block"),$(s).closest(".imageContainer").find(".previewing").attr("src",e.target.result)},r.readAsDataURL(this.files[0])})),$(document).on("click","#addPosSalePaymentRow",(function(){$(".paymentMethodBox").append('<div style="margin: 0;" class="row">\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Amount</label>\n <span style="cursor:pointer; padding: 0 4px;" class="pull-right removePosPaymentItem" ><i class="fa fa-times"></i></span>\n <input type="number" onclick="this.select();" name="posSalePaymentAmount[]" class="form-control posSalePaymentAmount" step="any">\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Reference/Info</label>\n <input type="text" name="posSalePaymentReference[]" class="form-control">\n </div>\n <div style="display: none;" class="posSalePaymentBankAccount form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Bank Account</label>\n <select name="posSalePaymentBankAccount[]" class="form-control pull-left select2Ajax" \n select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=accountList" style="width: 100%;">\n <option value=""><?php echo __("Select Account"); ?>....</option>\n </select>\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Payment Method</label>\n <select name="posSalePaymentMethod[]" class="posSalePaymentMethod form-control">\n <option value="Cash"><?php echo __("Cash"); ?></option>\n <option value="Bank Transfer"><?php echo __("Bank Transfer"); ?></option>\n <option value="Cheque"><?php echo __("Cheque"); ?></option>\n <option value="Card"><?php echo __("Card"); ?></option>\n <option value="Others"><?php echo __("Others"); ?></option>\n </select>\n </div>\n </div>')})),$(document).on("click",".removePosPaymentItem",(function(){$(this).closest(".row").remove(),BMS.POS.grandTotal()})),$(document).on("change",".posSalePaymentMethod",(function(){"Cash"===$(this).val()?$(this).closest(".row").find(".posSalePaymentBankAccount").hide():$(this).closest(".row").find(".posSalePaymentBankAccount").show()})),$(document).on("submit","#modalForm, #popUpForm, #jqFormAdd, #jqFormUpdate",(function(e){e.preventDefault(),ajaxFormSubmit(this)})),$(document).on("submit","#inlineForm",(function(e){e.preventDefault(),ajaxFormSubmit(this,!0)})),$(document).on("click",".deleteEntry",(function(e){e.preventDefault();var t=$(this).attr("href"),a=$(this).attr("data-to-be-deleted"),o=$(this).attr("removeParent"),n=this;Swal.fire({title:"Are you sure to delete this entry?",icon:"warning",didOpen:function(){BMS.fn.play("warning")},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:"Yes, delete it!"}).then((e=>{e.value&&$.post(t,{datatoDelete:a},(function(e,t){if(isJson(e)){var a=JSON.parse(e);for(var s in a)sweetAlert[s]=a[s]}Swal.fire({toast:sweetAlert.toast,position:sweetAlert.position,timer:sweetAlert.timer,showConfirmButton:sweetAlert.showConfirmButton,showCloseButton:sweetAlert.showCloseButton,icon:sweetAlert.icon,title:sweetAlert.title,text:sweetAlert.text,onClose:$("body").css("padding","0px")}),void 0!==o&&$(n).closest(o).hide("fast"),$("#dataTableWithAjax").DataTable().ajax.reload(null,!1),$("#dataTableWithAjaxExtend").DataTable().ajax.reload(null,!1)}))}))})),$(document).on("click",".updateEntry",(function(e){e.preventDefault();var t=$(this).attr("href"),a=$(this).attr("data-to-be-updated");$(this).css("color","black"),$(this).find("i.fa").addClass("fa-spin"),$.post(t,{datatoUpdate:a},(function(e,t){if(isJson(e)){var a=JSON.parse(e);for(var o in a)sweetAlert[o]=a[o]}Swal.fire({toast:sweetAlert.toast,position:sweetAlert.position,timer:sweetAlert.timer,showConfirmButton:sweetAlert.showConfirmButton,showCloseButton:sweetAlert.showCloseButton,icon:sweetAlert.icon,title:sweetAlert.title,text:sweetAlert.text,onClose:$("body").css("padding","0px")}),$("#dataTableWithAjax").DataTable().ajax.reload(null,!1),$("#dataTableWithAjaxExtend").DataTable().ajax.reload(null,!1)}))})),$(document).on("dblclick","iledit",(function(e){e.preventDefault();var t=$(this),a=t.closest("td"),o=t.closest("table").find("th").eq(a.index()),n=t.closest("tr").find("pkey").text(),s=o.attr("type"),r=o.attr("data-source"),l=o.attr("data-options"),i=o.attr("where-to-update"),c=t.attr("data-val"),d=t.text(),u=a.width();if("select2"===s){a.html(`\n <select class="form-control select2InlineEdit" select2-ajax-url="${r}" style="width: ${u}px;" required>\n <option value=""><?php echo __("Select Entry"); ?>....</option>\n </select>\n `);var m=a.find(".select2InlineEdit");BMS.fn.select2(m,c,d),m.select2("open")}else if("select"===s){(l=l.split(",")).forEach((function(e){l+=`<option ${d==e?"selected":""} value='${e}'>${e}</option>`})),a.html(`\n <select class="form-control" style="width: ${u}px; padding: 6px 6px;" required>\n ${l}\n </select>\n `),(m=a.find("select")).select2(),m.select2("open")}else a.html(`\n <input type="text" value="${d}" style="width: ${u}px;" class="form-control">\n `),"datePicker"===s&&(a.find("input").addClass("datePicker"),a.find(".datePicker").focus());a.find("input, select, textarea").on("enter blur clear apply.daterangepicker, select2:close",(function(){var e=["select2","select"].includes(s)?c:d,t=$(this).val(),o=$(this);t!==e?$.post(i,{pkey:n,newData:t},(function(e,t){void 0!==(e=JSON.parse(e)).error&&"true"===e.error?BMS.fn.alertError(e.msg):(BMS.fn.alertSuccess("The data has been successfully updated."),"select2"===s||"select"===s?a.html("<iledit data-val='"+$(o).val()+"'>"+$("option:selected",o).text()+"</iledit>"):a.html("<iledit>"+$(o).val()+"</iledit>"))})):"select2"===s||"select"===s?a.html("<iledit data-val='"+$(o).val()+"'>"+$("option:selected",o).text()+"</iledit>"):a.html("<iledit>"+$(o).val()+"</iledit>")}))})),$(document).on("hidden.bs.modal",(function(e){$(e.target).removeData("bs.modal").find(".modal-ajax").html("")})),$(document).ready((function(){$(document).on("mouseenter focus",".select2Ajax",(function(){BMS.fn.select2(this)}))})),$(document).ready((function(){$("body").tooltip({selector:'[data-toggle="tooltip"]'})})),$(document).click((function(e){$(".dropdown-menu[data-parent]").hide()})),$(document).on("click",'.col-sm-12 [data-toggle="dropdown"]',(function(){if($("body").hasClass("modal-open"))throw new Error("This solution is not working inside a responsive table inside a modal, you need to find out a way to calculate the modal Z-index and add it to the element");if($buttonGroup=$(this).parent(),$buttonGroup.attr("data-attachedUl"))$ul=$("[data-parent="+$buttonGroup.attr("data-attachedUl")+"]");else{var e=+new Date;$ul=$(this).siblings("ul"),$ul.attr("data-parent",e),$buttonGroup.attr("data-attachedUl",e),$(window).resize((function(){$ul.css("display","none").data("top")}))}var t,a,o;$buttonGroup.hasClass("open")?(t=$(this).parent(),a=$ul,o=t.offset().top+t.outerHeight(),a.css("top",o+"px"),a.css("left",t.offset().left-100+"px"),a.css("position","absolute"),a.css("width",a.width()),a.css("heigt",a.height()),a.css("display","block"),a.appendTo(".dynamic-container")):$ul.css("display","none")})),$(document).on("click",".restricted",(function(){Swal.fire({title:"Sorry!",text:"You have no permission to perform this action",icon:"error"})})),$(".modal").on("show.bs.modal",(function(e){if(-1!==$.inArray("restricted",e.target.classList))return e.preventDefault()})),$(".modal").on("shown.bs.modal",(function(){$(this).find("[autofocus]").focus()})),$("form").on("focus","input[type=number]",(function(e){$(this).on("wheel.disableScroll",(function(e){e.preventDefault()}))})),$("form").on("blur","input[type=number]",(function(e){$(this).off("wheel.disableScroll")}));var sweetAlert=[];sweetAlert.title="The command has been executed successfully.",sweetAlert.text="",sweetAlert.icon="success",sweetAlert.toast=!0,sweetAlert.position="top",sweetAlert.timer=5e3,sweetAlert.showConfirmButton=!1,sweetAlert.showCloseButton=!1,$('input[type="checkbox"].square, input[type="radio"].square').iCheck({checkboxClass:"icheckbox_square-blue",radioClass:"iradio_square-blue"}),$.ajaxSetup({beforeSend:function(e){e.setRequestHeader("X-CSRF-TOKEN",xCsrfToken)}});var getPageTitle=JSON.parse('<?php echo json_encode($_SETTINGS["PAGE_TITLE"]); ?>');$(window).bind("popstate",(function(e){"undefined"!=typeof session&&(session.terminate(),phone.stop()),e.preventDefault(),$.get(location.href+"?contentOnly=true",(function(e,t){defaultiDisplayLength="",$("li").removeClass("active");var a=location.href,o="Not Found!";void 0!==getPageTitle[a]&&(o=getPageTitle[a]),window.document.title=o,$(".dynamic-container").html(e),jQuery.get(full_website_address+"/assets/js/initiator.min.js")}))})),$(document).on("keydown",(function(e){"F2"===e.key&&($("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").hasClass("select2-hidden-accessible")||BMS.fn.select2("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct"),$("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").select2("open")),"F3"===e.key&&(e.preventDefault(),$("#orderDiscount").modal("show"))})),$(document).on("click",".toggleNotButton",(function(){var e=$(this).closest("span").find(".notThisValueFilter");"="===$(e).val()?($(e).val("!="),$(this).text("|")):($(this).text(""),$(e).val("="))})),$(document).on("click",".stopPropagation",(function(e){e.stopPropagation()})),$(document).on("change","#productType",(function(){$("#productVariationSection").hide(),$("#bundleProductsContainer").hide(),$(".bundleProduct").hide(),$(".groupedProduct").hide();"Variable"===this.value?$("#productVariationSection").show():"Bundle"===this.value?($(".bundleProduct").show(),$("#bundleProductsContainer").show()):"Grouped"===this.value&&($(".groupedProduct").show(),$("#bundleProductsContainer").show())})),$(document).on("click",".removeThisVariation",(function(e){if(e.stopPropagation(),confirm("Are sure to remove this variation?")){var t=$(this).closest("li").find(".variation_product_id").val();$(this).closest("li").hide("fast",(function(){$(this).remove()})),void 0!==t&&$.ajax({url:full_website_address+"/xhr/?module=products&page=deleteVariationProduct",type:"post",data:{product_id:t},success:function(e,t){}})}})),$(document).on("click","#setVariationPrice",(function(){setVariationPrice()})),$(window).keydown((function(e){if(13==e.keyCode&&$("#productVariationPrice").hasClass("in"))return e.preventDefault(),setVariationPrice(),$("#productVariationPrice").modal("hide"),!1})),$("#browseProduct").on("show.bs.modal",(function(e){BMS.PRODUCT.showProduct()})),$(document).on("change","#productHasExpiryDate",(function(){"1"===this.value?$(".productIntitalStock").prop("disabled",!0):$(".productIntitalStock").prop("disabled",!1)}));let barCcode="";$(document).on("keypress",(e=>{if("Enter"===e.key){var t="input"!==e.target.tagName.toLowerCase();""!==barCcode&&(isPosPage&&t?BMS.POS.addProduct(barCcode,!0):isPurchasePage&&t?BMS.PURCHASE.addProduct(barCcode,!0):isTransferStockPage&&t?BMS.STOCK_TRANSFER.addProduct(barCcode,!0):isProductReturnPage&&t?BMS.RETURN.addProduct(barCcode,!0):isStockEntryPage&&t?BMS.STOCK_ENTRY.addProduct(barCcode,!0):isAddProductPage&&$("#productCode").val(barCcode)),barCcode=""}else barCcode+=e.key})),$(document).on("click",".copyThis",(function(e){navigator.clipboard.writeText($(this).text())}));
\ No newline at end of file
+$(document).on("change","#productCategoryFilter, #productBrandFilter, #productEditionFilter, #productGenericFilter, #productAuthorFilter",(function(){BMS.PRODUCT.showProduct({category:$("#productCategoryFilter").val(),brand:$("#productBrandFilter").val(),edition:$("#productEditionFilter").val(),generic:$("#productGenericFilter").val(),author:$("#productAuthorFilter").val()})})),$(document).on("change","#customers",(function(){var e=$("#customers").val();$("#customersId").val(e),BMS.fn.get(`getCustomerData&cid=${e}`,(function(e){$("#orderDiscountValue").val(e.discount),$("#packetShippingRate").val(e.shipping_rate)}))})),$(document).on("change","#warehouse",(function(){var e=$("#warehouse").val();$("#warehouseId").val(e),$("#selectPosProduct").attr("select2-ajax-url",`${full_website_address}/info/?module=select2&page=productListForPos&wid=${e}`),BMS.fn.select2("#selectPosProduct")})),$(document).on("change","#stockTransferFromWarehouse, #stockTransferToWarehouse",(function(){var e=$("#stockTransferFromWarehouse").val(),t=$("#stockTransferToWarehouse").val();$("#stockTransferFromWarehouseId").val(e),$("#stockTransferToWarehouseId").val(t)})),$(document).on("change","#scTransferWarehouse",(function(){var e=$("#scTransferWarehouse").val();$("#scTransferWarehouseId").val(e)})),$(document).on("click","#addTariffChargesRow",(function(){BMS.MAIN.addTariffChargesRow("#tariffCharges")})),$(document).on("click",".productButton",(function(){isPosPage?BMS.POS.addProduct(this.value):isPurchasePage?BMS.PURCHASE.addProduct(this.value):isTransferStockPage?BMS.STOCK_TRANSFER.addProduct(this.value):isProductReturnPage?BMS.RETURN.addProduct(this.value):isSpecimenCopyPage?BMS.SPECIMEN_COPY.addProduct(this.value):isScDistributionPage?BMS.SC_DISTRIBUTION.addProduct(this.value):isAddProductPage?BMS.PRODUCT.addProduct(this.value):isStockEntryPage?BMS.STOCK_ENTRY.addProduct(this.value):isSaleOrderPage&&BMS.ORDER.addProduct(this.value)})),$(document).on("change","#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct",(function(){isPosPage?BMS.POS.addProduct(this.value):isPurchasePage?BMS.PURCHASE.addProduct(this.value):isTransferStockPage?BMS.STOCK_TRANSFER.addProduct(this.value):isProductReturnPage?BMS.RETURN.addProduct(this.value):isSpecimenCopyPage?BMS.SPECIMEN_COPY.addProduct(this.value):isScDistributionPage?BMS.SC_DISTRIBUTION.addProduct(this.value):isAddProductPage?BMS.PRODUCT.addProduct(this.value):isStockEntryPage?BMS.STOCK_ENTRY.addProduct(this.value):isSaleOrderPage&&BMS.ORDER.addProduct(this.value),$(this).html("<option value=''>Search Product....</option>")})),$(document).on("click","#addWastageSaleRow",(function(){BMS.WASTAGE_SALE.addWastageSaleItem()})),$(document).on("click",".removeThisProduct, .removeThisItem",(function(){$(this).closest("tr").css("background-color","red").hide("fast",(function(){$(this).closest("tr").remove(),isPosPage?(BMS.POS.grandTotal(),BMS.POS.disableEnableWCSelect()):isPurchasePage?BMS.PURCHASE.grandTotal():isTransferStockPage?(BMS.STOCK_TRANSFER.grandTotal(),BMS.STOCK_TRANSFER.disableEnableWarehouseSelect()):isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSpecimenCopyPage?BMS.SPECIMEN_COPY.disableEnableWarehouseSelect():isStockEntryPage?BMS.STOCK_ENTRY.grandTotal():isSaleOrderPage&&(BMS.ORDER.grandTotal(),BMS.POS.disableEnableWCSelect())}))})),$(document).on("click",".removeThisTariffCharges",(function(){$(this).closest(".row").css("background-color","whitesmoke").hide("fast",(function(){$(this).closest(".row").remove(),isPosPage?BMS.POS.grandTotal():isPurchasePage?BMS.PURCHASE.grandTotal():isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSaleOrderPage&&BMS.ORDER.grandTotal()}))})),$(document).on("change",".tariffChargesName",(function(){isPosPage?BMS.POS.grandTotal():isPurchasePage?BMS.PURCHASE.grandTotal():isProductReturnPage?BMS.RETURN.grandTotal():isWastageSalePage?BMS.WASTAGE_SALE.grandTotal():isSaleOrderPage&&BMS.ORDER.grandTotal()})),$(document).on("keyup blur",".productQnt",(function(){isPosPage?BMS.POS.productQntCheck(this):isPurchasePage?(BMS.PURCHASE.calculateEachProduct(this),BMS.PURCHASE.grandTotal()):isTransferStockPage?BMS.STOCK_TRANSFER.productQntCheck(this):isProductReturnPage?(BMS.RETURN.grandTotal(),BMS.RETURN.calculateEachProduct(this)):isSpecimenCopyPage?BMS.SPECIMEN_COPY.productQntCheck(this):isStockEntryPage?(BMS.STOCK_ENTRY.calculateEachProduct(this),BMS.STOCK_ENTRY.grandTotal()):isSaleOrderPage&&BMS.ORDER.productQntCheck(this)})),$(document).on("keydown",".productQnt",(function(e){"Enter"===e.key&&($("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").hasClass("select2-hidden-accessible")||BMS.fn.select2("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct"),$("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").select2("open"))})),$(document).on("keydown","#purchaseDiscountValue",(function(e){"Enter"===e.key&&(e.preventDefault(),$("#purchaseDiscount").modal("hide"),$("#finalizePurchase").modal("show"))})),$(document).on("keydown","#shippingCharge",(function(e){"Enter"===e.key&&(e.preventDefault(),$("#adjustAmount").select())})),$(document).on("keydown","#adjustAmount",(function(e){$(this).addClass("disableAdjustAmountAutoChange"),"Enter"===e.key&&(e.preventDefault(),$(".posSalePaymentAmount").first().select(),$(".posSalePaymentAmount").first().addClass("disablePaymentAmountAutoChange"))})),$(document).on("keydown focus",".posSalePaymentAmount",(function(e){var t=$(this).closest(".row").next(".row").find("input.posSalePaymentAmount");$(this).addClass("disablePaymentAmountAutoChange"),1===t.length&&"Enter"===e.key&&(e.preventDefault(),t.addClass("disablePaymentAmountAutoChange"),t.select())})),$(document).on("keydown",".select2-search__field",(function(e){isPosPage&&"select2-selectPosProduct-results"===$(this).attr("aria-controls")&&""===this.value&&$(".productQnt").length>0&&"Enter"===e.key&&($("#selectPosProduct").select2("close"),$("#orderDiscount").modal("show")),isPurchasePage&&"select2-selectProduct-results"===$(this).attr("aria-controls")&&""===this.value&&$(".productQnt").length>0&&"Enter"===e.key&&($("#selectProduct").select2("close"),$("#purchaseDiscount").modal("show"))})),$(document).on("hide.bs.modal","#orderDiscount",(function(e){var t=$("#orderDiscountValue"),a=$(t).val();BMS.POS.isGivenDiscountPermitted(t)?($("#payment").modal("show"),BMS.POS.grandTotal()):(Swal.fire({title:"Error!",text:`You do not have permission to give ${a} discount.`,icon:"error"}),$(t).val(0),e.preventDefault())})),$(document).on("blur keyup",".wastageSaleItemQnt, .wastageSaleItemPrice",(function(){var e=$(this).closest("tr").find(".wastageSaleItemQnt").val(),t=$(this).closest("tr").find(".wastageSaleItemPrice").val();$(this).closest("tr").find(".wastageSaleItemSubtotal").html(parseFloat(e*t).toFixed(2)),BMS.WASTAGE_SALE.grandTotal()})),$(document).on("blur keyup","#wastageSaleDiscount, #wastageSalePaidAmount",(function(){BMS.WASTAGE_SALE.grandTotal()})),$(document).on("blur keyup",".productPurchaseDiscount, .productPurchasePrice",(function(){isPurchasePage?(BMS.PURCHASE.calculateEachProduct(this),BMS.PURCHASE.grandTotal()):isTransferStockPage&&(BMS.STOCK_TRANSFER.calculateEachProduct($(this)),BMS.STOCK_TRANSFER.grandTotal())})),$(document).on("blur keyup",".productReturnDiscount, .productReturnPrice",(function(){BMS.RETURN.calculateEachProduct(this),BMS.RETURN.grandTotal()})),$(document).on("keyup blur","#purchaseDiscount, #purchasePaidAmount, #purchaseShipping",(function(){BMS.PURCHASE.grandTotal()})),$(document).on("keyup blur","#returnDiscount, #returnShipping, #returnSurcharge, #returnPaidAmount",(function(){BMS.RETURN.grandTotal()})),$(document).on("keyup blur","#productSaleItemPacket",(function(){})),$(document).on("blur keydown","#productSaleItemDiscount",(function(e){BMS.POS.productDiscountCheck(e)})),$(document).on("keydown","#orderDiscountValue",(function(e){13===(e.keyCode||e.which)&&BMS.POS.orderDiscountCheck(this,e)})),$(document).on("keyup",".posSalePaymentAmount, #shippingCharge, #totalPackets, #packetShippingRate, #adjustAmount",(function(e){BMS.POS.grandTotal(e)})),$(document).on("submit","#posSale",(function(e){e.preventDefault();var t=0===$(".productQnt").length,a=$(".productSO").filter((function(){return 1==this.value})).length>0;if(""===$("#customersId").val())return BMS.fn.alertError("Please select the customer");var o=e.originalEvent.submitter;if("sale_is_hold"!==o.value||confirm("Are you sure to Hold this?"))if(t||a)Swal.fire({title:"Error!",html:t?"Please add a least one product":"Sorry! there have at least one out of stock product in selected warehouse, which are marked with <span style='Background-color:pink;'>Pink background</span>. Please remove them first.",icon:"error",onClose:$("body").css("padding","0px")});else{$(o).html("Submit &nbsp;&nbsp; <i class='fa fa-spin fa-refresh'></i>");var n=new FormData(this);n.append(o.name,o.value),$("#payment").find("button").prop("disabled",!0),$.ajax({url:full_website_address+"/info/?module=pos",type:"post",data:n,cache:!1,contentType:!1,processData:!1,success:function(t,a){if("success"==a){$(o).html("Printing...");var n=JSON.parse(t);"success"===n.saleStatus?BMS.MAIN.printPage(full_website_address+"/invoice-print/?invoiceType=posSale&id="+n.salesId,e,(function(){$("#payment").modal("hide"),BMS.POS.clearScreen(),$("#payment").find("button").prop("disabled",!1)})):($("#posErrorMsg").html('<div class="alert alert-danger">'+n.msg+"</div>"),$("#payment").find("button").prop("disabled",!1))}}})}})),$(document).on("submit","#productPurchase, #productStockTransfer, #productReturn, #specimenCopyForm, #scDistributionForm",(function(e){if($(".productQnt").length<1)return alert("Please add at least one product."),void e.preventDefault()})),$(document).on("submit","#wastageSaleForm",(function(e){return $(".wastageSaleItemQnt").length<1?(alert("Please add at least one item."),void e.preventDefault()):Number($("#wastageSalePaidAmount").val())>0&&""===$("#wastageSaleAccounts").val()?(alert("Please select the accounts."),void e.preventDefault()):void 0})),$(document).on("keypress","#posSale, #productPurchase, #productReturn, #productStockTransfer, #wastageSaleForm",(function(e){13===(e.keyCode||e.which)&&(!1===$("#payment, #finalizePurchase, #finalizeReturn, #finalizeWastageSale").hasClass("in")&&e.preventDefault(),isPosPage?(BMS.POS.grandTotal(),$("#orderDiscount").hasClass("in")?$("#orderDiscount").modal("hide"):$("#salesTariffCharges").hasClass("in")?$("#salesTariffCharges").modal("hide"):$("#productSaleDetails").hasClass("in")&&$("#productSaleDetails").modal("hide")):isPurchasePage?(BMS.PURCHASE.grandTotal(),$("#purchaseTariffCharges").hasClass("in")?$("#purchaseTariffCharges").modal("hide"):$("#purchaseDiscount").hasClass("in")&&$("#purchaseDiscount").modal("hide")):isProductReturnPage?(BMS.RETURN.grandTotal(),$("#returnTariffCharges").hasClass("in")?$("#returnTariffCharges").modal("hide"):$("#returnDiscount").hasClass("in")&&$("#returnDiscount").modal("hide")):isWastageSalePage&&(BMS.WASTAGE_SALE.grandTotal(),$("#wastageSaleTariffCharges").hasClass("in")?$("#wastageSaleTariffCharges").modal("hide"):$("#wastageSaleDiscount").hasClass("in")&&$("#wastageSaleDiscount").modal("hide")))})),$(document).on("shown.bs.modal","#orderDiscount, #purchaseDiscount, #returnDiscount, #wastageSaleDiscount, #payment",(function(){$("#purchaseDiscountValue, #purchasePaidAmount, #orderDiscountValue, #shippingCharge, #returnDiscountValue, #returnPaidAmount, #wastageSaleDiscountValue, #shippingCharge").select()})),$(document).on("show.bs.modal","#customerPurchaseList",(function(){BMS.fn.get(`customerPurchaseList&cid=${$("#customersId").val()}`,(e=>{if(""!=e){var t="";e.forEach((e=>{"Hold"===e.sales_status?t+=`<li class="item">\n <a href="${full_website_address}/sales/pos/?edit=${e.id}" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n <span style="font-size: 12px;" class="label label-warning">Hold</span>\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`:t+=`<li onClick="getPurchaseProductList(${e.id}, '${e.ref}');" class="item">\n <a href="javascript:void(0)" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`})),$("#showPurchaseList ul").html(t)}else $("#showPurchaseList ul").html('<li class="alert alert-danger">Sorry! No data found.</li>')}))})),$(document).on("keydown",".searchInvoiceInPos",(function(e){if("Enter"===e.key){$("body").toggleClass("wait");var t=encodeURIComponent($(this).val());BMS.fn.get(`customerPurchaseList&cid=${$("#customersId").val()}&s=${t}`,(e=>{if(""==e)return $("body").toggleClass("wait"),void $("#showPurchaseList ul").html('<li class="alert alert-danger">Sorry! No data found.</li>');var t="";e.forEach((e=>{"Hold"===e.sales_status?t+=`<li class="item">\n <a href="${full_website_address}/sales/pos/?edit=${e.id}" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n <span style="font-size: 12px;" class="label label-warning">Hold</span>\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`:t+=`<li onClick="getPurchaseProductList(${e.id}, '${e.ref}');" class="item">\n <a href="javascript:void(0)" class="product-title">\n ${e.date} (${e.ref})\n <span style="font-size: 12px;" class="label label-success pull-right">${to_money(e.total)}</span>\n <span class="product-description">\n From: ${e.shop}; Status: ${e.pay_status}\n </span>\n </a>\n </li>`})),$("#showPurchaseList ul").html(t),$("body").toggleClass("wait")}))}})),$(document).on("click",".quick-cash",(function(){var e=Number($(this).html());$(".posSalePaymentAmount").val(parseFloat(e).toFixed(2)),BMS.POS.grandTotal()})),$(document).on("hide.bs.modal","#productSaleDetails",(function(){var e=$("#productSaleDetails .rowId").val(),t=$("#productSaleDetails #productSaleItemPrice").val(),a=$("#productSaleDetails #productSaleItemDiscount").val(),o=$("#productSaleDetails #productSaleItemPacket").val(),n=$("#productSaleDetails #productSaleItemDetails").val(),s=$("tr#"+e);s.find(".netSalesPrice").val(t);var r=BMS.FUNCTIONS.calculateDiscount(t,a),l="";if(Number(r)===Number(t))l=parseFloat(t).toFixed(2);else l="<span>"+r+"</span><span><del><small>"+parseFloat(t).toFixed(2)+"</small></del></span>";s.find(".displayProductPrice").html(l),s.find(".productDiscount").val(a),s.find(".productItemDetails").val(n),s.find(".productPacket").val(o),s.find(".subtotalCol").html(r*s.find(".productQnt").val()),BMS.POS.grandTotal()})),$(document).on("focus",".productQnt",(function(){$(this)[0].scrollIntoView({behavior:"smooth",block:"nearest",inline:"start"})})),$(document).on("change","#ReturnMoney",(function(){$("#ReturnMoney").is(":checked")?$(".returnAmountAccountsDiv").show():$(".returnAmountAccountsDiv").hide()})),$(document).on("submit","#accountsLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=accountsLedger&account_id="+$("#accountSelection").val()+"&dateRange="+$("#accountsLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getAccountsInfo",{accountsId:$("#accountSelection").val()},(function(e,t){var a=JSON.parse(e);$("#accountsName").html(a.name),$("#accountsBalance").html(tsd(a.balance)),$("#accountsLedgerDates").html($("#accountsLedgerDateRange").val())}))})),$(document).on("submit","#employeeLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=employeeLedger&emp_id="+$("#employeeSelection").val()+"&dateRange="+$("#employeeLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getEmpSalaryData",{empId:$("#employeeSelection").val()},(function(e,t){var a=JSON.parse(e),o=Number(a.emp_payable_salary)+Number(a.emp_payable_overtime)+Number(a.emp_payable_bonus);$("#salaryInfo > tbody > tr > td:nth-child(1)").html(tsd(a.emp_payable_salary)),$("#salaryInfo > tbody > tr > td:nth-child(2)").html(tsd(a.emp_payable_overtime)),$("#salaryInfo > tbody > tr > td:nth-child(3)").html(tsd(a.emp_payable_bonus)),$("#salaryInfo > tbody > tr > td:nth-child(4)").html(tsd(o)),$("#employeeName").html(a.emp_firstname+" "+a.emp_lastname),$("#accountsLedgerDates").html($("#employeeLedgerDateRange").val())}))})),$(document).on("submit","#journalLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=journalLedger&journal_id="+$("#journalSelection").val()+"&dateRange="+$("#journalLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#customerLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=customerLedger&customer_id="+$("#customerSelection").val()+"&dateRange="+$("#customerLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#companyLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=companyLedger&company_id="+$("#companySelection").val()+"&dateRange="+$("#companyLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#advancePaymentLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=ledgers&page=advancePaymentLedger&emp_id="+$("#employeeSelection").val()+"&dateRange="+$("#advancePaymentLedgerDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#productLedgerForm",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=productLedger&pid="+$("#productSelection").val()+"&wid="+$("#warehouseSelection").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("submit","#customerStatementReport",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=customerStatement&cid="+$("#customerSelection").val()+"&dateRange="+$("#customerStatementDateRange").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load(),$.post(full_website_address+"/info/?module=data&page=getCustomerStatementInfo",{customerId:$("#customerSelection").val(),dateRange:$("#customerStatementDateRange").val()},(function(e,t){var a=JSON.parse(e),o=Number(a.net_purchased)-(Number(a.total_product_returns)+Number(a.total_purchased_discount)),n=Number(a.advance_payments_amount)+Number(a.received_payments_amount)+Number(a.sales_payments_amount),s=n+Number(a.previous_balance)+Number(a.total_given_bonus)+Number(a.special_discounts_amount)-(o+Number(a.total_shipping)+Number(a.payments_return_amount));$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(2)").html(tsd(a.net_purchased)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(2)").html(tsd(a.total_purchased_discount)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(2)").html(tsd(a.total_shipping)),$("#paymentInfo > tbody > tr:nth-child(4) > td:nth-child(2)").html(tsd(a.total_product_returns)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(2)").html(tsd(o)),$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(4)").html(tsd(a.sales_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(4)").html(tsd(a.received_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(4)").html(tsd(a.advance_payments_amount)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(4)").html(tsd(n)),$("#paymentInfo > tbody > tr:nth-child(1) > td:nth-child(6)").html(tsd(a.previous_balance)),$("#paymentInfo > tbody > tr:nth-child(2) > td:nth-child(6)").html(tsd(a.total_given_bonus)),$("#paymentInfo > tbody > tr:nth-child(3) > td:nth-child(6)").html(tsd(a.special_discounts_amount)),$("#paymentInfo > tbody > tr:nth-child(4) > td:nth-child(6)").html(tsd(a.payments_return_amount)),$("#paymentInfo > tbody > tr:nth-child(5) > td:nth-child(6)").html(tsd(s)),$("#customerName").html(a.customer_name),$("#customerAddress").html(a.customer_address+", "+a.district_name),$("#customerStatementDates").html($("#customerStatementDateRange").val())}))})),$(document).on("submit","#locationWiseSaleReort",(function(e){e.preventDefault();var t=full_website_address+"/xhr/?module=reports&page=locationWiseSalesReport&pid="+$("#selectProductForLocationReport").val()+"&location="+$("#selectLocation").val();$("#dataTableWithAjaxExtend").DataTable().ajax.url(t).load()})),$(document).on("change","#paymentEmployee, #dontAdujctAdvance, .paymentsType",(function(){var e=$(this);$.post("<?php echo full_website_address(); ?>/info/?module=data&page=getEmpSalaryData",{empId:$("#paymentEmployee").val()},(function(t,a){$("#dontAdjustAdvance").is(":checked");var o=JSON.parse(t),n=Number(o.emp_payable_salary)+Number(o.emp_payable_overtime)+Number(o.emp_payable_bonus),s="Last taken loan: "+tsd(o.loan_amount)+"; Paid: "+tsd(o.loan_installment_paid_amount)+"; Monthly:"+tsd(o.loan_installment_amount);$("#salaryInfo > tbody > tr > td:nth-child(1)").html(tsd(o.emp_payable_salary)),$("#salaryInfo > tbody > tr > td:nth-child(2)").html(tsd(o.emp_payable_overtime)),$("#salaryInfo > tbody > tr > td:nth-child(3)").html(tsd(o.emp_payable_bonus)),$("#salaryInfo > tbody > tr > td:nth-child(4)").html(tsd(n)),$("#salaryInfo > tfoot > tr:nth-child(1) > th").html(s);var r=$(e).val();"Salary"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_salary).toFixed(0)):"Overtime"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_overtime).toFixed(0)):"Bonus"==r?$(e).closest(".row").find(".paymentAmount").val(Number(o.emp_payable_bonus).toFixed(0)):"Advance Salary"==r?$(e).closest(".row").find(".paymentAmount").val(0):$(".paymentAmount").val(Number(o.emp_payable_salary).toFixed(0))}))})),$(document).on("change","#paymentMethods",(function(){"Cheque"==$("#paymentMethods").val()?$("#hiddenItem").css("display","block"):$("#hiddenItem").css("display","none")})),$(document).off("click","#addSalaryPaymentRow"),$(document).on("click","#addSalaryPaymentRow",(function(){$("#salaryPaymentRow").append('<div class="row"> <div class="col-md-4"> <div class="form-group required"> <select name="paymentsType[]" class="paymentsType form-control" style="width: 100%;" required> <option value="Salary">Salary</option> <option value="Overtime">Overtime</option> <option value="Bonus">Bonus</option> </select> </div> </div> <div class="col-md-3"> <div class="form-group required"> <input type="number" name="paymentAmount[]" class="paymentAmount form-control" required> </div> </div> <div class="col-md-4"> <div class="form-group"> <input type="text" name="salaryPaymentNote[]" class="salaryPaymentNote form-control"> </div> </div> <div class="col-xs-1"> <i style="cursor: pointer; padding: 10px 5px 0 0;" class="fa fa-trash-o removeSalaryPaymentRow"></i> </div> </div>')})),$(document).on("click",".removeSalaryPaymentRow",(function(){$(this).closest(".row").css("background-color","whitesmoke").hide("slow",(function(){$(this).closest(".row").remove()}))})),$(document).on("focusin",".datePicker",(function(){BMS.FUNCTIONS.datePicker()})),$(document).on("focusin",".dateTimePicker",(function(){BMS.FUNCTIONS.datePicker({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".dateRangePicker",(function(){BMS.FUNCTIONS.dateRangePicker()})),$(document).on("focusin",".dateTimeRangePicker",(function(){BMS.FUNCTIONS.dateRangePicker({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".dateRangePickerPreDefined",(function(){BMS.FUNCTIONS.dateRangePickerPreDefined()})),$(document).on("focusin",".dateTimeRangePickerPreDefined",(function(){BMS.FUNCTIONS.dateRangePickerPreDefined({selector:this,format:"YYYY-MM-DD HH:mm",timePicker:!0})})),$(document).on("focusin",".multiDatePicker",(function(){BMS.FUNCTIONS.multiDatePicker()})),$(document).on("change",".imageToUpload",(function(){var e=$(this).closest(".imageContainer").find(".photoErrorMessage");$(e).empty();var t=this.files[0],a=t.type,o=t.size;if(!1===["image/jpeg","image/png","image/jpg"].includes(a))return $(e).length<1?(BMS.fn.alertError("<?php echo __('Please select a valid image file'); ?>"),this.value=this.defaultValue):$(e).html("<div style='margin-bottom: 0;' class='alert alert-danger'><?php echo __('Please select a valid image file'); ?></div>"),!1;if("<?php echo $_SETTINGS['MAX_UPLOAD_SIZE'] * 1024 * 1024; ?>"<o)return $(e).length<1?(BMS.fn.alertError("<?php echo __('Max file size %d MB', $_SETTINGS['MAX_UPLOAD_SIZE']); ?>"),this.value=this.defaultValue):$(e).html("<div class='alert alert-danger'><?php echo __('Max file size %d MB', $_SETTINGS['MAX_UPLOAD_SIZE']); ?></div>"),!1;var n=$(this).val().replace(/\\/g,"/").replace(/.*\//,"");$(this).closest(".imageContainer").find(".imageNameShow").val(n);var s=$(this),r=new FileReader;r.onload=function(e){$(s).css("color","green"),$(s).closest(".imageContainer").find(".image_preview").css("display","block"),$(s).closest(".imageContainer").find(".previewing").attr("src",e.target.result)},r.readAsDataURL(this.files[0])})),$(document).on("click","#addPosSalePaymentRow",(function(){$(".paymentMethodBox").append('<div style="margin: 0;" class="row">\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Amount</label>\n <span style="cursor:pointer; padding: 0 4px;" class="pull-right removePosPaymentItem" ><i class="fa fa-times"></i></span>\n <input type="number" onclick="this.select();" name="posSalePaymentAmount[]" class="form-control posSalePaymentAmount" step="any">\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Reference/Info</label>\n <input type="text" name="posSalePaymentReference[]" class="form-control">\n </div>\n <div style="display: none;" class="posSalePaymentBankAccount form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Bank Account</label>\n <select name="posSalePaymentBankAccount[]" class="form-control pull-left select2Ajax" \n select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=accountList" style="width: 100%;">\n <option value=""><?php echo __("Select Account"); ?>....</option>\n </select>\n </div>\n <div class="form-group pull-right col-md-3 adjustFormGroupPadding">\n <label>Payment Method</label>\n <select name="posSalePaymentMethod[]" class="posSalePaymentMethod form-control">\n <option value="Cash"><?php echo __("Cash"); ?></option>\n <option value="Bank Transfer"><?php echo __("Bank Transfer"); ?></option>\n <option value="Cheque"><?php echo __("Cheque"); ?></option>\n <option value="Card"><?php echo __("Card"); ?></option>\n <option value="Others"><?php echo __("Others"); ?></option>\n </select>\n </div>\n </div>')})),$(document).on("click",".removePosPaymentItem",(function(){$(this).closest(".row").remove(),BMS.POS.grandTotal()})),$(document).on("change",".posSalePaymentMethod",(function(){"Cash"===$(this).val()?$(this).closest(".row").find(".posSalePaymentBankAccount").hide():$(this).closest(".row").find(".posSalePaymentBankAccount").show()})),$(document).on("submit","#modalForm, #popUpForm, #jqFormAdd, #jqFormUpdate",(function(e){e.preventDefault(),ajaxFormSubmit(this)})),$(document).on("submit","#inlineForm",(function(e){e.preventDefault(),ajaxFormSubmit(this,!0)})),$(document).on("click",".deleteEntry",(function(e){e.preventDefault();var t=$(this).attr("href"),a=$(this).attr("data-to-be-deleted"),o=$(this).attr("removeParent"),n=this;Swal.fire({title:"Are you sure to delete this entry?",icon:"warning",didOpen:function(){BMS.fn.play("warning")},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:"Yes, delete it!"}).then((e=>{e.value&&$.post(t,{datatoDelete:a},(function(e,t){if(isJson(e)){var a=JSON.parse(e);for(var s in a)sweetAlert[s]=a[s]}Swal.fire({toast:sweetAlert.toast,position:sweetAlert.position,timer:sweetAlert.timer,showConfirmButton:sweetAlert.showConfirmButton,showCloseButton:sweetAlert.showCloseButton,icon:sweetAlert.icon,title:sweetAlert.title,text:sweetAlert.text,onClose:$("body").css("padding","0px")}),void 0!==o&&$(n).closest(o).hide("fast"),$("#dataTableWithAjax").DataTable().ajax.reload(null,!1),$("#dataTableWithAjaxExtend").DataTable().ajax.reload(null,!1)}))}))})),$(document).on("click",".updateEntry",(function(e){e.preventDefault();var t=$(this).attr("href"),a=$(this).attr("data-to-be-updated");$(this).css("color","black"),$(this).find("i.fa").addClass("fa-spin"),$.post(t,{datatoUpdate:a},(function(e,t){if(isJson(e)){var a=JSON.parse(e);for(var o in a)sweetAlert[o]=a[o]}Swal.fire({toast:sweetAlert.toast,position:sweetAlert.position,timer:sweetAlert.timer,showConfirmButton:sweetAlert.showConfirmButton,showCloseButton:sweetAlert.showCloseButton,icon:sweetAlert.icon,title:sweetAlert.title,text:sweetAlert.text,onClose:$("body").css("padding","0px")}),$("#dataTableWithAjax").DataTable().ajax.reload(null,!1),$("#dataTableWithAjaxExtend").DataTable().ajax.reload(null,!1)}))})),$(document).on("dblclick","iledit",(function(e){e.preventDefault();var t=$(this),a=t.closest("td"),o=t.closest("table").find("th").eq(a.index()),n=t.closest("tr").find("pkey").text(),s=o.attr("type"),r=o.attr("data-source"),l=o.attr("data-options"),i=o.attr("where-to-update"),c=t.attr("data-val"),d=t.text(),u=a.width();if("select2"===s){a.html(`\n <select class="form-control select2InlineEdit" select2-ajax-url="${r}" style="width: ${u}px;" required>\n <option value=""><?php echo __("Select Entry"); ?>....</option>\n </select>\n `);var m=a.find(".select2InlineEdit");BMS.fn.select2(m,c,d),m.select2("open")}else if("select"===s){(l=l.split(",")).forEach((function(e){l+=`<option ${d==e?"selected":""} value='${e}'>${e}</option>`})),a.html(`\n <select class="form-control" style="width: ${u}px; padding: 6px 6px;" required>\n ${l}\n </select>\n `),(m=a.find("select")).select2(),m.select2("open")}else a.html(`\n <input type="text" value="${d}" style="width: ${u}px;" class="form-control">\n `),"datePicker"===s&&(a.find("input").addClass("datePicker"),a.find(".datePicker").focus());a.find("input, select, textarea").on("enter blur clear apply.daterangepicker, select2:close",(function(){var e=["select2","select"].includes(s)?c:d,t=$(this).val(),o=$(this);t!==e?$.post(i,{pkey:n,newData:t},(function(e,t){void 0!==(e=JSON.parse(e)).error&&"true"===e.error?BMS.fn.alertError(e.msg):(BMS.fn.alertSuccess("The data has been successfully updated."),"select2"===s||"select"===s?a.html("<iledit data-val='"+$(o).val()+"'>"+$("option:selected",o).html()+"</iledit>"):a.html("<iledit>"+$(o).val()+"</iledit>"))})):"select2"===s||"select"===s?(console.log($("option:selected",o).html()),a.html("<iledit data-val='"+$(o).val()+"'>"+$("option:selected",o).html()+"</iledit>")):a.html("<iledit>"+$(o).val()+"</iledit>")}))})),$(document).on("hidden.bs.modal",(function(e){$(e.target).removeData("bs.modal").find(".modal-ajax").html("")})),$(document).ready((function(){$(document).on("mouseenter focus",".select2Ajax",(function(){BMS.fn.select2(this)}))})),$(document).ready((function(){$("body").tooltip({selector:'[data-toggle="tooltip"]'})})),$(document).click((function(e){$(".dropdown-menu[data-parent]").hide()})),$(document).on("click",'.col-sm-12 [data-toggle="dropdown"]',(function(){if($("body").hasClass("modal-open"))throw new Error("This solution is not working inside a responsive table inside a modal, you need to find out a way to calculate the modal Z-index and add it to the element");if($buttonGroup=$(this).parent(),$buttonGroup.attr("data-attachedUl"))$ul=$("[data-parent="+$buttonGroup.attr("data-attachedUl")+"]");else{var e=+new Date;$ul=$(this).siblings("ul"),$ul.attr("data-parent",e),$buttonGroup.attr("data-attachedUl",e),$(window).resize((function(){$ul.css("display","none").data("top")}))}var t,a,o;$buttonGroup.hasClass("open")?(t=$(this).parent(),a=$ul,o=t.offset().top+t.outerHeight(),a.css("top",o+"px"),a.css("left",t.offset().left-100+"px"),a.css("position","absolute"),a.css("width",a.width()),a.css("heigt",a.height()),a.css("display","block"),a.appendTo(".dynamic-container")):$ul.css("display","none")})),$(document).on("click",".restricted",(function(){Swal.fire({title:"Sorry!",text:"You have no permission to perform this action",icon:"error"})})),$(".modal").on("show.bs.modal",(function(e){if(-1!==$.inArray("restricted",e.target.classList))return e.preventDefault()})),$(".modal").on("shown.bs.modal",(function(){$(this).find("[autofocus]").focus()})),$("form").on("focus","input[type=number]",(function(e){$(this).on("wheel.disableScroll",(function(e){e.preventDefault()}))})),$("form").on("blur","input[type=number]",(function(e){$(this).off("wheel.disableScroll")}));var sweetAlert=[];sweetAlert.title="The command has been executed successfully.",sweetAlert.text="",sweetAlert.icon="success",sweetAlert.toast=!0,sweetAlert.position="top",sweetAlert.timer=5e3,sweetAlert.showConfirmButton=!1,sweetAlert.showCloseButton=!1,$('input[type="checkbox"].square, input[type="radio"].square').iCheck({checkboxClass:"icheckbox_square-blue",radioClass:"iradio_square-blue"}),$.ajaxSetup({beforeSend:function(e){e.setRequestHeader("X-CSRF-TOKEN",xCsrfToken)}});var getPageTitle=JSON.parse('<?php echo json_encode($_SETTINGS["PAGE_TITLE"]); ?>');$(window).bind("popstate",(function(e){"undefined"!=typeof session&&(session.terminate(),phone.stop()),e.preventDefault(),$.get(location.href+"?contentOnly=true",(function(e,t){defaultiDisplayLength="",$("li").removeClass("active");var a=location.href,o="Not Found!";void 0!==getPageTitle[a]&&(o=getPageTitle[a]),window.document.title=o,$(".dynamic-container").html(e),jQuery.get(full_website_address+"/assets/js/initiator.min.js")}))})),$(document).on("keydown",(function(e){"F2"===e.key&&($("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").hasClass("select2-hidden-accessible")||BMS.fn.select2("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct"),$("#selectProduct, #selectPosProduct, #selectStockTransferProduct, #selectStockEntryProduct").select2("open")),"F3"===e.key&&(e.preventDefault(),$("#orderDiscount").modal("show"))})),$(document).on("click",".toggleNotButton",(function(){var e=$(this).closest("span").find(".notThisValueFilter");"="===$(e).val()?($(e).val("!="),$(this).text("|")):($(this).text(""),$(e).val("="))})),$(document).on("click",".stopPropagation",(function(e){e.stopPropagation()})),$(document).on("change","#productType",(function(){$("#productVariationSection").hide(),$("#bundleProductsContainer").hide(),$(".bundleProduct").hide(),$(".groupedProduct").hide();"Variable"===this.value?$("#productVariationSection").show():"Bundle"===this.value?($(".bundleProduct").show(),$("#bundleProductsContainer").show()):"Grouped"===this.value&&($(".groupedProduct").show(),$("#bundleProductsContainer").show())})),$(document).on("click",".removeThisVariation",(function(e){if(e.stopPropagation(),confirm("Are sure to remove this variation?")){var t=$(this).closest("li").find(".variation_product_id").val();$(this).closest("li").hide("fast",(function(){$(this).remove()})),void 0!==t&&$.ajax({url:full_website_address+"/xhr/?module=products&page=deleteVariationProduct",type:"post",data:{product_id:t},success:function(e,t){}})}})),$(document).on("click","#setVariationPrice",(function(){setVariationPrice()})),$(window).keydown((function(e){if(13==e.keyCode&&$("#productVariationPrice").hasClass("in"))return e.preventDefault(),setVariationPrice(),$("#productVariationPrice").modal("hide"),!1})),$("#browseProduct").on("show.bs.modal",(function(e){BMS.PRODUCT.showProduct()})),$(document).on("change","#productHasExpiryDate",(function(){"1"===this.value?$(".productIntitalStock").prop("disabled",!0):$(".productIntitalStock").prop("disabled",!1)}));let barCcode="";$(document).on("keypress",(e=>{if("Enter"===e.key){var t="input"!==e.target.tagName.toLowerCase();""!==barCcode&&(isPosPage&&t?BMS.POS.addProduct(barCcode,!0):isPurchasePage&&t?BMS.PURCHASE.addProduct(barCcode,!0):isTransferStockPage&&t?BMS.STOCK_TRANSFER.addProduct(barCcode,!0):isProductReturnPage&&t?BMS.RETURN.addProduct(barCcode,!0):isStockEntryPage&&t?BMS.STOCK_ENTRY.addProduct(barCcode,!0):isAddProductPage&&$("#productCode").val(barCcode)),barCcode=""}else barCcode+=e.key})),$(document).on("click",".copyThis",(function(e){navigator.clipboard.writeText($(this).text())}));
\ No newline at end of file

programming_language: JavaScript
filename: ajax_data.php
change_type: ModificationType.MODIFY
diff: @@ -777,7 +777,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getEmpSalaryData") {
                 loan_ids, sum(loan_installment_paying_amount) as loan_installment_paid_amount 
             from {$table_prefix}loan_installment where is_trash = 0 group by loan_ids
         ) as loan_installment on loan_id = loan_ids
-        where emp_id = {$emp_id}
+        where emp_id = '{$emp_id}'
         order by loan_id 
         desc limit 1"
     )["data"][0];
@@ -824,7 +824,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getCustomerPaymentInfo") {
                 sum(payments_return_amount) as payments_return_amount
             from {$table_prefix}payments_return where is_trash = 0 and payments_return_type = 'Outgoing' group by payments_return_customer_id
         ) as payment_return on customer_id = payments_return_customer_id
-        where customer_id = {$customer_id}"
+        where customer_id = '{$customer_id}'"
     )["data"][0];
 
     echo json_encode($customerPaymentsData);
@@ -896,7 +896,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getCustomerStatementInfo") {
             where is_trash = 0 and payments_return_type = 'Outgoing' and date(payments_return_date) between '{$dateRange[0]}' and '{$dateRange[1]}' 
             group by payments_return_customer_id
         ) as payment_return on customer_id = payments_return_customer_id
-        where customer_id = {$customer_id}"
+        where customer_id = '{$customer_id}'"
     )["data"][0];
 
     $customerPaymentsData["previous_balance"] = easySelectD("
@@ -935,7 +935,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getCustomerStatementInfo") {
                 where is_trash = 0 and payments_return_type = 'Outgoing' and date(payments_return_date) < '{$dateRange[0]}'
                 group by payments_return_customer_id
             ) as payment_return on customer_id = payments_return_customer_id
-			where customer_id = {$customer_id}
+			where customer_id = '{$customer_id}'
 	")["data"][0]["previous_balance"];
 
     echo json_encode($customerPaymentsData);
@@ -962,18 +962,18 @@ if(isset($_GET['page']) and $_GET['page'] == "getEmpLoanLoanData") {
         left join (select 
                 loan_ids, 
                 1 as thisMonthInstallmentPayingStatus
-            from {$table_prefix}loan_installment where is_trash = 0 and MONTH(loan_installment_date) = {$month} and year(loan_installment_date) = {$year} group by loan_ids 
+            from {$table_prefix}loan_installment where is_trash = 0 and MONTH(loan_installment_date) = '{$month}' and year(loan_installment_date) = '{$year}' group by loan_ids 
         ) as thisMonthStatus on loan_id = thisMonthStatus.loan_ids
-        where loan.is_trash = 0 and loan_borrower = {$emp_id} and loan_installment_starting_from <= '{$year}-{$month}-01'
+        where loan.is_trash = 0 and loan_borrower = '{$emp_id}' and loan_installment_starting_from <= '{$year}-{$month}-01'
         and ( loan_paid_amount is null or loan_paid_amount < loan_amount)" 
         // loan_paid_amount can be NULL on left join if there is no recrods, for that the is null check.
-        // We can also use HAVING cluese without using is null check. But it will raise a error with full_group_by mode.
+        // We can also use HAVING clause without using is null check. But it will raise a error with full_group_by mode.
     );
 
     $selectSalary = easySelectA(array(
         "table"     => "employees",
         "fields"    => "round(emp_salary, 2) as emp_salary",
-        "where"     => array("emp_id = {$emp_id}")
+        "where"     => array("emp_id = '{$emp_id}'")
     ))["data"][0]["emp_salary"];
 
     if(!isset($getLoanDetails["data"])) {
@@ -1042,7 +1042,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getEmployeeAdvancePaymentsData") {
                 sum(payments_return_amount) as payments_return_amount_sum 
             from {$table_prefix}payments_return where is_trash = 0 group by payments_return_emp_id 
         ) as get_advance_return on payments_return_emp_id = emp_id
-        where emp_id = {$emp_id}"
+        where emp_id = '{$emp_id}'"
     )["data"][0];
     
     echo json_encode($getEmpAdvancePaymentData);
@@ -1089,7 +1089,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getCompanyDueBillDetails") {
                 sum(CASE WHEN is_return = 1 then purchase_due end) as purchase_return_grand_total
             from {$table_prefix}purchases where is_trash = 0 group by purchase_company_id
         ) as purchaseBill on purchaseBill.purchase_company_id = company_id
-        where company_id = {$company_id}"
+        where company_id = '{$company_id}'"
     )["data"][0];
     
     echo json_encode($getEmpAdvancePaymentData);
@@ -1369,7 +1369,7 @@ if(isset($_GET['page']) and $_GET['page'] == "getAccountsInfo") {
 
 if(isset($_GET['page']) and $_GET['page'] == "customerPurchaseList") {
 
-    $invoiceSearch = ( isset($_GET["s"]) and !empty($_GET["s"]) ) ? "and sales_reference like '%{$_GET["s"]}%'" : "";
+    $invoiceSearch = ( isset($_GET["s"]) and !empty($_GET["s"]) ) ? "and sales_reference like '%". safe_input($_GET["s"]) ."%'" : "";
 
     $selectSales = easySelectA(array(
         "table"     => "sales",
@@ -1542,10 +1542,10 @@ if(isset($_GET['page']) and $_GET['page'] == "productVisualList") {
 
     $productCategoryFilter = ( isset($_GET["catId"]) and !empty($_GET["catId"]) ) ? $_GET["catId"] : "";
     $productBrandFilter = ( isset($_GET["brand"]) and !empty($_GET["brand"]) ) ? $_GET["brand"] : "";
-    $productEditionFilter = ( isset($_GET["edition"]) and !empty($_GET["edition"]) ) ? " AND product.product_edition = '{$_GET["edition"]}'" : " AND product_type != 'Child' ";
+    $productEditionFilter = ( isset($_GET["edition"]) and !empty($_GET["edition"]) ) ? " AND product.product_edition = '". safe_input($_GET["edition"]) ."'" : " AND product_type != 'Child' ";
     $productGenericFilter = ( isset($_GET["generic"]) and !empty($_GET["generic"]) ) ? $_GET["generic"] : "";
     $productAuthorFilter = ( isset($_GET["author"]) and !empty($_GET["author"]) ) ? $_GET["author"] : "";
-    $productTerms = ( isset($_GET["terms"]) and !empty($_GET["terms"]) ) ? " AND product_name like '%{$_GET["terms"]}%'" : "";
+    $productTerms = ( isset($_GET["terms"]) and !empty($_GET["terms"]) ) ? " AND product_name like '%". safe_input($_GET["terms"]) ."%'" : "";
     $productSort = ( isset($_GET["sort"]) and !empty($_GET["sort"]) ) ? $_GET["sort"] : "";
 
     $oderBy = array(
@@ -1692,7 +1692,7 @@ if(isset($_GET['page']) and $_GET['page'] == "productVisualList") {
 if(isset($_GET['page']) and $_GET['page'] == "getChildProductData") {
 
 
-    $warehouse_filter = empty($_GET["wid"]) ? "" : " = " . safe_input($_GET["wid"]);
+    $warehouse_filter = empty($_GET["wid"]) ? "" : " = '" . safe_input($_GET["wid"]) . "'";
 
     $getChildProductData = easySelectA(array(
         "table"     => "products as product",

programming_language: SQL
filename: ajax_select2.php
change_type: ModificationType.MODIFY
diff: @@ -1014,7 +1014,8 @@ if(isset($_GET['page']) and $_GET['page'] == "batchList") {
         "table"   => "product_batches",
         "fields"  => "batch_id, batch_number",
         "where"   => array(
-            "is_trash = 0 and date(batch_expiry_date) >= curdate() and batch_number LIKE '". $search ."%'",
+            "is_trash = 0 and date(batch_expiry_date) >= curdate()",
+            " and batch_number LIKE " => "{$search}%",
             " and product_id"   => $product_id
         ),
         "limit"   => array (

programming_language: PHP
filename: functions.php
change_type: ModificationType.MODIFY
diff: @@ -1565,6 +1565,16 @@ function easyUpload(
             );
 
         } else {
+
+            // Remove path traversal characters
+            $location = str_replace(
+                array(
+                    "./",
+                    "../"
+                ),
+                "",
+                $location
+            );
             
             $uploadDir = DIR_UPLOAD . $location;
 

programming_language: PHP
filename: route.php
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,6 @@
 <?php
 
-// Remove directory browsing elements
+// Remove path traversal characters
 $pageSlug = str_replace(
     array(
         "./",

programming_language: PHP
filename: index.php
change_type: ModificationType.MODIFY
diff: @@ -12,9 +12,23 @@ if(is_login() !== true) {
 */
 
 if(isset($_GET['module'])) {
+
+    $module = $_GET['module'];
+
+    // Remove directory browsing elements
+    $module = str_replace(
+        array(
+            "./",
+            "../",
+            ".",
+            ".."
+        ),
+        "",
+        $module
+    );
     
-    // Biuld the page location
-    $ajaxModulePage = DIR_MODULE . $_GET['module'] . "/ajax.php";
+    // Build the page location
+    $ajaxModulePage = DIR_MODULE . $module . "/ajax.php";
 
     // Check if the ajax page is exists
     if(file_exists($ajaxModulePage)) {

programming_language: PHP
filename: info.php
change_type: ModificationType.MODIFY
diff: @@ -12,9 +12,23 @@ if(is_login() !== true) {
 
 
 if(isset($_GET['module'])) {
+
+    $module = $_GET['module'];
+
+    // Remove directory browsing elements
+    $module = str_replace(
+        array(
+            "./",
+            "../",
+            ".",
+            ".."
+        ),
+        "",
+        $module
+    );
     
     // Biuld the page location
-    $ajaxModulePage = DIR_BASE . "core/ajax/ajax_" . $_GET['module'] . ".php";
+    $ajaxModulePage = DIR_BASE . "core/ajax/ajax_" . $module . ".php";
 
     // Check if the ajax page is exists
     if(file_exists($ajaxModulePage)) {

programming_language: PHP
filename: composer.lock
change_type: ModificationType.ADD
diff: @@ -0,0 +1,1443 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "f700817e1354843cb08388babe276094",
+    "packages": [
+        {
+            "name": "cboden/ratchet",
+            "version": "v0.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ratchetphp/Ratchet.git",
+                "reference": "5012dc954541b40c5599d286fd40653f5716a38f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ratchetphp/Ratchet/zipball/5012dc954541b40c5599d286fd40653f5716a38f",
+                "reference": "5012dc954541b40c5599d286fd40653f5716a38f",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/psr7": "^1.7|^2.0",
+                "php": ">=5.4.2",
+                "ratchet/rfc6455": "^0.3.1",
+                "react/event-loop": ">=0.4",
+                "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5",
+                "symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0|^6.0",
+                "symfony/routing": "^2.6|^3.0|^4.0|^5.0|^6.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.8"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Ratchet\\": "src/Ratchet"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Matt Bonneau",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHP WebSocket library",
+            "homepage": "http://socketo.me",
+            "keywords": [
+                "Ratchet",
+                "WebSockets",
+                "server",
+                "sockets",
+                "websocket"
+            ],
+            "support": {
+                "chat": "https://gitter.im/reactphp/reactphp",
+                "issues": "https://github.com/ratchetphp/Ratchet/issues",
+                "source": "https://github.com/ratchetphp/Ratchet/tree/v0.4.4"
+            },
+            "time": "2021-12-14T00:20:41+00:00"
+        },
+        {
+            "name": "evenement/evenement",
+            "version": "v3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/igorw/evenement.git",
+                "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
+                "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Evenement": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Igor Wiedler",
+                    "email": "igor@wiedler.ch"
+                }
+            ],
+            "description": "Événement is a very simple event dispatching library for PHP",
+            "keywords": [
+                "event-dispatcher",
+                "event-emitter"
+            ],
+            "support": {
+                "issues": "https://github.com/igorw/evenement/issues",
+                "source": "https://github.com/igorw/evenement/tree/master"
+            },
+            "time": "2017-07-23T21:35:13+00:00"
+        },
+        {
+            "name": "guzzlehttp/psr7",
+            "version": "2.4.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/psr7.git",
+                "reference": "67c26b443f348a51926030c83481b85718457d3d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
+                "reference": "67c26b443f348a51926030c83481b85718457d3d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.0",
+                "ralouphie/getallheaders": "^3.0"
+            },
+            "provide": {
+                "psr/http-factory-implementation": "1.0",
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.1",
+                "http-interop/http-factory-tests": "^0.9",
+                "phpunit/phpunit": "^8.5.29 || ^9.5.23"
+            },
+            "suggest": {
+                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "2.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Psr7\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://sagikazarmark.hu"
+                }
+            ],
+            "description": "PSR-7 message implementation that also provides common utility methods",
+            "keywords": [
+                "http",
+                "message",
+                "psr-7",
+                "request",
+                "response",
+                "stream",
+                "uri",
+                "url"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/psr7/issues",
+                "source": "https://github.com/guzzle/psr7/tree/2.4.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-10-26T14:07:24+00:00"
+        },
+        {
+            "name": "marcelog/pami",
+            "version": "v2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/marcelog/PAMI.git",
+                "reference": "f586d0fcbf7db7952965ccb91e4ed231bd168fb3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/marcelog/PAMI/zipball/f586d0fcbf7db7952965ccb91e4ed231bd168fb3",
+                "reference": "f586d0fcbf7db7952965ccb91e4ed231bd168fb3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "psr/log": ">= 1.0.0"
+            },
+            "require-dev": {
+                "codeclimate/php-test-reporter": "dev-master",
+                "evert/phpdoc-md": "~0.1.1",
+                "marcelog/pagi": "2.*",
+                "monolog/monolog": "1.*",
+                "phing/phing": "2.*",
+                "phpdocumentor/phpdocumentor": "2.*",
+                "phpmd/phpmd": "2.*",
+                "phpunit/phpunit": "4.*",
+                "satooshi/php-coveralls": "1.0.1",
+                "sebastian/phpcpd": "*",
+                "squizlabs/php_codesniffer": "2.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PAMI\\": "src/PAMI"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache2"
+            ],
+            "authors": [
+                {
+                    "name": "Marcelo Gornstein",
+                    "email": "marcelog@gmail.com",
+                    "homepage": "http://marcelog.github.com/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Asterisk Manager Interface (AMI) client for PHP, event driven, object oriented",
+            "homepage": "http://marcelog.github.com/PAMI",
+            "keywords": [
+                "action",
+                "ami",
+                "asterisk",
+                "client",
+                "event",
+                "manager",
+                "monitor",
+                "telephony",
+                "voip"
+            ],
+            "support": {
+                "issues": "https://github.com/marcelog/PAMI/issues",
+                "source": "https://github.com/marcelog/PAMI/tree/v2.0.2"
+            },
+            "time": "2017-10-10T18:59:17+00:00"
+        },
+        {
+            "name": "psr/http-factory",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-factory.git",
+                "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
+                "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0.0",
+                "psr/http-message": "^1.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interfaces for PSR-7 HTTP message factories",
+            "keywords": [
+                "factory",
+                "http",
+                "message",
+                "psr",
+                "psr-17",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-factory/tree/master"
+            },
+            "time": "2019-04-30T12:38:16+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-message.git",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-message/tree/master"
+            },
+            "time": "2016-08-06T14:39:51+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+                "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/log/tree/3.0.0"
+            },
+            "time": "2021-07-14T16:46:02+00:00"
+        },
+        {
+            "name": "ralouphie/getallheaders",
+            "version": "3.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ralouphie/getallheaders.git",
+                "reference": "120b605dfeb996808c31b6477290a714d356e822"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+                "reference": "120b605dfeb996808c31b6477290a714d356e822",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpunit": "^5 || ^6.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/getallheaders.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ralph Khattar",
+                    "email": "ralph.khattar@gmail.com"
+                }
+            ],
+            "description": "A polyfill for getallheaders.",
+            "support": {
+                "issues": "https://github.com/ralouphie/getallheaders/issues",
+                "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+            },
+            "time": "2019-03-08T08:55:37+00:00"
+        },
+        {
+            "name": "ratchet/rfc6455",
+            "version": "v0.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ratchetphp/RFC6455.git",
+                "reference": "7c964514e93456a52a99a20fcfa0de242a43ccdb"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/7c964514e93456a52a99a20fcfa0de242a43ccdb",
+                "reference": "7c964514e93456a52a99a20fcfa0de242a43ccdb",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/psr7": "^2 || ^1.7",
+                "php": ">=5.4.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7",
+                "react/socket": "^1.3"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Ratchet\\RFC6455\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Matt Bonneau",
+                    "role": "Developer"
+                }
+            ],
+            "description": "RFC6455 WebSocket protocol handler",
+            "homepage": "http://socketo.me",
+            "keywords": [
+                "WebSockets",
+                "rfc6455",
+                "websocket"
+            ],
+            "support": {
+                "chat": "https://gitter.im/reactphp/reactphp",
+                "issues": "https://github.com/ratchetphp/RFC6455/issues",
+                "source": "https://github.com/ratchetphp/RFC6455/tree/v0.3.1"
+            },
+            "time": "2021-12-09T23:20:49+00:00"
+        },
+        {
+            "name": "react/cache",
+            "version": "v1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/cache.git",
+                "reference": "d47c472b64aa5608225f47965a484b75c7817d5b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b",
+                "reference": "d47c472b64aa5608225f47965a484b75c7817d5b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "react/promise": "^3.0 || ^2.0 || ^1.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "React\\Cache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "Async, Promise-based cache interface for ReactPHP",
+            "keywords": [
+                "cache",
+                "caching",
+                "promise",
+                "reactphp"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/cache/issues",
+                "source": "https://github.com/reactphp/cache/tree/v1.2.0"
+            },
+            "funding": [
+                {
+                    "url": "https://opencollective.com/reactphp",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2022-11-30T15:59:55+00:00"
+        },
+        {
+            "name": "react/dns",
+            "version": "v1.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/dns.git",
+                "reference": "a5427e7dfa47713e438016905605819d101f238c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/dns/zipball/a5427e7dfa47713e438016905605819d101f238c",
+                "reference": "a5427e7dfa47713e438016905605819d101f238c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "react/cache": "^1.0 || ^0.6 || ^0.5",
+                "react/event-loop": "^1.2",
+                "react/promise": "^3.0 || ^2.7 || ^1.2.1",
+                "react/promise-timer": "^1.9"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.3 || ^4.8.35",
+                "react/async": "^4 || ^3 || ^2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "React\\Dns\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "Async DNS resolver for ReactPHP",
+            "keywords": [
+                "async",
+                "dns",
+                "dns-resolver",
+                "reactphp"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/dns/issues",
+                "source": "https://github.com/reactphp/dns/tree/v1.10.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-09-08T12:22:46+00:00"
+        },
+        {
+            "name": "react/event-loop",
+            "version": "v1.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/event-loop.git",
+                "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/event-loop/zipball/187fb56f46d424afb6ec4ad089269c72eec2e137",
+                "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35"
+            },
+            "suggest": {
+                "ext-event": "~1.0 for ExtEventLoop",
+                "ext-pcntl": "For signal handling support when using the StreamSelectLoop",
+                "ext-uv": "* for ExtUvLoop"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "React\\EventLoop\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.",
+            "keywords": [
+                "asynchronous",
+                "event-loop"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/event-loop/issues",
+                "source": "https://github.com/reactphp/event-loop/tree/v1.3.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-03-17T11:10:22+00:00"
+        },
+        {
+            "name": "react/promise",
+            "version": "v2.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/promise.git",
+                "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910",
+                "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "React\\Promise\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+            "keywords": [
+                "promise",
+                "promises"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/promise/issues",
+                "source": "https://github.com/reactphp/promise/tree/v2.9.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-02-11T10:27:51+00:00"
+        },
+        {
+            "name": "react/promise-timer",
+            "version": "v1.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/promise-timer.git",
+                "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/aa7a73c74b8d8c0f622f5982ff7b0351bc29e495",
+                "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3",
+                "react/event-loop": "^1.2",
+                "react/promise": "^3.0 || ^2.7.0 || ^1.2.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "React\\Promise\\Timer\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.",
+            "homepage": "https://github.com/reactphp/promise-timer",
+            "keywords": [
+                "async",
+                "event-loop",
+                "promise",
+                "reactphp",
+                "timeout",
+                "timer"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/promise-timer/issues",
+                "source": "https://github.com/reactphp/promise-timer/tree/v1.9.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-06-13T13:41:03+00:00"
+        },
+        {
+            "name": "react/socket",
+            "version": "v1.12.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/socket.git",
+                "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/socket/zipball/81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b",
+                "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b",
+                "shasum": ""
+            },
+            "require": {
+                "evenement/evenement": "^3.0 || ^2.0 || ^1.0",
+                "php": ">=5.3.0",
+                "react/dns": "^1.8",
+                "react/event-loop": "^1.2",
+                "react/promise": "^3 || ^2.6 || ^1.2.1",
+                "react/promise-timer": "^1.9",
+                "react/stream": "^1.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35",
+                "react/async": "^4 || ^3 || ^2",
+                "react/promise-stream": "^1.4"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "React\\Socket\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP",
+            "keywords": [
+                "Connection",
+                "Socket",
+                "async",
+                "reactphp",
+                "stream"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/socket/issues",
+                "source": "https://github.com/reactphp/socket/tree/v1.12.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-08-25T12:32:25+00:00"
+        },
+        {
+            "name": "react/stream",
+            "version": "v1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/stream.git",
+                "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/stream/zipball/7a423506ee1903e89f1e08ec5f0ed430ff784ae9",
+                "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9",
+                "shasum": ""
+            },
+            "require": {
+                "evenement/evenement": "^3.0 || ^2.0 || ^1.0",
+                "php": ">=5.3.8",
+                "react/event-loop": "^1.2"
+            },
+            "require-dev": {
+                "clue/stream-filter": "~1.2",
+                "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "React\\Stream\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Lück",
+                    "email": "christian@clue.engineering",
+                    "homepage": "https://clue.engineering/"
+                },
+                {
+                    "name": "Cees-Jan Kiewiet",
+                    "email": "reactphp@ceesjankiewiet.nl",
+                    "homepage": "https://wyrihaximus.net/"
+                },
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@gmail.com",
+                    "homepage": "https://sorgalla.com/"
+                },
+                {
+                    "name": "Chris Boden",
+                    "email": "cboden@gmail.com",
+                    "homepage": "https://cboden.dev/"
+                }
+            ],
+            "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP",
+            "keywords": [
+                "event-driven",
+                "io",
+                "non-blocking",
+                "pipe",
+                "reactphp",
+                "readable",
+                "stream",
+                "writable"
+            ],
+            "support": {
+                "issues": "https://github.com/reactphp/stream/issues",
+                "source": "https://github.com/reactphp/stream/tree/v1.2.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/WyriHaximus",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/clue",
+                    "type": "github"
+                }
+            ],
+            "time": "2021-07-11T12:37:55+00:00"
+        },
+        {
+            "name": "symfony/deprecation-contracts",
+            "version": "v3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/deprecation-contracts.git",
+                "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
+                "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "3.0-dev"
+                },
+                "thanks": {
+                    "name": "symfony/contracts",
+                    "url": "https://github.com/symfony/contracts"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "function.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "A generic function and convention to trigger deprecation notices",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-01-02T09:55:41+00:00"
+        },
+        {
+            "name": "symfony/http-foundation",
+            "version": "v6.0.17",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/http-foundation.git",
+                "reference": "22fe17e40b0481d39212e7165e004eb26422085d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/22fe17e40b0481d39212e7165e004eb26422085d",
+                "reference": "22fe17e40b0481d39212e7165e004eb26422085d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.2",
+                "symfony/deprecation-contracts": "^2.1|^3",
+                "symfony/polyfill-mbstring": "~1.1"
+            },
+            "require-dev": {
+                "predis/predis": "~1.0",
+                "symfony/cache": "^5.4|^6.0",
+                "symfony/dependency-injection": "^5.4|^6.0",
+                "symfony/expression-language": "^5.4|^6.0",
+                "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
+                "symfony/mime": "^5.4|^6.0",
+                "symfony/rate-limiter": "^5.2|^6.0"
+            },
+            "suggest": {
+                "symfony/mime": "To use the file extension guesser"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\HttpFoundation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Defines an object-oriented layer for the HTTP specification",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/http-foundation/tree/v6.0.17"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-12-14T15:52:41+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.27.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+                "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "provide": {
+                "ext-mbstring": "*"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.27-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-11-03T14:55:06+00:00"
+        },
+        {
+            "name": "symfony/routing",
+            "version": "v6.0.17",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/routing.git",
+                "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/routing/zipball/61687a0aa80f6807c52e116ee64072f6ec53780c",
+                "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.2"
+            },
+            "conflict": {
+                "doctrine/annotations": "<1.12",
+                "symfony/config": "<5.4",
+                "symfony/dependency-injection": "<5.4",
+                "symfony/yaml": "<5.4"
+            },
+            "require-dev": {
+                "doctrine/annotations": "^1.12|^2",
+                "psr/log": "^1|^2|^3",
+                "symfony/config": "^5.4|^6.0",
+                "symfony/dependency-injection": "^5.4|^6.0",
+                "symfony/expression-language": "^5.4|^6.0",
+                "symfony/http-foundation": "^5.4|^6.0",
+                "symfony/yaml": "^5.4|^6.0"
+            },
+            "suggest": {
+                "symfony/config": "For using the all-in-one router or any loader",
+                "symfony/expression-language": "For using expression matching",
+                "symfony/http-foundation": "For using a Symfony Request object",
+                "symfony/yaml": "For using the YAML loader"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Routing\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Maps an HTTP request to a set of configuration variables",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "router",
+                "routing",
+                "uri",
+                "url"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/routing/tree/v6.0.17"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-12-20T16:40:04+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": [],
+    "plugin-api-version": "2.3.0"
+}

programming_language: Jupyter Notebook
filename: ajax.php
change_type: ModificationType.MODIFY
diff: @@ -1525,6 +1525,11 @@ if(isset($_GET['page']) and $_GET['page'] == "payableReport") {
     }
 
 
+    $orderby = "ASC";
+    if($requestData['order'][0]['dir'] === "DESC") {
+        $orderby = "DESC";
+    }
+
          
     $getData = easySelectD(
         "select 
@@ -1558,8 +1563,8 @@ if(isset($_GET['page']) and $_GET['page'] == "payableReport") {
         ) as payment_adjustment on pa_company = company_id
 
         where company.is_trash = 0 and company_name like '{$search}%'
-        group by company_id order by company_name ". safe_input($requestData['order'][0]['dir']) ."
-        LIMIT ". safe_input($requestData['start']) .", ". safe_input($requestData['length']) ."
+        group by company_id order by company_name {$orderby}
+        LIMIT ". intval(safe_input($requestData['start'])) .", ". intval(safe_input($requestData['length'])) ."
         "
     );
 

programming_language: PHP
filename: ajax.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,3133 @@
+<?php
+
+/*************************** Representative List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "representativeList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "abs(emp_PIN)",
+        "emp_photo",
+        "emp_firstname",
+        "emp_working_area",
+        "emp_contact_number"
+    );
+    
+    // Count Total recrods
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "employees",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0 and emp_department_id = 2"
+        )
+    ))["data"][0]["totalRow"];
+
+    if($requestData['length'] == -1) {
+      $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+        
+        $getData = easySelect(
+            "employees as employee",
+            "emp_id, emp_PIN, emp_firstname, emp_lastname, emp_positions, emp_working_area, emp_contact_number, emp_emergency_contact_number, emp_photo",
+            array(),
+            array (
+                "employee.is_trash = 0 and emp_department_id = 2 and (emp_PIN = '". safe_input($requestData['search']['value']) ."' ",
+                " OR emp_firstname LIKE" => $requestData['search']['value'] . "%",
+                " OR emp_lastname LIKE" => $requestData['search']['value'] . "%",
+                " OR emp_positions LIKE" => $requestData['search']['value'] . "%",
+                " OR emp_working_area LIKE" => $requestData['search']['value'] . "%",
+                " OR emp_contact_number LIKE" => $requestData['search']['value'] . "%",
+                ")"
+            ),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+        $getData = easySelect(
+            "employees as employee",
+            "emp_id, emp_PIN, emp_firstname, emp_lastname, emp_positions, emp_working_area, emp_contact_number, emp_emergency_contact_number, emp_photo",
+            array(),
+            array("employee.is_trash = 0 and emp_department_id = 2"),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if(isset($getData['count']) and $getData['count'] > 0) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = $value["emp_PIN"];
+            $allNestedData[] = empty($value['emp_photo']) ? "<img width='60px' height='60px' src='".full_website_address()."/assets/images/defaultUserPic.png' class='img-circle'/>" : "<img width='60px' height='60px' src='".full_website_address()."/images/?for=employees&id={$value['emp_id']}&q=YTozOntzOjI6Iml3IjtpOjE4MDtzOjI6ImloIjtpOjE4MDtzOjI6ImlxIjtpOjcwO30=&v=". strlen($value['emp_photo']) ."' class='img-circle'/>";
+            $allNestedData[] = "<strong>{$value["emp_firstname"]} {$value["emp_lastname"]},</strong><br/> {$value["emp_positions"]}";
+            $allNestedData[] = $value["emp_working_area"];
+            $allNestedData[] = $value["emp_contact_number"];
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/*************************** Product List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "productList") {
+    
+    $requestData = $_REQUEST;
+  
+    $getData = [];
+  
+    // List of all columns name
+    $columns = array(
+        "",
+        "product_name",
+        "product_edition",
+        "category_name",
+        "product_sale_price",
+        "product_description"
+    );
+    
+    // Count Total recrods
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+          "table" => "products",
+          "fields" => "count(*) as totalRow",
+          "where" => array(
+              "is_trash = 0 and product_type != 'Child'"
+          )
+      ))["data"][0]["totalRow"];
+  
+    if($requestData['length'] == -1) {
+      $requestData['length'] = $totalRecords;
+    }
+  
+    if(!empty($requestData["search"]["value"]) or !empty($requestData["columns"][2]['search']['value']) or !empty($requestData["columns"][3]['search']['value'])) {  // get data with search
+        
+        $getData = easySelect(
+          "products as product",
+          "product_name, product_description, round(product_sale_price, 2) as product_sale_price, category_name, product_edition",
+          array (
+            "left join {$table_prefix}product_category on product_category_id = category_id"
+          ),
+            array (
+                "product.is_trash = 0 and (product_name LIKE '". safe_input($requestData['search']['value']) ."%' ",
+                " OR category_name LIKE" => $requestData['search']['value'] . "%",
+                ")",
+                " AND product_category_id" => $requestData["columns"][3]['search']['value'],
+                " AND product_edition" => $requestData["columns"][2]['search']['value']
+            ),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+  
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+  
+    } else { // Get data withouth search
+  
+        $getData = easySelect(
+            "products as product",
+            "product_name, product_description, round(product_sale_price, 2) as product_sale_price, category_name, product_edition",
+            array (
+              "left join {$table_prefix}product_category on product_category_id = category_id"
+            ),
+            array("product.is_trash = 0 and product_type != 'Child'"),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+  
+    }
+  
+    $allData = [];
+    // Check if there have more then zero data
+    if(isset($getData['count']) and $getData['count'] > 0) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = $value["product_name"] . "<br/> <b>Price: </b>" . $value["product_sale_price"];
+            $allNestedData[] = $value["product_edition"];
+            $allNestedData[] = $value["category_name"];
+            $allNestedData[] = $value["product_description"];
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+  
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+  
+}
+
+
+/*************************** getCallerDetails ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "getCallerDetails") {
+
+    $caller = str_replace("+88", "",  safe_input($_POST["caller"]) );
+
+    $callerData = easySelectD("
+        SELECT
+            person_full_name as name,
+            person_type as type,
+            person_address as address,
+            concat(person_designation, ', ', institute_name) as designation
+        FROM {$table_prefix}persons 
+        left join {$table_prefix}institute on institute_id = person_institute
+        WHERE person_phone like '%{$caller}'
+        UNION ALL
+        SELECT
+            customer_name as name,
+            'Library/ Customer' as type,
+            customer_address as address,
+            customer_type as designation
+        FROM {$table_prefix}customers
+        WHERE customer_phone like '%{$caller}'
+        UNION ALL
+        SELECT
+            concat(emp_firstname, ' ', emp_lastname) as name,
+            'Internal Employees' as type,
+            emp_present_address as address,
+            emp_positions as designation
+        FROM {$table_prefix}employees
+        WHERE emp_contact_number like '%{$caller}'
+    ");
+
+    // Get the last call datetime
+    $lastCall = easySelectA(array(
+        "table"     => "calls",
+        "fields"    => "call_datetime as lastCall, concat(emp_firstname, ' ', emp_lastname) as agent_name, call_status, ( select count(call_id) from {$table_prefix}calls where client_identity like '%{$caller}' ) as callCount ",
+        "join"      => array(
+            "left join {$table_prefix}users on representative = user_id",
+            "left join {$table_prefix}employees on user_emp_id = emp_id",
+        ),
+        "where"     => array(
+            "client_identity like '%{$caller}'"
+        ),
+        "orderby"   => array(
+            "call_id" => "DESC"
+        ),
+        "limit"     => array(
+            "start"     => 0,
+            "length"    => 1,
+        )
+    ));
+
+
+    $callerDetails = array(
+        "details"       => array(),
+        "lastCallTime"      => "",
+        "totalCallCount"    => 0,
+        "agentName"         => "",
+        "call_status"       => ""
+    );
+
+    if($lastCall !== false) {
+        $callerDetails["lastCallTime"] = $lastCall["data"][0]["lastCall"];
+        $callerDetails["call_status"] = $lastCall["data"][0]["call_status"];
+        $callerDetails["agentName"] = $lastCall["data"][0]["agent_name"];
+        $callerDetails["totalCallCount"] = $lastCall["data"][0]["callCount"];
+    }
+
+
+    if($callerData !== false) {
+  
+        $callerDetails["details"] = $callerData["data"][0];
+
+    } 
+
+    echo json_encode($callerDetails);
+
+}
+
+
+/*************************** getCallerDetails ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "getCallerAllDetails") {
+
+    $caller = str_replace("+88", "",  safe_input($_POST["caller"]) );
+
+    $callerData = easySelectD("
+        SELECT
+            person_id as id,
+            1 as has_sc,
+            '/xhr/?icheck=false&module=marketing&page=editPerson&id=' as editUri,
+            person_full_name as name,
+            person_type as type,
+            CONCAT( COALESCE(person_address, ''), ', ', COALESCE(upazila_name, ''), ', ', COALESCE(district_name, ''), ', ', COALESCE(division_name, '') ) as address,
+            concat( if(person_designation is null, '', person_designation) , ', ', if(institute_name is null, '', institute_name) ) as designation
+        FROM {$table_prefix}persons 
+        left join {$table_prefix}institute on institute_id = person_institute
+        left join {$table_prefix}districts on district_id = person_district
+        left join {$table_prefix}divisions on division_id = person_division
+        left join {$table_prefix}upazilas on upazila_id = person_upazila
+        WHERE person_phone like '%{$caller}'
+        UNION ALL
+        SELECT
+            customer_id as id,
+            0 as has_sc,
+            '/xhr/?icheck=false&module=peoples&page=editCustomer&id=' as editUri,
+            customer_name as name,
+            'Library/ Customer' as type,
+            customer_address as address,
+            customer_type as designation
+        FROM {$table_prefix}customers
+        WHERE customer_phone like '%{$caller}'
+        UNION ALL
+        SELECT
+            emp_id as id,
+            0 as has_sc,
+            '/xhr/?icheck=true&module=peoples&page=editEmployee&id=' as editUri,
+            concat(emp_firstname, ' ', emp_lastname) as name,
+            'Internal Employees' as type,
+            emp_present_address as address,
+            emp_positions as designation
+        FROM {$table_prefix}employees
+        WHERE emp_contact_number like '%{$caller}'
+    ");
+
+    // Get Call History
+    $getCallHistory = easySelectA(array(
+        "table"     => "calls",
+        "fields"    => "call_datetime, concat(emp_firstname, ' ', emp_lastname) as agent_name, call_status, call_direction, 
+                        if(call_reason is null, 'Unknown', call_reason) as call_reason, duration, feedback",
+        "join"      => array(
+            "left join {$table_prefix}users on user_id = representative",
+            "left join {$table_prefix}employees on emp_id = user_emp_id",
+        ),
+        "where"     => array(
+            "client_identity like '%{$caller}'"
+        ),
+        "orderby"   => array(
+            "call_id" => "DESC"
+        ),
+        "limit"     => array(
+            "start"     => 0,
+            "length"    => 5,
+        )
+    ));
+
+
+    $callerDetails = array(
+        "details"           => array(),
+        "callHistory"       => array(),
+        "totalCallCount"    => 0,
+        "smsHistory"        => array(),
+        "totalSmsCount"     => array(),
+        "caseHistory"       => array(),
+        "orderHistory"       => array()
+    );
+
+    if($getCallHistory !== false) {
+
+        $callerDetails["callHistory"] = $getCallHistory["data"];
+        $callerDetails["totalCallCount"] = easySelectD("select count(*) as totalCallCount from {$table_prefix}calls where client_identity like '%{$caller}'")["data"][0]["totalCallCount"];
+
+    }
+
+
+    if($callerData !== false) {
+  
+        $callerDetails["details"] = $callerData["data"][0];
+
+    } 
+
+
+    // Get SMS History
+    $getSmsHistory = easySelectA(array(
+        "table"     => "sms_sender as sms",
+        "fields"    => "send_time, concat(emp_firstname, ' ', emp_lastname) as agent_name, left(sms_text, 50) as sms_text",
+        "join"      => array(
+            "left join {$table_prefix}users on user_id = send_by",
+            "left join {$table_prefix}employees on emp_id = user_emp_id",
+        ),
+        "where"     => array(
+            "sms.is_trash = 0 and sms.send_to like '%{$caller}'"
+        ),
+        "orderby"   => array(
+            "sms_id" => "DESC"
+        ),
+        "limit"     => array(
+            "start"     => 0,
+            "length"    => 5,
+        )
+    ));
+
+    if($getSmsHistory !== false) {
+
+        $callerDetails["smsHistory"] = $getSmsHistory["data"];
+        $callerDetails["totalSmsCount"] = easySelectD("select count(*) as totalSmsCount from {$table_prefix}sms_sender where send_to like '%{$caller}'")["data"][0]["totalSmsCount"];
+
+    }
+
+
+    $caseHistory = easySelectA(array(
+        "table"     => "cases as cases",
+        "fields"    => "case_id, case_datetime, case_title, case_status, 
+                        case_added_by_agent, concat(posted_by_employee.emp_firstname, ' ', posted_by_employee.emp_lastname) as posted_by_name",
+        "join"      => array(
+            "left join {$table_prefix}users as posted_user on posted_user.user_id = case_added_by_agent",
+            "left join {$table_prefix}employees as posted_by_employee on posted_by_employee.emp_id = posted_user.user_emp_id",
+            "left join {$table_prefix}persons on person_id = case_person",
+            "left join {$table_prefix}customers on customer_id = case_customer",
+        ),
+        "where"     => array(
+            "cases.is_trash = 0 AND (",
+            " customer_phone LIKE" => '%' . $caller,
+            " OR person_phone LIKE" => '%' . $caller,
+            ")"
+        ),
+        "limit" => array(
+            "start" => 0,
+            "length" => 5
+        )
+    ));
+
+    if($caseHistory !== false) {
+        $callerDetails["caseHistory"] = $caseHistory["data"];
+    }
+
+
+    // Select Orders
+    $orderHistory = easySelectA(array(
+        "table"     => "sales as sale",
+        "fields"    => "sales_id as id, sales_delivery_date as date, sales_status as status, sales_reference as reference, round(sales_grand_total, 2) as total, sales_payment_status as payment_status",
+        "join"      => array(
+            "left join {$table_prefix}customers on customer_id = sales_customer_id"
+        ),
+        "where"     => array(
+            "sale.is_trash = 0 AND customer_phone LIKE" => '%' . $caller,
+        ),
+        "limit" => array(
+            "start" => 0,
+            "length" => 5
+        )
+    ));
+
+    if($orderHistory !== false) {
+        $callerDetails["orderHistory"] = $orderHistory["data"];
+    }
+
+    echo json_encode($callerDetails);
+    
+
+}
+
+
+
+/*************************** get Call history ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "getCallHistoryData") {
+
+    $caller = str_replace("+88", "",  safe_input($_POST["caller"]) );
+
+
+    $getCallHistory = easySelectA(array(
+        "table"     => "calls",
+        "fields"    => "call_datetime, concat(emp_firstname, ' ', emp_lastname) as agent_name, call_status, call_direction, 
+                        if(call_reason is null, 'Unknown', call_reason) as call_reason, duration, feedback",
+        "join"      => array(
+            "left join {$table_prefix}users on user_id = representative",
+            "left join {$table_prefix}employees on emp_id = user_emp_id",
+        ),
+        "where"     => array(
+            "client_identity like '%{$caller}'"
+        ),
+        "orderby"   => array(
+            "call_id" => "DESC"
+        ),
+        "limit"     => array(
+            "start"     => 5,
+            "length"    => 100,
+        )
+    ));
+
+
+    if( $getCallHistory !== false ) {
+
+        echo json_encode($getCallHistory["data"]);
+
+    } else {
+
+        echo json_encode(array());
+
+    }
+
+
+}
+
+
+
+/*************************** getCallerDetails ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "sendSMS") {
+
+    if(send_sms($_POST["number"], $_POST["text"])) {
+
+        echo "1";
+
+    } else {
+        echo "0";
+    }
+
+}
+
+
+/*************************** getCallerDetails ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "addCallLog") {
+
+    $insertCall = easyInsert(
+       "calls",
+       array(
+           "call_datetime"      => date("Y-m-d H:i:s"),
+           "call_direction"     => $_POST["direction"] === "incoming" ? "Incoming" : "Outgoing",
+           "call_reason"        => "Unknown",
+           "client_identity"    => $_POST["caller"],
+           "call_status"        => $_POST["status"],
+           "duration"           => $_POST["duration"],
+           "feedback"           => $_POST["feedback"],
+           "reviewer"           => empty($_POST["reviewer"]) ? NULL : $_POST["reviewer"],
+           "representative"     => $_SESSION["uid"]
+       ),
+       array(),
+       true
+    );
+
+    if($insertCall !== false) {
+
+        // Update last call time in person list
+        easyUpdate(
+            "persons",
+            array(
+                "last_call_time"    => date("Y-m-d H:i:s")
+            ),
+            array(
+                "person_phone"  => $_POST["caller"]
+            )
+        );
+        
+        echo $insertCall["last_insert_id"];
+
+    }
+
+}
+
+
+/*************************** Representative Call List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "myCallList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "call_id",
+        "call_direction",
+        "call_status",
+        "client_identity",
+        "duration",
+        "feedback",
+        "representative"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "calls",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0 and (representative = {$_SESSION["uid"]} or reviewer = {$_SESSION["uid"]} )"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"]) or 
+        !empty($requestData["columns"][1]['search']['value']) or 
+        !empty($requestData["columns"][2]['search']['value']) or 
+        !empty($requestData["columns"][3]['search']['value']) or 
+        !empty($requestData["columns"][4]['search']['value']) 
+    ) {  // get data with search
+
+        $dateFilter = "";
+        $specimenDateFilter = "";
+        if(!empty($requestData["columns"][1]['search']['value'])) {
+            $dateRange = explode(" - ", safe_input($requestData["columns"][1]['search']['value']));
+            $dateFilter = "and date(call_datetime) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+            $specimenDateFilter = "where date(scd_add_on) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+        }
+
+        $search = "";
+        if( !empty($requestData['search']['value']) ) {
+            $search = "and ( person_full_name LIKE '". safe_input($requestData['search']['value']) ."%' or client_identity LIKE '". safe_input($requestData['search']['value']) ."%' ) ";
+        }
+        
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "call_id, call_datetime, call_direction, call_status, specimen_product_details, person_full_name, person_type, person_address, designation, 
+                            client_identity, duration, feedback, call_reason",
+            "join"      => array(
+                "left join ( select 
+                                person_full_name,
+                                person_type,
+                                concat(
+                                    if(person_address = '', '', concat(person_address, ', ') ), 
+                                    if(upazila_name is null, '', concat(upazila_name, ', ') ), 
+                                    if(district_name is null, '', concat(district_name, ', ') ), 
+                                    if(division_name is null, '', concat(division_name) )
+                                ) as person_address,
+                                product_details as specimen_product_details,
+                                person_phone,
+                                concat(if(person_designation is null, person_designation, ''), ', ', institute_name) as designation
+                            FROM {$table_prefix}persons
+                            left join {$table_prefix}districts on district_id = person_district
+                            left join {$table_prefix}divisions on division_id = person_division
+                            left join {$table_prefix}upazilas on upazila_id = person_upazila
+                            left join {$table_prefix}institute on institute_id = person_institute
+                            left join ( select
+                                    group_concat(product_name, '- ', round(scd_product_qnt, 2) SEPARATOR '<br/>' ) as product_details,
+                                    scd_person_id
+                                from {$table_prefix}sc_distribution
+                                left join {$table_prefix}products on product_id = scd_product_id
+                                where is_bundle_item = 0
+                                group by scd_person_id
+                            ) as specimen_details on scd_person_id = person_id
+                ) as person on person.person_phone = calls.client_identity"
+            ),
+            "where"     => array(
+                "calls.is_trash = 0",
+                " AND call_direction"  => $requestData["columns"][2]['search']['value'],
+                " AND call_reason"  => $requestData["columns"][3]['search']['value'],
+                " AND call_status"  => $requestData["columns"][4]['search']['value'],
+                " AND (representative = {$_SESSION["uid"]} or reviewer = {$_SESSION["uid"]} ) $search $dateFilter"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+        
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "call_id, call_datetime, call_direction, call_status, specimen_product_details, person_full_name, person_type, person_address, designation, 
+                            client_identity, duration, feedback, call_reason",
+            "join"      => array(
+                "left join ( select 
+                                person_full_name,
+                                person_type,
+                                concat(
+                                    if(person_address = '', '', concat(person_address, ', ') ), 
+                                    if(upazila_name is null, '', concat(upazila_name, ', ') ), 
+                                    if(district_name is null, '', concat(district_name, ', ') ), 
+                                    if(division_name is null, '', concat(division_name) )
+                                ) as person_address,
+                                product_details as specimen_product_details,
+                                person_phone,
+                                concat(if(person_designation is null, person_designation, ''), ', ', institute_name) as designation
+                            FROM {$table_prefix}persons
+                            left join {$table_prefix}districts on district_id = person_district
+                            left join {$table_prefix}divisions on division_id = person_division
+                            left join {$table_prefix}upazilas on upazila_id = person_upazila
+                            left join {$table_prefix}institute on institute_id = person_institute
+                            left join ( select
+                                    group_concat(product_name, '- ', round(scd_product_qnt, 2) SEPARATOR '<br/>' ) as product_details,
+                                    scd_person_id
+                                from {$table_prefix}sc_distribution
+                                left join {$table_prefix}products on product_id = scd_product_id
+                                where is_bundle_item = 0
+                                group by scd_person_id
+                            ) as specimen_details on scd_person_id = person_id
+                ) as person on person.person_phone = calls.client_identity"
+            ),
+            "where"     => array(
+                "calls.is_trash = 0",
+                " and (representative = {$_SESSION["uid"]} or reviewer = {$_SESSION["uid"]} )"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            
+            $callStatus = "";
+            if($value["call_status"] === "Answered") {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-success'>Answered</span>";
+            } else if($value["call_status"] === "Rejected") {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-danger'>Rejected</span>";
+            } else {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-info'>{$value["call_status"]}</span>";
+            }
+
+            $allNestedData[] = "";
+            $allNestedData[] = $value["call_datetime"];
+            $allNestedData[] = $value["call_direction"];
+            $allNestedData[] = $value["call_reason"];
+            $allNestedData[] = $callStatus;
+            $allNestedData[] = "{$value["client_identity"]}<br/>{$value["person_full_name"]}, {$value["person_type"]} <br/> {$value["designation"]}, {$value["person_address"]}";
+            $allNestedData[] = $value["specimen_product_details"];
+            $allNestedData[] = $value["duration"];
+            $allNestedData[] = $value["feedback"] . '<a style="margin-left: 10px;" data-toggle="modal" data-target="#modalDefault" href="'. full_website_address() .'/xhr/?module=customer-support&page=editCallFeedback&call_id='. $value["call_id"] .'"><i class="fa fa-edit"></i></a>';
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/*************************** Representative Call List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "allCallList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "call_id",
+        "call_direction",
+        "call_status",
+        "client_identity",
+        "person_type",
+        "duration",
+        "feedback",
+        "feedback_informative",
+        "sale_our_product",
+        "use_our_product",
+        "mr_feedback",
+        "other_info",
+        "representative"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "calls",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+ 
+    if( !empty($requestData["search"]["value"]) or 
+        !empty($requestData["columns"][1]['search']['value']) or 
+        !empty($requestData["columns"][2]['search']['value']) or 
+        !empty($requestData["columns"][3]['search']['value']) or 
+        !empty($requestData["columns"][4]['search']['value']) or 
+        !empty($requestData["columns"][6]['search']['value']) or 
+        !empty($requestData["columns"][10]['search']['value']) or 
+        !empty($requestData["columns"][16]['search']['value']) 
+    ) {  // get data with search
+
+        $dateFilter = "";
+        $specimenDateFilter = "";
+        if(!empty($requestData["columns"][1]['search']['value'])) {
+            $dateRange = explode(" - ", safe_input($requestData["columns"][1]['search']['value']));
+            $dateFilter = "and date(call_datetime) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+            $specimenDateFilter = "where date(scd_add_on) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+        }
+
+        $search = "";
+        if( !empty($requestData['search']['value']) ) {
+            $search = "and ( person_full_name LIKE '". safe_input($requestData['search']['value']) ."%' or client_identity LIKE '". safe_input($requestData['search']['value']) ."%' ) ";
+        }
+        
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "call_id, call_datetime, call_direction, call_status, call_reason, specimen_product_details, person_full_name, person_type, 
+                            person_address, designation, client_identity, duration, feedback, concat(emp_firstname, ' ', emp_lastname) as representative,
+                            feedback_informative, sale_our_product, use_our_product, mr_feedback, other_info, specimen_copy_received",
+            "join"      => array(
+                "left join {$table_prefix}users on representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+                "left join ( select 
+                                person_full_name,
+                                person_type,
+                                concat(
+                                    if(person_address = '', '', concat(person_address, ', ') ), 
+                                    if(upazila_name is null, '', concat(upazila_name, ', ') ), 
+                                    if(district_name is null, '', concat(district_name, ', ') ), 
+                                    if(division_name is null, '', concat(division_name) )
+                                ) as person_address,
+                                product_details as specimen_product_details,
+                                person_phone,
+                                concat(if(person_designation is null, person_designation, ''), ', ', institute_name) as designation
+                            FROM {$table_prefix}persons
+                            left join {$table_prefix}districts on district_id = person_district
+                            left join {$table_prefix}divisions on division_id = person_division
+                            left join {$table_prefix}upazilas on upazila_id = person_upazila
+                            left join {$table_prefix}institute on institute_id = person_institute
+                            left join ( select
+                                    group_concat(product_name, '- ', round(scd_product_qnt, 2) SEPARATOR '<br/>' ) as product_details,
+                                    scd_person_id
+                                from {$table_prefix}sc_distribution
+                                left join {$table_prefix}products on product_id = scd_product_id
+                                where is_bundle_item = 0
+                                group by scd_person_id
+                            ) as specimen_details on scd_person_id = person_id
+                ) as person on person.person_phone = calls.client_identity"
+            ),
+            "where"     => array(
+                "calls.is_trash = 0",
+                " AND call_direction"  => $requestData["columns"][2]['search']['value'],
+                " AND call_status"  => $requestData["columns"][3]['search']['value'],
+                " AND call_reason"  => $requestData["columns"][4]['search']['value'],
+                " AND person_type"  => $requestData["columns"][6]['search']['value'],
+                " AND specimen_copy_received"  => $requestData["columns"][10]['search']['value'],
+                " AND representative"  => $requestData["columns"][16]['search']['value'],
+                " $search $dateFilter"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+
+        ));
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+
+    } else { // Get data withouth search
+
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "call_id, call_datetime, call_direction, call_status, call_reason, specimen_product_details, person_full_name, person_type, 
+                            person_address, designation, client_identity, duration, feedback, concat(emp_firstname, ' ', emp_lastname) as representative,
+                            feedback_informative, sale_our_product, use_our_product, mr_feedback, other_info, specimen_copy_received
+                            ",
+            "join"      => array(
+                "left join {$table_prefix}users on representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+                "left join ( select 
+                                person_full_name,
+                                person_type,
+                                concat(
+                                    if(person_address = '', '', concat(person_address, ', ') ), 
+                                    if(upazila_name is null, '', concat(upazila_name, ', ') ), 
+                                    if(district_name is null, '', concat(district_name, ', ') ), 
+                                    if(division_name is null, '', concat(division_name) )
+                                ) as person_address,
+                                product_details as specimen_product_details,
+                                person_phone,
+                                concat(if(person_designation is null, person_designation, ''), ', ', institute_name) as designation
+                            FROM {$table_prefix}persons
+                            left join {$table_prefix}districts on district_id = person_district
+                            left join {$table_prefix}divisions on division_id = person_division
+                            left join {$table_prefix}upazilas on upazila_id = person_upazila
+                            left join {$table_prefix}institute on institute_id = person_institute
+                            left join ( select
+                                    group_concat(product_name, '- ', round(scd_product_qnt, 2) SEPARATOR '<br/>' ) as product_details,
+                                    scd_person_id
+                                from {$table_prefix}sc_distribution
+                                left join {$table_prefix}products on product_id = scd_product_id
+                                where is_bundle_item = 0
+                                group by scd_person_id
+                            ) as specimen_details on scd_person_id = person_id
+                ) as person on person.person_phone = calls.client_identity"
+            ),
+            "where"     => array(
+                "calls.is_trash = 0"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            
+            $callStatus = "";
+            if($value["call_status"] === "Answered") {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-success'>Answered</span>";
+            } else if($value["call_status"] === "Rejected") {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-danger'>Rejected</span>";
+            } else {
+                $callStatus = "<span style='padding: 2px 5px;' class='text-center btn-info'>{$value["call_status"]}</span>";
+            }
+
+            $allNestedData[] = "";
+            $allNestedData[] = $value["call_datetime"];
+            $allNestedData[] = $value["call_direction"];
+            $allNestedData[] = $callStatus;
+            $allNestedData[] = $value["call_reason"];
+            $allNestedData[] = "{$value["client_identity"]}<br/>{$value["person_full_name"]} <br/> {$value["designation"]}, {$value["person_address"]}";
+            $allNestedData[] = $value["person_type"];
+            $allNestedData[] = $value["specimen_product_details"];
+            $allNestedData[] = $value["duration"];
+            $allNestedData[] = $value["feedback"] . '<a style="margin-left: 10px;" data-toggle="modal" data-target="#modalDefault" href="'. full_website_address() .'/xhr/?module=customer-support&page=editCallFeedback&call_id='. $value["call_id"] .'"><i class="fa fa-edit"></i></a>';
+            $allNestedData[] = $value["specimen_copy_received"];
+            $allNestedData[] = $value["feedback_informative"];
+            $allNestedData[] = $value["sale_our_product"];
+            $allNestedData[] = $value["use_our_product"];
+            $allNestedData[] = $value["mr_feedback"];
+            $allNestedData[] = $value["other_info"];
+            $allNestedData[] = $value["representative"];
+            
+            $allData[] = $allNestedData;
+            
+        }
+
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/************************** Edit Call Feedback **********************/
+if(isset($_GET['page']) and $_GET['page'] == "editCallFeedback") {
+
+    $getCallData = easySelectA(array(
+        "table"     => "calls",
+        "fields"    => "feedback, client_identity, reviewer, concat(emp_firstname, ' ', emp_lastname) as reviewer_name",
+        "join"      => array(
+            "left join {$table_prefix}users on reviewer = user_id",
+            "left join {$table_prefix}employees on user_emp_id = emp_id"
+        ),
+        "where"     => array(
+            "call_id"   => $_GET["call_id"]
+        )
+    ))["data"][0];
+  
+    // Include the modal header
+    modal_header("Edit feedback for {$getCallData["client_identity"]}", full_website_address() . "/xhr/?module=customer-support&page=updateCallFeedback");
+    
+    ?>
+      <div class="box-body">
+
+        <div class="form-group required">
+            <label for="feedback">Feedback:</label>
+            <textarea name="feedback" id="feedback" cols="30" rows="6" class="form-control" placeholder="Please enter case/ issue/ problem details here"> <?php echo $getCallData["feedback"]; ?> </textarea>
+        </div>
+        <div class="form-group required">
+            <label for="reviewer">Reviewer:</label>
+            <select name="reviewer" id="reviewer" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                <option value=""><?= __("Select feedback reviewer"); ?>....</option>
+                <option selected value="<?php echo $getCallData["reviewer"]; ?>"> <?php echo $getCallData["reviewer_name"]; ?> </option>
+            </select>
+        </div>
+        <input type="hidden" name="callId" value="<?php echo safe_entities($_GET["call_id"]); ?>">
+        
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+
+/*************************** updateCallFeedback ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "updateCallFeedback") {
+
+    $call_id = empty($_POST["callId"]) ? "" : $_POST["callId"];
+
+    // if $_POST["callId"] there have a caller number to search the call_id in database
+    if( $call_id === "" and isset( $_POST["caller"] ) ) {
+    
+        $lastCallOfThisCaller = easySelectD("SELECT call_id FROM {$table_prefix}calls where client_identity = '". safe_input($_POST["caller"]) ."' and date(call_datetime) = current_date order by call_id DESC limit 0,1");
+
+        if($lastCallOfThisCaller !== false) {
+            $call_id = $lastCallOfThisCaller["data"][0]["call_id"];
+        }
+
+    }
+
+    // If there caller id is empty then return an error msg
+    if($call_id === "") {
+        return _e("There is no call found regarding this number.");
+    }
+
+    $updateCallsFeedback = easyUpdate(
+        "calls",
+        array(
+            "feedback"               => $_POST["feedback"],
+            "call_reason"            => $_POST["reason"],
+            "specimen_copy_received" => empty($_POST["specimenReceived"]) ? NULL : $_POST["specimenReceived"],
+            "feedback_informative"   => empty($_POST["informative"]) ? NULL : $_POST["informative"],
+            "sale_our_product"       => empty($_POST["saleOurProduct"]) ? NULL : $_POST["saleOurProduct"],
+            "use_our_product"        => empty($_POST["userOurProduct"]) ? NULL : $_POST["userOurProduct"],
+            "mr_feedback"            => empty($_POST["mrFeedback"]) ? NULL : $_POST["mrFeedback"],
+            "other_info"             => $_POST["otherInformation"],
+            "reviewer"               => empty($_POST["reviewer"]) ? NULL : $_POST["reviewer"],
+        ),
+        array(
+            "call_id"    => $call_id
+        )
+    );
+
+    if($updateCallsFeedback !== false) {
+        _s("Successfully updated");
+    } else {
+        _e($updateCallsFeedback);
+    }
+
+}
+
+/************************** New Case **********************/
+if(isset($_GET['page']) and $_GET['page'] == "newCase") {
+  
+    // Include the modal header
+    modal_header("Add New Case", full_website_address() . "/xhr/?module=customer-support&page=addNewCase");
+    
+    ?>
+      <div class="box-body">
+
+        <script src="<?php echo full_website_address(); ?>/assets/3rd-party/tinymce_6.1.2/tinymce.min.js"></script>
+
+        <div class="row">
+
+            <div class="col-md-7">
+
+                <div class="form-group required">
+                    <label for="caseTitle"><?= __("Case Title:"); ?></label>
+                    <input type="text" name="caseTitle" id="caseTitle" class="form-control" required>
+                </div>
+                <div class="form-group required">
+                    <label for="caseDetails">Case/ Issue details:</label>
+                    <textarea name="caseDetails" id="caseDetails" cols="30" rows="8" class="form-control" placeholder="Please enter case/ issue/ problem details here"></textarea>
+                </div>
+                <div class="form-group">
+                    <label for="caseNote">Note/ Private Reply:</label>
+                    <textarea name="caseNote" id="caseNote" cols="30" rows="4" class="form-control" placeholder="Enter Note/ Private reply here. This will not visible to customers."></textarea>
+                </div>
+                <div class="form-group">
+                    <label for="caseAttachment">Attachment</label>
+                    <input type="file" name="caseAttachment[]" id="caseAttachment" multiple accept="image/png, image/jpeg" class="form-control">
+                    <small style='padding: 2px;' class='alert-danger'>Note: Max Upload Size: <?php echo $_SETTINGS["MAX_UPLOAD_SIZE"]; ?>MB. Only JPEG and PNG image types are allowed to upload</small>    
+                </div>
+                
+                
+            </div>
+
+            <div class="col-md-5">
+
+                <div class="form-group required">
+                    <label for="casePriority"><?= __("Prority:"); ?></label>
+                    <select name="casePriority" id="casePriority" class="form-control" style="width: 100%;" required>
+                        <option value=""><?= __("Select Prority"); ?>....</option>
+                        <?php 
+                            $priority = array('Low', 'Medium', 'High', 'Critical');
+                            foreach($priority as $priority) {
+                                echo "<option value='{$priority}'>{$priority}</option>";
+                            }
+                        ?>
+
+                    </select>
+                </div>
+
+                <div class="form-group required">
+                    <label for="caseType"><?= __("Type:"); ?></label>
+                    <select name="caseType" id="caseType" class="form-control" style="width: 100%;" required>
+                        <option value=""><?= __("Select Type"); ?>....</option>
+                        <?php 
+                            $type = array('Refund Request', 'Packaging Issues', 'Delivery Issue', 'Technical Issues', 'Query', 'Damaged Item', 'Exchange', 'Others');
+                            foreach($type as $type) {
+                                echo "<option value='{$type}'>{$type}</option>";
+                            }
+                        ?>
+
+                    </select>
+                </div>
+
+                <div class="form-group">
+                    <label for="caseStatus"><?= __("Status:"); ?></label>
+                    <select name="caseStatus" id="caseStatus" class="form-control" style="width: 100%;">
+                        <option value=""><?= __("Select Status"); ?>....</option>
+                        <?php 
+                            $status = array('Pending', 'Open', 'Replied', 'Customer Responded', 'Solved', 'Informed', 'On Hold');
+                            foreach($status as $status) {
+                                echo "<option value='{$status}'>{$status}</option>";
+                            }
+                        ?>
+
+                    </select>
+                </div>
+
+                <div class="form-group">
+                    <label for="caseCustomer"><?= __("Customer:"); ?></label>
+                    <select name="caseCustomer" id="caseCustomer" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=customerList" style="width: 100%;">
+                        <option value=""><?= __("Select Customer"); ?>....</option>
+                    </select>
+                </div>
+
+                <div class="form-group">
+                    <label for="casePerson"><?= __("Person/ Lead:"); ?></label>
+                    <select name="casePerson" id="casePerson" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=personList" style="width: 100%;">
+                        <option value=""><?= __("Select Person/ Lead"); ?>....</option>
+                    </select>
+                </div>
+
+                <div class="form-group">
+                    <label for="caseSite"><?= __("Site:"); ?></label>
+                    <input type="text" name="caseSite" id="caseSite" class="form-control">
+                </div>
+
+                <div class="form-group">
+                    <label for="caseAssignTo"><?= __("Assign To:"); ?></label>
+                    <select name="caseAssignTo" id="caseAssignTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                        <option value=""><?= __("Select user"); ?>....</option>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label for="caseBelongsTo"><?= __("Belongs To:"); ?></label>
+                    <select name="caseBelongsTo" id="caseBelongsTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=employeeList" style="width: 100%;">
+                        <option value=""><?= __("Select Employee"); ?>....</option>
+                    </select>
+                </div>
+
+            </div>
+
+
+        </div>
+
+        <script>
+            // Initialize the editor
+            tinymce.init({
+                selector: '#caseDetails',
+                menubar: false,
+                plugins: 'link',
+                toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | link | outdent indent',
+                statusbar: false,
+                height : 270,
+                default_link_target: "_blank",
+                branding: false,
+                invalid_elements : 'em,input,textarea,button',
+            });
+        </script>
+
+        
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+
+if(isset($_GET['page']) and $_GET['page'] == "addNewCase") {
+
+
+    if( empty($_POST["caseTitle"]) ) {
+        return _e("Please enter case title");
+    } else if( empty($_POST["caseDetails"]) ) {
+        return _e("Please enter case detials");
+    } else if( empty($_POST["casePriority"]) ) {
+        return _e("Please select priority");
+    } else if( empty($_POST["caseType"]) ) {
+        return _e("Please select case type");
+    }
+
+    $attachmentList = array();
+    $hasErrorOnUpload = false;
+
+    if( $_FILES["caseAttachment"]["size"][0] > 0 ) {
+
+        $maxUploadSize = $_SETTINGS["MAX_UPLOAD_SIZE"] * 1024 * 1024;
+
+        foreach($_FILES["caseAttachment"]["size"] as $index => $size)  {
+
+            if ($maxUploadSize < $size) {
+                $hasErrorOnUpload = true;
+                break;
+            }
+
+            $mimeType = strtolower($_FILES["caseAttachment"]["type"][$index]);
+            $extension = explode(".", $_FILES["caseAttachment"]["name"][$index]);
+            $extension = end($extension);
+
+            if( 
+                !isset( $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"][$extension] ) or 
+                (   
+                    isset($_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"][$extension]) and 
+                    !in_array( $mimeType, $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"][$extension] ) 
+                ) 
+            ) {
+                $hasErrorOnUpload = true;
+                break;
+            }
+
+            if($size > 0) {
+
+                array_push($attachmentList, array(
+                    "name"  => $_FILES["caseAttachment"]["name"][$index],
+                    "type"  => $_FILES["caseAttachment"]["type"][$index],
+                    "tmp_name"  => $_FILES["caseAttachment"]["tmp_name"][$index],
+                    "error"  => $_FILES["caseAttachment"]["error"][$index],
+                    "size"  => $_FILES["caseAttachment"]["size"][$index]
+                ));
+
+            }
+
+        }
+
+    }
+
+    if($hasErrorOnUpload) {
+        return _e("There have an error to upload the images. Please check the image type and size.");
+    }
+
+    // Insert case
+    $insertCase = easyInsert(
+        "cases",
+        array(
+            "case_datetime"     => date("Y-m-d H:i:s"),
+            "case_title"        => $_POST["caseTitle"],
+            "case_priority"     => $_POST["casePriority"],
+            "case_type"         => $_POST["caseType"],
+            "case_status"       => empty($_POST["caseStatus"]) ? 'Open' : $_POST["caseStatus"],
+            "case_site"         => $_POST["caseSite"],
+            "case_customer"     => empty($_POST["caseCustomer"]) ? NULL : $_POST["caseCustomer"],
+            "case_person"       => empty($_POST["casePerson"]) ? NULL : $_POST["casePerson"],
+            "case_assigned_to"  => empty($_POST["caseAssignTo"]) ? NULL : $_POST["caseAssignTo"],
+            "case_belongs_to"  => empty($_POST["caseBelongsTo"]) ? NULL : $_POST["caseBelongsTo"],
+            "case_added_by_agent" => $_SESSION["uid"]
+        ),
+        array(),
+        true
+    );
+
+    //print_r($insertCase);
+
+    if( isset($insertCase["status"]) and $insertCase["status"] === 'success' ) {
+
+
+        $uploadedAttachment = array();
+
+        if( count($attachmentList) > 0 ) {
+
+            foreach($attachmentList as $attached)  {
+
+                $attachmentUploadDir = "attachments/cases/{$_POST["caseType"]}/" . date("Y-m-d");
+                $uploadCaseAttachment = easyUpload($attached, $attachmentUploadDir );
+
+                if(!isset($uploadCaseAttachment["success"])) {
+                    $hasErrorOnUpload = true;
+                } else {
+                    array_push($uploadedAttachment, $attachmentUploadDir . "/".$uploadCaseAttachment["fileName"]);
+                }
+
+            }
+
+        }
+
+
+        // Insert case public replies
+        easyInsert(
+            "case_replies",
+            array(
+                "reply_type"        => 'Public',
+                'reply_case_id'     => $insertCase["last_insert_id"],
+                "reply_datetime"    => date("Y-m-d H:i:s"),
+                "reply_details"     => purify_html($_POST["caseDetails"]) ,
+                "reply_attachment"  => serialize($uploadedAttachment),
+                "reply_by_agent"    => $_SESSION["uid"]
+            )
+        );
+
+        // Insert case private replies
+        if( !empty($_POST["caseNote"]) ) {
+            easyInsert(
+                "case_replies",
+                array(
+                    "reply_type"        => 'Private',
+                    'reply_case_id'     => $insertCase["last_insert_id"],
+                    "reply_datetime"    => date("Y-m-d H:i:s"),
+                    "reply_details"     => purify_html($_POST["caseNote"]),
+                    "reply_attachment"  => NULL,
+                    "reply_by_agent"    => $_SESSION["uid"]
+                )
+            );
+        }
+        
+        _s("Case has been added successfully");
+
+    }
+
+}
+
+
+if(isset($_GET['page']) and $_GET['page'] == "addCaseReply") {
+
+
+    if( empty($_POST["caseReply"]) ) {
+        return _e("Please enter case reply");
+    } else if( empty($_POST["replyMode"]) ) {
+        return _e("Please select reply mode");
+    }
+
+    $attachmentList = array();
+    $hasErrorOnUpload = false;
+
+    if( $_FILES["caseReplyAttachment"]["size"][0] > 0 ) {
+
+        $maxUploadSize = $_SETTINGS["MAX_UPLOAD_SIZE"] * 1024 * 1024;
+
+        foreach($_FILES["caseReplyAttachment"]["size"] as $index => $size)  {
+
+            if ($maxUploadSize < $size) {
+                $hasErrorOnUpload = true;
+                break;
+            }
+
+            $extensionName = strtolower(explode("/", $_FILES["caseReplyAttachment"]["type"][$index])[1]);
+            if(!in_array($extensionName, $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"])) {
+                $hasErrorOnUpload = true;
+                break;
+            }
+
+            if($size > 0) {
+
+                array_push($attachmentList, array(
+                    "name"  => $_FILES["caseReplyAttachment"]["name"][$index],
+                    "type"  => $_FILES["caseReplyAttachment"]["type"][$index],
+                    "tmp_name"  => $_FILES["caseReplyAttachment"]["tmp_name"][$index],
+                    "error"  => $_FILES["caseReplyAttachment"]["error"][$index],
+                    "size"  => $_FILES["caseReplyAttachment"]["size"][$index]
+                ));
+
+            }
+
+        }
+
+    }
+
+    if($hasErrorOnUpload) {
+        return _e("There have an error to upload the images. Please check the image type and size.");
+    }
+
+
+    $uploadedAttachment = array();
+
+    if( count($attachmentList) > 0 ) {
+
+        foreach($attachmentList as $attached)  {
+
+            $attachmentUploadDir = "attachments/cases/{$_POST["caseType"]}/" . date("Y-m-d");
+            $uploadCaseAttachment = easyUpload($attached, $attachmentUploadDir );
+
+            if(!isset($uploadCaseAttachment["success"])) {
+                $hasErrorOnUpload = true;
+            } else {
+                array_push($uploadedAttachment, $attachmentUploadDir . "/".$uploadCaseAttachment["fileName"]);
+            }
+
+        }
+
+    }
+
+
+    // Insert case public replies
+    $addCaseReyply = easyInsert(
+        "case_replies",
+        array(
+            "reply_type"        => $_POST["replyMode"],
+            'reply_case_id'     => $_POST["case_id"],
+            "reply_datetime"    => date("Y-m-d H:i:s"),
+            "reply_details"     => purify_html($_POST["caseReply"]),
+            "reply_attachment"  => serialize($uploadedAttachment),
+            "reply_by_agent"    => $_SESSION["uid"]
+        ),
+        array(),
+        true
+    );
+  
+
+    
+    if( isset($addCaseReyply["status"]) and $addCaseReyply["status"] === 'success' ) {
+
+        $selectReplies = easySelectA(array(
+            "table"     => "case_replies as reply",
+            "fields"    => "reply_id, reply_type, reply_datetime, reply_details, reply_attachment,
+                            if(emp_firstname is null, customer_name, concat(emp_firstname, ' ', emp_lastname)) as reply_by,
+                            reply_by_customer
+                            ",
+            "join"      => array(
+                "left join {$table_prefix}users on user_id = reply_by_agent",
+                "left join {$table_prefix}employees on emp_id = user_emp_id",
+                "left join {$table_prefix}customers on customer_id = reply_by_customer"
+            ),
+            "where"     => array(
+                "reply.is_trash = 0 and reply_id"    => $addCaseReyply["last_insert_id"]
+            )
+        ));
+
+        if($selectReplies !== false) {
+
+            $reply = $selectReplies["data"][0];
+
+            $time_elaps = time_elapsed_string($reply["reply_datetime"]) . " (" .  date("d F, Y h:m A", strtotime($reply["reply_datetime"]))  .")";
+
+            $attachment = "";
+            if($reply["reply_attachment"] !== null) {
+
+                $listAttachment = unserialize( html_entity_decode($reply["reply_attachment"]) );
+
+                foreach($listAttachment as $image) {
+                    $attachment .= "<li><img width='80' height='80' src='". full_website_address() ."/assets/upload/{$image}'></li>";
+                }
+
+            }
+
+
+            // Define user and reply type
+            $userType = "<span><i class='fa fa-user'></i> Staff</span>";
+            $replyType = "<span><i class='fa fa-globe'></i> Public</span>";
+            $replyClass = 'reply';
+            $replyTypeMoveTo = 'Private';
+            if( $reply["reply_by_customer"] !== null ) {
+                $userType = "<span><i class='fa fa-user'></i> Customer</span>";
+            }
+
+            if( $reply["reply_type"] === "Private" ) {
+                $replyType = "<span><i class='fa fa-lock'></i> Private</span>";
+                $replyClass = 'reply private';
+                $replyTypeMoveTo = 'Public';
+            }
+
+            // If there have any attachment then show them
+            if($attachment !== "") {
+                $attachment = "<div class='attachment'>
+                                    <p>Attachment:</p>
+                                    <ul class='imageAttachment'>
+                                        {$attachment}
+                                    </ul>
+                                </div>";
+            }
+            
+            
+            echo "<div class='{$replyClass}'>
+                    
+                    <div class='title'>
+                        <span>{$reply["reply_by"]}</span>
+                        <span>
+                            {$time_elaps}
+                        
+                            <div class='btn-group'>
+                                
+                                <button type='button' class='btn btn-link' data-toggle='dropdown'>
+                                    <i class='fa fa-ellipsis-v'></i>
+                                </button>
+                                <ul class='dropdown-menu dropdown-menu-right' role='menu'>
+
+                                    <li><a class='deleteEntry' removeParent='.reply' href='". full_website_address() . "/xhr/?module=customer-support&page=deleteCase data-to-be-deleted={$reply["reply_id"]}'> Delete</a></li>
+                                    <li> <a class='updateEntry' href='". full_website_address() . "/xhr/?module=customer-support&page=updateCaseReplyType' data-to-be-updated='{$reply["reply_id"]}'>Move to {$replyTypeMoveTo} </a> </li>
+
+                                </ul>
+
+                            </div>
+                        </span>
+
+                    </div>
+                    <div class='type'>
+                        {$userType}
+                        {$replyType}
+                    </div>
+
+                    <div class='reply-details'>
+                        ". str_replace('\n', '</br>', html_entity_decode($reply["reply_details"]) ) ."
+                    </div>
+                    $attachment
+                    
+                </div>";
+
+        }
+
+    }
+
+}
+
+
+/*************************** case List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "caseList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "case_datetime",
+        "requester",
+        "case_title",
+        "FIELD(case_is_pin, 1, 0),
+        FIELD(case_status, 'Pending', 'Customer Responded', 'Open', 'Informed', 'On Hold', 'Replied', 'Closed', 'Solved'),
+        FIELD(case_priority, 'Critical', 'High', 'Medium', 'Low'),
+        case_datetime"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "cases",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+
+
+ if( !empty($requestData["search"]["value"])) {  // get data with only search
+
+        $getData = easySelectA(array(
+            "table"     => "cases as cases",
+            "fields"    => "case_id, case_datetime, case_title, case_priority, case_type, case_status, last_reply, 
+                            case_assigned_to, concat(assigned_to_employee.emp_firstname, ' ', assigned_to_employee.emp_lastname) as case_assign_to_name, 
+                            case_belongs_to, concat(belongs_to.emp_firstname, ' ', belongs_to.emp_lastname) as case_belongs_to_name,
+                            case_added_by_agent, concat(posted_by_employee.emp_firstname, ' ', posted_by_employee.emp_lastname) as posted_by_name, 
+                            if(person_full_name is null, 
+                                concat(customer_name, '<br/>', customer_phone),
+                                concat(person_full_name, '<br/>', person_phone, ', ', person_email)
+                            ) as requester",
+            "join"      => array(
+                "left join {$table_prefix}users as assigned_user on assigned_user.user_id = case_assigned_to",
+                "left join {$table_prefix}employees as assigned_to_employee on assigned_to_employee.emp_id = assigned_user.user_emp_id",
+
+                "left join {$table_prefix}users as posted_user on posted_user.user_id = case_added_by_agent",
+                "left join {$table_prefix}employees as posted_by_employee on posted_by_employee.emp_id = posted_user.user_emp_id",
+
+                "left join {$table_prefix}employees as belongs_to on belongs_to.emp_id = case_belongs_to",
+                "left join {$table_prefix}persons on person_id = case_person",
+                "left join {$table_prefix}customers on customer_id = case_customer",
+                "left join (select
+                        max(reply_datetime) as last_reply,
+                        reply_case_id
+                    from {$table_prefix}case_replies
+                    where is_trash = 0
+                    group by reply_case_id
+                ) as replies on replies.reply_case_id = case_id"
+            ),
+            "where"     => array(
+                "cases.is_trash = 0 AND (",
+                " customer_name LIKE '". safe_input($requestData["search"]["value"]) ."' ",
+                " OR customer_phone LIKE" => $requestData["search"]["value"] . '%',
+                " OR person_full_name LIKE" => '%' . $requestData["search"]["value"] . '%',
+                " OR person_phone LIKE" => $requestData["search"]["value"] . '%',
+                ")",
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+        
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else if( !empty($requestData["search"]["value"]) or
+        !empty($requestData["columns"][1]['search']['value']) or 
+        !empty($requestData["columns"][3]['search']['value']) or 
+        !empty($requestData["columns"][4]['search']['value']) or 
+        !empty($requestData["columns"][5]['search']['value']) or 
+        !empty($requestData["columns"][6]['search']['value']) or
+        !empty($requestData["columns"][7]['search']['value']) or
+        !empty($requestData["columns"][8]['search']['value']) or
+        !empty($requestData["columns"][10]['search']['value'])
+    ) {  // get data with search and filters
+
+        $dateFilter = "";
+        if(!empty($requestData["columns"][1]['search']['value'])) {
+            $dateRange = explode(" - ", safe_input($requestData["columns"][1]['search']['value']));
+            $dateFilter = " AND date(case_datetime) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+        }
+
+        $getData = easySelectA(array(
+            "table"     => "cases as cases",
+            "fields"    => "case_id, case_datetime, case_title, case_priority, case_type, case_status, last_reply, 
+                            case_assigned_to, concat(assigned_to_employee.emp_firstname, ' ', assigned_to_employee.emp_lastname) as case_assign_to_name, 
+                            case_belongs_to, concat(belongs_to.emp_firstname, ' ', belongs_to.emp_lastname) as case_belongs_to_name,
+                            case_added_by_agent, concat(posted_by_employee.emp_firstname, ' ', posted_by_employee.emp_lastname) as posted_by_name, 
+                            if(person_full_name is null, 
+                                concat(customer_name, '<br/>', customer_phone),
+                                concat(person_full_name, '<br/>', person_phone, ', ', person_email)
+                            ) as requester",
+            "join"      => array(
+                "left join {$table_prefix}users as assigned_user on assigned_user.user_id = case_assigned_to",
+                "left join {$table_prefix}employees as assigned_to_employee on assigned_to_employee.emp_id = assigned_user.user_emp_id",
+
+                "left join {$table_prefix}users as posted_user on posted_user.user_id = case_added_by_agent",
+                "left join {$table_prefix}employees as posted_by_employee on posted_by_employee.emp_id = posted_user.user_emp_id",
+
+                "left join {$table_prefix}employees as belongs_to on belongs_to.emp_id = case_belongs_to",
+                "left join {$table_prefix}persons on person_id = case_person",
+                "left join {$table_prefix}customers on customer_id = case_customer",
+                "left join (select
+                        max(reply_datetime) as last_reply,
+                        reply_case_id
+                    from {$table_prefix}case_replies
+                    where is_trash = 0
+                    group by reply_case_id
+                ) as replies on replies.reply_case_id = case_id"
+            ),
+            "where"     => array(
+                "cases.is_trash = 0 AND (",
+                " COALESCE(customer_name, '') LIKE '%". safe_input($requestData["columns"][2]['search']['value']) ."%' ",
+                " OR customer_phone LIKE" => $requestData["columns"][3]['search']['value'] . '%',
+                " OR COALESCE(person_full_name, '') LIKE" => '%' . $requestData["columns"][2]['search']['value'] . '%',
+                " OR person_phone LIKE" => $requestData["columns"][3]['search']['value'] . '%',
+                ")",
+                " AND case_priority"    => $requestData["columns"][4]['search']['value'],
+                " AND case_type"        => $requestData["columns"][5]['search']['value'],
+                " AND case_status"      => $requestData["columns"][6]['search']['value'],
+                " AND case_assigned_to" => $requestData["columns"][7]['search']['value'],
+                " AND case_belongs_to"  => $requestData["columns"][8]['search']['value'],
+                " AND case_added_by_agent"  => $requestData["columns"][10]['search']['value'],
+                " {$dateFilter}"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+        
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+
+        $getData = easySelectA(array(
+            "table"     => "cases as cases",
+            "fields"    => "case_id, case_datetime, case_title, case_priority, case_type, case_status, last_reply, 
+                            case_assigned_to, concat(assigned_to_employee.emp_firstname, ' ', assigned_to_employee.emp_lastname) as case_assign_to_name, 
+                            case_belongs_to, concat(belongs_to.emp_firstname, ' ', belongs_to.emp_lastname) as case_belongs_to_name,
+                            case_added_by_agent, concat(posted_by_employee.emp_firstname, ' ', posted_by_employee.emp_lastname) as posted_by_name, 
+                            if(person_full_name is null, 
+                                concat(customer_name, '<br/>', customer_phone),
+                                concat(person_full_name, '<br/>', person_phone, ', ', person_email)
+                            ) as requester",
+            "join"      => array(
+                "left join {$table_prefix}users as assigned_user on assigned_user.user_id = case_assigned_to",
+                "left join {$table_prefix}employees as assigned_to_employee on assigned_to_employee.emp_id = assigned_user.user_emp_id",
+
+                "left join {$table_prefix}users as posted_user on posted_user.user_id = case_added_by_agent",
+                "left join {$table_prefix}employees as posted_by_employee on posted_by_employee.emp_id = posted_user.user_emp_id",
+
+                "left join {$table_prefix}employees as belongs_to on belongs_to.emp_id = case_belongs_to",
+                "left join {$table_prefix}persons on person_id = case_person",
+                "left join {$table_prefix}customers on customer_id = case_customer",
+                "left join (select
+                        max(reply_datetime) as last_reply,
+                        reply_case_id
+                    from {$table_prefix}case_replies
+                    where is_trash = 0
+                    group by reply_case_id
+                ) as replies on replies.reply_case_id = case_id"
+            ),
+            "where"     => array(
+                "cases.is_trash = 0"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            
+            $caseStatus = "";
+            if($value["case_status"] === "Pending") {
+                $caseStatus = "<span class='text-center btn btn-sm btn-danger'>Pending</span>";
+            } else if($value["case_status"] === "Solved") {
+                $caseStatus = "<span class='text-center btn btn-sm btn-success'>Solved</span>";
+            } else {
+                $caseStatus = "<span class='text-center btn btn-sm btn-info'>{$value["case_status"]}</span>";
+            }
+
+            $casePriority = "";
+            if($value["case_priority"] === "Critical") {
+                $casePriority = "<span class='text-center btn btn-sm btn-danger'>Critical</span>";
+            } else if($value["case_priority"] === "High") {
+                $casePriority = "<span class='text-center btn btn-sm btn-warning'>High</span>";
+            }  else if($value["case_priority"] === "Medium") {
+                $casePriority = "<span class='text-center btn btn-sm btn-info'>Medium</span>";
+            } else {
+                $casePriority = "<span class='text-center btn btn-sm btn-light'>Low</span>";
+            }
+
+            $allNestedData[] = "";
+            $allNestedData[] = $value["case_datetime"];
+            $allNestedData[] = '<a href="'. full_website_address() .'/customer-support/case-list/?case_id='. $value["case_id"] .'"> '. $value["case_title"] .' </a>';
+            $allNestedData[] = $value["requester"];
+            $allNestedData[] = $casePriority;
+            $allNestedData[] = $value["case_type"];
+            $allNestedData[] = $caseStatus;
+            $allNestedData[] = $value["case_assign_to_name"];
+            $allNestedData[] = $value["case_belongs_to_name"];
+            $allNestedData[] = $value["last_reply"] === null ? 'No Reply' : time_elapsed_string($value["last_reply"] );
+            $allNestedData[] = $value["posted_by_name"];
+            
+            $allNestedData[] = '<div class="btn-group">
+                                    <button type="button" class="btn btn-xs btn-flat btn-primary dropdown-toggle" data-toggle="dropdown">
+                                    action
+                                    <span class="caret"></span>
+                                    <span class="sr-only">Toggle Dropdown</span>
+                                    </button>
+                                    <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        <li><a href="'. full_website_address() .'/customer-support/case-list/?case_id='. $value["case_id"] .'"><i class="fa fa-plus-circle"></i> Add Reply</a></li>
+                                        <li><a class="'. ( current_user_can("customer_support_cases.Delete") ? "" : "restricted " ) .'deleteEntry" href="'. full_website_address() . '/xhr/?module=customer-support&page=deleteCase" data-to-be-deleted="'. $value["case_id"] .'"><i class="fa fa-minus-circle"></i> Delete</a></li>
+                                    </ul>
+                                </div>';
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/************************** New Case **********************/
+if(isset($_GET['page']) and $_GET['page'] == "deleteCase") {
+
+    if(current_user_can("customer_support_cases.Delete") !== true) {
+        echo '{
+            "title": "Sorry!",
+            "text": "you do not have permission to delete case.",
+            "showConfirmButton": true,
+            "showCloseButton": true,
+            "toast": false,
+            "icon": "error"
+        }';
+        return;
+    }
+
+    $deleteData = easyDelete(
+        "cases",
+        array(
+            "case_id" => $_POST["datatoDelete"]
+        )
+    );
+
+    if($deleteData === true) {
+        echo '{
+            "title": "The case has been deleted successfully."
+        }';
+    } 
+
+}
+
+
+/************************** New Case **********************/
+if(isset($_GET['page']) and $_GET['page'] == "deleteCaseReply") {
+
+    if(current_user_can("customer_support_cases.Delete") !== true) {
+        echo '{
+            "title": "Sorry!",
+            "text": "you do not have permission to delete case reply.",
+            "showConfirmButton": true,
+            "showCloseButton": true,
+            "toast": false,
+            "icon": "error"
+        }';
+        return;
+    }
+
+    $deleteData = easyDelete(
+        "case_replies",
+        array(
+            "reply_id" => $_POST["datatoDelete"]
+        )
+    );
+
+    if($deleteData === true) {
+        echo '{
+            "title": "The reply has been deleted successfully."
+        }';
+    } 
+
+}
+
+/***************** update case type/ mode ****************/
+if(isset($_GET['page']) and $_GET['page'] == "updateCaseReplyType") {
+
+
+    $replyMode = easySelectA(array(
+        "table"     => "case_replies",
+        "fields"    => "reply_type",
+        "where"     => array(
+            "reply_id"    => $_POST["datatoUpdate"]
+        )
+    ))["data"][0]["reply_type"];
+    
+
+    easyUpdate(
+        "case_replies",
+        array(
+            "reply_type"    => $replyMode === "Private" ? 'Public' : 'Private'
+        ),
+        array(
+            "reply_id"    => $_POST["datatoUpdate"]
+        )
+    );
+
+    echo '{
+        "title": "Updated successfully. Please reload to see the changes."
+    }';
+
+}
+
+
+/*************************** case List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "updateCase") {
+
+    easyUpdate(
+        "cases",
+        array(
+            "case_title"        => $_POST["caseTitle"],
+            "case_priority"     => $_POST["casePriority"],
+            "case_type"         => $_POST["caseType"],
+            "case_status"       => empty($_POST["caseStatus"]) ? 'Open' : $_POST["caseStatus"],
+            "case_site"         => $_POST["caseSite"],
+            "case_customer"     => empty($_POST["caseCustomer"]) ? NULL : $_POST["caseCustomer"],
+            "case_person"       => empty($_POST["casePerson"]) ? NULL : $_POST["casePerson"],
+            "case_assigned_to"  => empty($_POST["caseAssignTo"]) ? NULL : $_POST["caseAssignTo"],
+            "case_belongs_to"   => empty($_POST["caseBelongsTo"]) ? NULL : $_POST["caseBelongsTo"]
+        ),
+        array(
+            "case_id"   => $_POST["case_id"]
+        )
+    );
+
+
+    echo '{
+        "title": "Case properties has been updated successfully."
+    }';
+
+}
+
+/*************************** case List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "smsList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "sms_id",
+        "send_to",
+        "sms_text",
+        "status",
+        "emp_firstname"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "cases",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+
+        $getData = easySelectA(array(
+            "table"     => "sms_sender as sms_sender",
+            "fields"    => "send_to, send_time, sms_text, status, concat(emp_firstname, ' ', emp_lastname) as sms_sent_by",
+            "join"      => array(
+                "left join {$table_prefix}users on send_by = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "sms_sender.is_trash = 0 and send_by"   => $_SESSION["uid"],
+                " and ( send_to LIKE" => $requestData['search']['value'] . "%",
+                " or emp_firstname LIKE" => $requestData['search']['value'] . "%",
+                ")"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+        
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+
+        $getData = easySelectA(array(
+            "table"     => "sms_sender as sms_sender",
+            "fields"    => "send_to, send_time, sms_text, status, concat(emp_firstname, ' ', emp_lastname) as sms_sent_by",
+            "join"      => array(
+                "left join {$table_prefix}users on send_by = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "sms_sender.is_trash = 0 and send_by"   => $_SESSION["uid"]
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            
+
+            $allNestedData[] = "";
+            $allNestedData[] = $value["send_time"];
+            $allNestedData[] = $value["send_to"];
+            $allNestedData[] = $value["sms_text"];
+            $allNestedData[] = $value["status"];
+            $allNestedData[] = $value["sms_sent_by"];
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/*************************** getCallerDetails ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "addNewNote") {
+
+    $insertNote = easyInsert(
+       "notes",
+       array(
+           "note_type"          => $_POST["type"],
+           "note_text"          => $_POST["note"],
+           "note_created_by"    => $_SESSION["uid"]
+       )
+    );
+
+}
+
+
+/************************** New Representative **********************/
+if(isset($_GET['page']) and $_GET['page'] == "newRepresentative") {
+  
+    // Include the modal header
+    modal_header("Add New Customer Care Representative", full_website_address() . "/xhr/?module=customer-support&page=addNewRepresentative");
+    
+    ?>
+      <div class="box-body">
+
+        <div class="form-group required">
+            <label for="representativeUser"><?= __("User:"); ?></label>
+            <select name="representativeUser" id="representativeUser" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;" required>
+                <option value=""><?= __("Select user"); ?>....</option>
+            </select>
+        </div>
+        <div class="form-group required">
+            <label for="sipUsername">SIP Username</label>
+            <input type="text" name="sipUsername" id="sipUsername" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipPassword">SIP Password</label>
+            <input type="password" name="sipPassword" id="sipPassword" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipDomain">SIP Domain</label>
+            <input type="text" name="sipDomain" id="sipDomain" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipSocketAddress">SIP Socket Address</label>
+            <input type="text" name="sipSocketAddress" id="sipSocketAddress" class="form-control" required>
+        </div>
+
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+if(isset($_GET['page']) and $_GET['page'] == "addNewRepresentative") {
+
+    if(empty($_POST["representativeUser"])) {
+        return _e("Please select user");
+    } elseif(empty($_POST["sipUsername"])) {
+        return _e("Please enter SIP username");
+    } elseif(empty($_POST["sipPassword"])) {
+        return _e("Please enter SIP password");
+    } elseif(empty($_POST["sipDomain"])) {
+        return _e("Please enter SIP domain");
+    } elseif(empty($_POST["sipSocketAddress"])) {
+        return _e("Please enter SIP socket address");
+    }
+
+    // Insert sip credentials
+    $insertSip = easyInsert(
+        "sip_credentials",
+        array(
+            "sip_representative"    => $_POST["representativeUser"],
+            "sip_username"          => $_POST["sipUsername"],
+            "sip_password"          => $_POST["sipPassword"],
+            "sip_domain"            => $_POST["sipDomain"],
+            "sip_websocket_addr"    => $_POST["sipSocketAddress"],
+            "sip_created_by"        => $_SESSION["uid"]
+        )
+    );
+
+    if($insertSip !== false) {
+        _s("Successfully addded");
+    } else {
+        _e($insertSip);
+    }
+
+}
+
+
+/*************************** case List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "callCenterRepresentativeList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "emp_firstname",
+        "sip_username",
+        "sip_domain",
+        "sip_websocket_addr"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "sip_credentials",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+
+        $getData = easySelectA(array(
+            "table"     => "sip_credentials as sip_credentials",
+            "fields"    => "sip_id, sip_username, sip_domain, sip_websocket_addr, concat(emp_firstname, ' ', emp_lastname) as callCenterRepresentative",
+            "join"      => array(
+                "left join {$table_prefix}users on sip_representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "sip_credentials.is_trash = 0",
+                " or emp_firstname LIKE" => $requestData['search']['value'] . "%",
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+        
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+
+        $getData = easySelectA(array(
+            "table"     => "sip_credentials as sip_credentials",
+            "fields"    => "sip_id, sip_username, sip_domain, sip_websocket_addr, concat(emp_firstname, ' ', emp_lastname) as callCenterRepresentative",
+            "join"      => array(
+                "left join {$table_prefix}users on sip_representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "sip_credentials.is_trash = 0"
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = $value["callCenterRepresentative"];
+            $allNestedData[] = $value["sip_username"];
+            $allNestedData[] = $value["sip_domain"];
+            $allNestedData[] = $value["sip_websocket_addr"];
+            $allNestedData[] = '<div class="btn-group">
+                                    <button type="button" class="btn btn-xs btn-flat btn-primary dropdown-toggle" data-toggle="dropdown">
+                                    action
+                                    <span class="caret"></span>
+                                    <span class="sr-only">Toggle Dropdown</span>
+                                    </button>
+                                    <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        <li><a data-toggle="modal" data-target="#modalDefault" href="'. full_website_address() .'/xhr/?module=customer-support&page=editCCRepresentative&id='. $value["sip_id"] .'"><i class="fa fa-edit"></i> Edit</a></li>
+                                        <li><a class="'. ( current_user_can("customer_support_representative.Delete") ? "" : "restricted " ) .'deleteEntry" href="'. full_website_address() . '/xhr/?module=customer-support&page=deleteCustomerCareRepresentative" data-to-be-deleted="'. $value["sip_id"] .'"><i class="fa fa-minus-circle"></i> Delete</a></li>
+                                    </ul>
+                                </div>';
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+
+/***************** Delete CustomerCareRepresentative ****************/
+if(isset($_GET['page']) and $_GET['page'] == "deleteCustomerCareRepresentative") {
+
+    if(current_user_can("customer_support_representative.Delete") !== true) {
+        echo '{
+            "title": "Sorry!",
+            "text": "you do not have permission to delete this accounts.",
+            "showConfirmButton": true,
+            "showCloseButton": true,
+            "toast": false,
+            "icon": "error"
+        }';
+        return;
+    }
+
+    $deleteData = easyDelete(
+        "sip_credentials",
+        array(
+            "sip_id" => $_POST["datatoDelete"]
+        )
+    );
+
+    if($deleteData === true) {
+        echo '{
+            "title": "The accounts has been deleted successfully."
+        }';
+    } 
+}
+
+
+/************************** New Representative **********************/
+if(isset($_GET['page']) and $_GET['page'] == "editCCRepresentative") {
+  
+    // Include the modal header
+    modal_header("Edit Customer Care Representative", full_website_address() . "/xhr/?module=customer-support&page=updateRepresentative");
+
+    // Select
+    $selectCCR = easySelectA(array(
+        "table"     => "sip_credentials as sip_credentials",
+        "fields"    => "sip_id, sip_representative, sip_username, sip_password, sip_domain, sip_websocket_addr, concat(emp_firstname, ' ', emp_lastname) as callCenterRepresentative",
+        "join"      => array(
+            "left join {$table_prefix}users on sip_representative = user_id",
+            "left join {$table_prefix}employees on user_emp_id = emp_id",
+        ),
+        "where"     => array(
+            "sip_credentials.sip_id"    => $_GET["id"]
+        )
+    ))["data"][0];
+    
+    ?>
+      <div class="box-body">
+
+        <div class="form-group required">
+            <label for="representativeUser"><?= __("User:"); ?></label>
+            <select name="representativeUser" id="representativeUser" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;" required>
+                <option value=""><?= __("Select user"); ?>....</option>
+                <option selected value="<?php echo $selectCCR["sip_representative"]; ?>"><?php echo $selectCCR["callCenterRepresentative"]; ?></option>
+            </select>
+        </div>
+        <div class="form-group required">
+            <label for="sipUsername">SIP Username</label>
+            <input type="text" name="sipUsername" id="sipUsername" value="<?php echo $selectCCR["sip_username"]; ?>" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipPassword">SIP Password</label>
+            <input type="password" name="sipPassword" id="sipPassword" value="<?php echo $selectCCR["sip_password"]; ?>" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipDomain">SIP Domain</label>
+            <input type="text" name="sipDomain" id="sipDomain" value="<?php echo $selectCCR["sip_domain"]; ?>" class="form-control" required>
+        </div>
+        <div class="form-group required">
+            <label for="sipSocketAddress">SIP Socket Address</label>
+            <input type="text" name="sipSocketAddress" id="sipSocketAddress" value="<?php echo $selectCCR["sip_websocket_addr"]; ?>" class="form-control" required>
+        </div>
+        <input type="hidden" name="sip_id" value="<?php echo safe_entities($_GET["id"]); ?>">
+
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+if(isset($_GET['page']) and $_GET['page'] == "updateRepresentative") {
+
+    if(empty($_POST["representativeUser"])) {
+        return _e("Please select user");
+    } elseif(empty($_POST["sipUsername"])) {
+        return _e("Please enter SIP username");
+    } elseif(empty($_POST["sipPassword"])) {
+        return _e("Please enter SIP password");
+    } elseif(empty($_POST["sipDomain"])) {
+        return _e("Please enter SIP domain");
+    } elseif(empty($_POST["sipSocketAddress"])) {
+        return _e("Please enter SIP socket address");
+    }
+
+    // Insert sip credentials
+    $updateSip = easyUpdate(
+        "sip_credentials",
+        array(
+            "sip_representative"    => $_POST["representativeUser"],
+            "sip_username"          => $_POST["sipUsername"],
+            "sip_password"          => $_POST["sipPassword"],
+            "sip_domain"            => $_POST["sipDomain"],
+            "sip_websocket_addr"    => $_POST["sipSocketAddress"],
+            "sip_created_by"        => $_SESSION["uid"]
+        ), 
+        array(
+            "sip_id"    => $_POST["sip_id"]
+        )
+    );
+
+    if($updateSip !== false) {
+        _s("Successfully updated");
+    } else {
+        _e($updateSip);
+    }
+
+}
+
+
+/*************************** Call List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "noteList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "note_id",
+        "note_type",
+        "note_text"
+    );
+    
+    // Count Total recrods
+
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "notes",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+ 
+    if($requestData['length'] == -1) {
+        $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+        
+      
+        $getData = easySelectA(array(
+            "table"     => "notes as notes",
+            "fields"    => "note_id, note_type, note_text",
+            "where"     => array(
+                "notes.is_trash = 0 and note_created_by"  => $_SESSION["uid"],
+                " and note_text LIKE" => $requestData['search']['value'] . "%",
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+
+        $getData = easySelectA(array(
+            "table"     => "notes as notes",
+            "fields"    => "note_id, note_type, note_text",
+            "where"     => array(
+                "notes.is_trash = 0 and note_created_by"  => $_SESSION["uid"]
+            ),
+            "orderby"   => array(
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if($getData) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+
+            $allNestedData[] = "";
+            $allNestedData[] = $value["note_id"];
+            $allNestedData[] = $value["note_type"];
+            $allNestedData[] = $value["note_text"];
+             $allNestedData[] = '<div class="btn-group">
+                                    <button type="button" class="btn btn-xs btn-flat btn-primary dropdown-toggle" data-toggle="dropdown">
+                                    action
+                                    <span class="caret"></span>
+                                    <span class="sr-only">Toggle Dropdown</span>
+                                    </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        <li><a class="'. ( current_user_can("customer_support_note.Edit") ? "" : "restricted " ) .'" data-toggle="modal" href="'. full_website_address() .'/xhr/?module=customer-support&page=editNote&id='. $value["note_id"] .'"  data-target="#modalDefault"><i class="fa fa-edit"></i> Edit</a></li>
+                                        <li><a class="'. ( current_user_can("customer_support_note.Delete") ? "" : "restricted " ) .'deleteEntry" href="'. full_website_address() . '/xhr/?module=customer-support&page=deleteNote" data-to-be-deleted="'. $value["note_id"] .'"><i class="fa fa-minus-circle"></i> Delete</a></li>
+                                    </ul>
+                                </div>';
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/***************** Delete Notes or Feedback ****************/
+if(isset($_GET['page']) and $_GET['page'] == "deleteNote") {
+
+    if(current_user_can("customer_support_note.Delete") !== true) {
+        echo '{
+            "title": "Sorry!",
+            "text": "you do not have permission to delete note or feedback.",
+            "showConfirmButton": true,
+            "showCloseButton": true,
+            "toast": false,
+            "icon": "error"
+        }';
+        return;
+    }
+
+    $deleteData = easyDelete(
+        "notes",
+        array(
+            "note_id" => $_POST["datatoDelete"]
+        )
+    );
+
+    if($deleteData === true) {
+        echo '{
+            "title": "The note or feedback has been deleted successfully."
+        }';
+    } 
+}
+
+
+/************************** New Case **********************/
+if(isset($_GET['page']) and $_GET['page'] == "editNote") {
+
+    // select note
+    $note = easySelectA(array(
+        "table"     => "notes",
+        "fields"    => "note_type, note_text",
+        "where"     => array(
+            "note_id"   => $_GET["id"]
+        )
+    ))["data"][0];
+  
+    // Include the modal header
+    modal_header("Edit {$note['note_type']}", full_website_address() . "/xhr/?module=customer-support&page=updateNote");
+    
+    ?>
+      <div class="box-body">
+
+        <div class="form-group required">
+            <label for="noteText"><?php echo __(  ucfirst($note['note_type']) . " text"); ?></label>
+            <textarea name="noteText" id="noteText" cols="30" rows="6" class="form-control"> <?php echo $note['note_text']; ?> </textarea>
+        </div>
+        <input type="hidden" name="note_id" value="<?php echo safe_entities($_GET["id"]); ?>">
+        
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+
+if(isset($_GET['page']) and $_GET['page'] == "updateNote") {
+
+    // update note
+    $updateNote = easyUpdate(
+        "notes",
+        array(
+            "note_text"     => $_POST["noteText"],
+        ),
+        array(
+            "note_id"   => $_POST["note_id"]
+        )
+    );
+
+    if($updateNote !== false) {
+        echo _s("Successfully updated");
+    }
+
+}
+
+
+
+/************************** new Voice Message Entry **********************/
+if(isset($_GET['page']) and $_GET['page'] == "newVoiceMessageEntry") {
+  
+    // Include the modal header
+    modal_header("Add New Voice Messae", full_website_address() . "/xhr/?module=customer-support&page=addNewVoiceMessageEntry");
+    
+    ?>
+      <div class="box-body">
+
+        <div class="form-group required">
+            <label for="vmDescription">Description:</label>
+            <input type="text" name="vmDescription" id="vmDescription" class="form-control">
+        </div>
+        <div class="form-group required">
+            <label for="vmRecord">Record:</label>
+            <input type="file" name="vmRecord" id="vmRecord" class="form-control" accept="audio/*">
+        </div>
+        <div class="form-group required">
+            <label for="vmNumbers">Numbers: </label>
+            <textarea name="vmNumbers" id="vmNumbers" cols="30" rows="8" placeholder="Please enter numbers with comma seperated" class="form-control"></textarea>
+        </div>
+        
+      </div>
+      <!-- /Box body-->
+  
+    <?php
+  
+    // Include the modal footer
+    modal_footer();
+  
+}
+
+
+if(isset($_GET['page']) and $_GET['page'] == "addNewVoiceMessageEntry") {
+
+    if( empty($_POST["vmDescription"]) ) {
+        return _e("Please enter description");
+    } else if( $_FILES["vmRecord"]["size"] < 1 ) {
+        return _e("Please select record");
+    } elseif( empty($_POST["vmNumbers"]) ) {
+        return _e("Please enter numbers");
+    }
+
+
+    // Upload the Record
+    $vmRecord = NULL;
+    if($_FILES["vmRecord"]["size"] > 0) {
+ 
+            $vmRecord = easyUpload(
+                $_FILES["vmRecord"], 
+                "media/sounds/voice-message/",
+                $_POST["vmDescription"]."_". time(),
+                "audio"
+            );
+ 
+            if(!isset($vmRecord["success"])) {
+                return _e($vmRecord);
+            } else {
+                $vmRecord = $vmRecord["fileName"];
+            }
+         
+    }
+
+    // Insert case
+    $insertVoiceMessage = easyInsert(
+        "voice_message",
+        array(
+            "vm_description"    => $_POST["vmDescription"],
+            "vm_record"         => $vmRecord,
+            "vm_added_on"       => date("Y-m-d H:i:s"),
+            "vm_added_by"       => $_SESSION["uid"]
+        ),
+        array(),
+        true
+    );
+
+    if( isset($insertVoiceMessage["status"]) and $insertVoiceMessage["status"] === "success" ) {
+
+        // insert numbers
+        $numbers = explode(",", $_POST["vmNumbers"] );
+
+        $insertNumbers = "INSERT INTO {$table_prefix}calls(
+            call_type,
+            call_status,
+            client_identity,
+            representative,
+            vm_id
+        ) VALUES ";
+
+        foreach($numbers as $number) {
+
+            $insertNumbers .= "(
+                'Voice Message',
+                'Pending',
+                '{$number}',
+                '{$_SESSION["uid"]}',
+                '{$insertVoiceMessage["last_insert_id"]}'
+            ),";
+
+        }
+
+        // Insert numbers in call table
+        $conn->query(substr_replace($insertNumbers, ";", -1, 1));
+
+        echo _s("Case added successfully");
+
+    }
+    
+}
+
+
+/*************************** Representative List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "voiceMessageList") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "vm_added_on",
+        "vm_description",
+        "",
+        "vm_status"
+    );
+    
+    // Count Total recrods
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "voice_message",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+
+    if($requestData['length'] == -1) {
+      $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+
+        $getData = easySelectA(array(
+            "table"     => "voice_message",
+            "fields"    => "vm_id, vm_description, vm_record, vm_status, vm_added_on",
+            "where"     => array(
+                "is_trash = 0",
+                " and vm_description LIKE" => "%". $requestData['search']['value'] . "%",
+            ),
+            "orderby"   => array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+       
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+        $getData = easySelectA(array(
+            "table"     => "voice_message",
+            "fields"    => "vm_id, vm_description, vm_record, vm_status, vm_added_on",
+            "where"     => array(
+                "is_trash = 0"
+            ),
+            "orderby"   => array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "limit" => array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if(isset($getData['count']) and $getData['count'] > 0) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = $value["vm_added_on"];
+            $allNestedData[] = $value["vm_description"];
+            $allNestedData[] = "<audio controls src='". full_website_address() ."/assets/upload/media/sounds/voice-message/{$value["vm_record"]}'></aduio>";
+            $allNestedData[] = $value["vm_status"];
+            $allNestedData[] = "<button class='btn btn-primary startSendingVoiceMessage' value='{$value["vm_id"]}'>Start Sending</button> ";
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+
+/*************************** getVoiceMessageContact List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "getVoiceMessageContact") {
+
+    // Update Voice Message to mark as sending
+    easyUpdate(
+        "voice_message",
+        array(
+            "vm_status" => "sending"
+        ),
+        array(
+            "vm_id" => $_POST["id"]
+        )
+    );
+
+    // Select recrods etc
+    $record = easySelectA(array(
+        "table"     => "voice_message",
+        "fields"    => "vm_description, vm_record",
+        "where"     => array(
+            "vm_id" => $_POST["id"]
+        )
+    ))["data"][0];
+
+    // Select contacts
+    $contacts = easySelectA(array(
+        "table"     => "calls",
+        "fields"    => "client_identity",
+        "where"     => array(
+            "is_trash = 0 and call_status = 'Pending' and vm_id"  => $_POST["id"]
+        )
+    ));
+
+    $data = array(
+        "record"        => $record["vm_record"],
+        "description"   => $record["vm_description"],
+        "contacts"      => array()
+    );
+
+    if($contacts !== false) {
+        foreach($contacts["data"] as $num) {
+            array_push( $data["contacts"], $num["client_identity"] );
+        }
+    }
+    
+
+    echo json_encode($data);
+
+}
+
+
+if(isset($_GET['page']) and $_GET['page'] == "updateCallLog") {
+
+    // update the calls log
+    easyUpdate(
+        "calls",
+        array(
+            "call_datetime"     => date("Y-m-d h:i:s"),
+            "call_direction"    => "Outgoing",
+            "call_status"       => $_POST["status"],
+            "duration"          => $_POST["duration"]
+        ),
+        array(
+            "vm_id"                 => $_POST["vm_id"],
+            " and client_identity"  => $_POST["number"],
+        )
+    );
+
+}
+
+
+/*************************** agentWiseCallStatistics List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "agentWiseCallStatistics") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+
+    // List of all columns name
+    $columns = array(
+        "",
+        "emp_firstname",
+        "talk_time",
+        "total_answered",
+        "total_not_answered",
+        ""
+    );
+    
+    // Count Total recrods
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "sip_credentials",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+
+    if($requestData['length'] == -1) {
+      $requestData['length'] = $totalRecords;
+    }
+ 
+    if(!empty($requestData["search"]["value"]) or !empty($requestData["columns"][1]['search']['value']) ) {  // get data with search
+
+        $dateFilter = "";
+        if(!empty($requestData["columns"][1]['search']['value'])) {
+            $dateRange = explode(" - ", safe_input($requestData["columns"][1]['search']['value']));
+            $dateFilter = "and date(call_datetime) BETWEEN '{$dateRange[0]}' and '{$dateRange[1]}'";
+        }
+
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "emp_firstname, emp_lastname, emp_positions, 
+                            sum( case when call_status = 'Answered' then duration end) as talk_time,
+                            count(*) as total_call,
+                            count( case when call_status = 'Answered' then duration end) as total_answered,
+                            count( case when call_status = 'Missed' then duration end) as total_missed,
+                            count( case when call_status = 'Not Answered' then duration end) as total_not_answered,
+                            count( case when call_status = 'Busy' then duration end) as total_busy,
+                            count( case when call_status = 'Unreachable' then duration end) as total_Unreachable
+                            ",
+            "join"      => array(
+                "left join {$table_prefix}users on representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "calls.is_trash = 0 and emp_firstname like '{$requestData["search"]["value"]}%' $dateFilter"
+            ),
+            "orderby"   => array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "groupby"   => "representative",
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+
+    } else { // Get data withouth search
+
+        $getData = easySelectA(array(
+            "table"     => "calls as calls",
+            "fields"    => "emp_firstname, emp_lastname, emp_positions, 
+                            sum( case when call_status = 'Answered' then duration end) as talk_time,
+                            count(*) as total_call,
+                            count( case when call_status = 'Answered' then duration end) as total_answered,
+                            count( case when call_status = 'Missed' then duration end) as total_missed,
+                            count( case when call_status = 'Not Answered' then duration end) as total_not_answered,
+                            count( case when call_status = 'Busy' then duration end) as total_busy,
+                            count( case when call_status = 'Unreachable' then duration end) as total_Unreachable
+                            ",
+            "join"      => array(
+                "left join {$table_prefix}users on representative = user_id",
+                "left join {$table_prefix}employees on user_emp_id = emp_id",
+            ),
+            "where"     => array(
+                "calls.is_trash = 0"
+            ),
+            "orderby"   => array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            "groupby"   => "representative",
+            "limit" => array(
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        ));
+
+    }
+
+    $allData = [];
+    // Check if there have more then zero data
+    if(isset($getData['count']) and $getData['count'] > 0) {
+        
+        foreach($getData['data'] as $key => $value) {
+
+            // ATT = Average Talk Time
+            $att = (empty($value["talk_time"]) ? 1 : $value["talk_time"]) / (empty($value["total_answered"]) ? 1 : $value["total_answered"]);
+            $attSeconds = round($att) % 60;
+            $att = round(( $att - $attSeconds ) / 60);
+
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = "{$value["emp_firstname"]} {$value["emp_lastname"]}";
+            $allNestedData[] = round($value["talk_time"] / 60) . " min(s)";
+            $allNestedData[] = $att .".". $attSeconds;
+            $allNestedData[] = $value["total_answered"];
+            $allNestedData[] = $value["total_not_answered"];
+            $allNestedData[] = $value["total_busy"];
+            $allNestedData[] = $value["total_missed"];
+            $allNestedData[] = $value["total_Unreachable"];
+            $allNestedData[] = $value["total_call"];
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+
+/*************************** Person List ***********************/
+if(isset($_GET['page']) and $_GET['page'] == "personListForCallCenter") {
+    
+    $requestData = $_REQUEST;
+    $getData = [];
+  
+    // List of all columns name for sorting
+    $columns = array(
+        "",
+        "person_full_name",
+        "person_designation",
+        "institute_name",
+        "person_phone",
+        "person_address"
+    );
+    
+    // Count Total recrods
+    $totalFilteredRecords = $totalRecords = easySelectA(array(
+        "table" => "persons",
+        "fields" => "count(*) as totalRow",
+        "where" => array(
+            "is_trash = 0"
+        )
+    ))["data"][0]["totalRow"];
+  
+    if($requestData['length'] == -1) {
+      $requestData['length'] = $totalRecords;
+    }
+  
+    if(!empty($requestData["search"]["value"])) {  // get data with search
+        
+        $getData = easySelect(
+            "persons as person",
+            "person_id, person_full_name, person_type, person_designation, institute_name, person_phone, person_address, 
+            upazila_name, district_name, division_name",
+            array (
+              "left join {$table_prefix}districts on person_district = district_id",
+              "left join {$table_prefix}divisions on person_division = division_id",
+              "left join {$table_prefix}upazilas on person_upazila = upazila_id",
+              "left join {$table_prefix}institute on person_institute = institute_id",
+            ),
+            array (
+              "person.is_trash = 0 and ( person_full_name LIKE '". safe_input($requestData['search']['value']) ."%' ",
+              " OR person_phone LIKE" => $requestData['search']['value'] . "%",
+              " OR person_email LIKE" => $requestData['search']['value'] . "%",
+              " OR institute_name LIKE" => $requestData['search']['value'] . "%",
+              " )"
+          ),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+    
+        $totalFilteredRecords = $getData ? $getData["count"] : 0;
+  
+    } else { // Get data withouth search
+  
+       $getData = easySelect(
+            "persons as person",
+            "person_id, person_full_name, person_type, person_designation, institute_name, person_phone, person_address, upazila_name, district_name, division_name",
+            array (
+              "left join {$table_prefix}districts on person_district = district_id",
+              "left join {$table_prefix}divisions on person_division = division_id",
+              "left join {$table_prefix}upazilas on person_upazila = upazila_id",
+              "left join {$table_prefix}institute on person_institute = institute_id"
+            ),
+            array("person.is_trash = 0"),
+            array (
+                $columns[$requestData['order'][0]['column']] => $requestData['order'][0]['dir']
+            ),
+            array (
+                "start" => $requestData['start'],
+                "length" => $requestData['length']
+            )
+        );
+  
+    }
+  
+    $allData = [];
+    // Check if there have more then zero data
+    if(isset($getData['count']) and $getData['count'] > 0) {
+        
+        foreach($getData['data'] as $key => $value) {
+            $allNestedData = [];
+            $allNestedData[] = "";
+            $allNestedData[] = "<b>{$value['person_full_name']}</b>, {$value['person_type']} <br/>{$value['person_designation']} {$value['institute_name']}";
+            $allNestedData[] = "{$value['person_phone']}";
+            $allNestedData[] = "{$value['person_address']}, {$value['upazila_name']}, {$value['district_name']}, {$value['division_name']}";
+            $allNestedData[] = '<a data-toggle="modal" href="' . full_website_address() . '/xhr/?module=marketing&page=viewSpecimenProduct&id=' . $value["person_id"] . '"  data-target="#modalDefault">View Specimen</a>';
+            // The action button
+            $allNestedData[] = '<div class="btn-group">
+                                    <button type="button" class="btn btn-xs btn-flat btn-primary dropdown-toggle" data-toggle="dropdown">
+                                    action
+                                    <span class="caret"></span>
+                                    <span class="sr-only">Toggle Dropdown</span>
+                                    </button>
+                                    <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        <li><a class="'. ( current_user_can("persons.Edit") ? "" : "restricted " ) .'" data-toggle="modal" href="'. full_website_address() .'/xhr/?icheck=false&module=marketing&page=editPerson&id='. $value["person_id"] .'"  data-target="#modalDefault"><i class="fa fa-edit"></i> Edit Person</a></li>
+                                        <li><a class="'. ( current_user_can("persons.Delete") ? "" : "restricted " ) .'deleteEntry" href="'. full_website_address() . '/xhr/?module=marketing&page=deletePerson" data-to-be-deleted="'. $value["person_id"] .'"><i class="fa fa-minus-circle"></i> Delete</a></li>
+                                    </ul>
+                                </div>';
+            
+            $allData[] = $allNestedData;
+        }
+    }
+    
+  
+    $jsonData = array (
+        "draw"              => intval( $requestData['draw'] ),
+        "recordsTotal"      => intval( $totalRecords ),
+        "recordsFiltered"   => intval( $totalFilteredRecords ),
+        "data"              => $allData
+    );
+    
+    // Encode in Json Formate
+    echo json_encode($jsonData); 
+
+}
+
+?>
\ No newline at end of file

programming_language: PHP
filename: all-call-history.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,147 @@
+<!-- Content Wrapper. Contains page content -->
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+      <h1>
+        <?= __("Customer Support"); ?>
+        <small><?= __("Call List"); ?></small>
+      </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+      <div class="row">
+        <div class="col-xs-12">
+          <div class="box">
+            <div class="box-header">
+              <h3 class="box-title"><?= __("Call List"); ?></h3>
+              <div class="printButtonPosition"></div>
+            </div>
+            <!-- Box header -->
+            <div class="box-body">
+              <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                <thead>
+                  <tr>
+                    <th></th>
+                    <th class="px120"><?php echo __("Date"); ?></th>
+                    <th class="px85"><?php echo __("Direction"); ?></th>
+                    <th class="px120"><?php echo __("Status"); ?></th>
+                    <th class="px85"><?php echo __("Reason"); ?></th>
+                    <th class="px160"><?php echo __("Client"); ?></th>
+                    <th class="px85"><?php echo __("Client Type"); ?></th>
+                    <th class="px220"><?php echo __("Specimen Products"); ?></th>
+                    <th class="px85"><?php echo __("Duration"); ?></th>
+                    <th class="px220"><?php echo __("Feedback"); ?></th>
+                    <th class="px85"><?php echo __("Specimen Received"); ?></th>
+                    <th class="px85"><?php echo __("Informative"); ?></th>
+                    <th class="px85"><?php echo __("Sale Our Book"); ?></th>
+                    <th class="px85"><?php echo __("Use Our Book"); ?></th>
+                    <th class="px85"><?php echo __("MR Feedback"); ?></th>
+                    <th class="px85"><?php echo __("Other Info"); ?></th>
+                    <th class="px85"><?php echo __("Perform By"); ?></th>
+                  </tr>
+                </thead>
+   
+                <tfoot>
+                  <tr>
+                    <th></th>
+                    <th class="no-print">
+                        <input type="text" placeholder="<?= __("Select Date"); ?>" name="callDate" id="callDate" class="form-control" autocomplete="off">
+                    </th>
+                    <th> 
+                        <select name="callDirection" id="callDirection" class="form-control select2" style="width: 100%">
+                            <option value="">Direction...</option>
+                            <?php
+                                $callDirection = array('Outgoing', 'Incoming');
+                                foreach($callDirection as $Direction) {
+                                    echo "<option value='{$Direction}'>{$Direction}</option>";
+                                }
+                            ?>
+                      </select>
+                    </th>
+                    <th class="no-print"> 
+                        <select name="callStatus" id="callStatus" class="form-control select2" style="width: 100%">
+                            <option value="">Status...</option>
+                            <?php
+                                $callStatus = array('Answered', 'Missed', 'Rejected', 'Not Answered', 'Busy', 'Unreachable', 'Pending');
+                                foreach($callStatus as $status) {
+                                    echo "<option value='{$status}'>{$status}</option>";
+                                }
+                            ?>
+                      </select>
+                    </th>
+                    <th>
+                        <select id="callReasonFilter" class="form-control select2Ajax" select2-tag="true" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=callReasonList" style="width: 100%;">
+                            <option value=""><?= __("All Reason"); ?>...</option>
+                        </select>
+                    </th>
+                    <th><?php echo __("Client"); ?></th>
+                    <th class="no-print"> 
+                        <select id="clientType" class="form-control select2" style="width: 100%">
+                            <option value="">Type...</option>
+                            <?php
+                                $personType = array('Teacher', 'Student', 'Guardian', 'Service Holder', 'Merchant');
+                                foreach($personType as $type) {
+                                    echo "<option value='{$type}'>{$type}</option>";
+                                }
+                            ?>
+                      </select>
+                    </th>
+                    <th><?php echo __("Specimen Products"); ?></th>
+                    <th><?php echo __("Duration"); ?></th>
+                    <th><?php echo __("Feedback"); ?></th>
+                    <th>
+                        <select id="specimenReceivedFilter" class="form-control select2" style="width: 100%">
+                            <option value="">All...</option>
+                            <?php
+                                $sr = array('Yes', 'No', 'Partial', 'Not Sure');
+                                foreach($sr as $sr) {
+                                    echo "<option value='{$sr}'>{$sr}</option>";
+                                }
+                            ?>
+                      </select>
+                    </th>
+                    <th><?php echo __("Informative"); ?></th>
+                    <th><?php echo __("Sale Our Book"); ?></th>
+                    <th><?php echo __("Use Our Book"); ?></th>
+                    <th><?php echo __("MR Feedback"); ?></th>
+                    <th><?php echo __("Other Info"); ?></th>
+                    <th class="no-print">
+                        <select name="callPerformBy" id="callPerformBy" class="form-control select2" style="width: 100%">
+                                <option value="">All...</option>
+                                <?php
+                                    $representative = easySelectA(array(
+                                        "table"     => "sip_credentials",
+                                        "fields"    => "sip_representative, concat(emp_firstname, ' ', emp_lastname) as representative_name",
+                                        "join"      => array(
+                                            "left join {$table_prefix}users on sip_representative = user_id",
+                                            "left join {$table_prefix}employees on user_emp_id = emp_id"
+                                        )
+                                    ));
+                                    foreach($representative["data"] as $representative) {
+                                        echo "<option value='{$representative["sip_representative"]}'>{$representative["representative_name"]}</option>";
+                                    }
+                                ?>
+                        </select>
+                    </th>
+                  </tr>
+                </tfoot>
+              </table>
+            </div>
+            <!-- box body-->
+          </div>
+          <!-- box -->
+        </div>
+        <!-- col-xs-12-->
+      </div>
+      <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+  </div>
+  <!-- /.content-wrapper -->
+  <script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=allCallList";
+    BMS.FUNCTIONS.dateRangePickerPreDefined({selector: "#callDate"});
+  </script>

programming_language: PHP
filename: call-center-old.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,559 @@
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+
+    <?php
+
+    $selectSipCredentials = easySelectA(array(
+        "table"     => "sip_credentials",
+        "fields"    => "sip_username, sip_password, sip_domain, sip_websocket_addr",
+        "where"     => array(
+            "sip_representative"    => $_SESSION["uid"]
+        )
+    ));
+
+    if ($selectSipCredentials !== false) {
+        $sip = $selectSipCredentials["data"][0];
+        echo "<script> const sipCredentials = {
+                uri: 'sip:{$sip['sip_username']}@{$sip['sip_domain']}',
+                socket: '{$sip['sip_websocket_addr']}',
+                user: '{$sip['sip_username']}',
+                pass: '{$sip['sip_password']}'
+            }; </script>";
+    }
+
+    $getExtentionNumber = easySelectA(array(
+        "table"     => "sip_credentials as sip_credential",
+        "fields"    => "sip_username as extention, concat(emp_firstname, ' ', emp_lastname) as name",
+        "join"      => array(
+            "left join {$table_prefix}users on sip_representative = user_id",
+            "left join {$table_prefix}employees on user_emp_id = emp_id",
+        ),
+        "where" => array(
+            "sip_credential.is_trash = 0"
+        )
+    ));
+
+    if ($getExtentionNumber !== false) {
+
+        echo "<script> const extentionNumbers = " . json_encode($getExtentionNumber["data"]) . "; </script>";
+    }
+
+    ?>
+    <!-- Content Wrapper. Contains page content -->
+    <script async src="<?php echo full_website_address(); ?>/js/?q=cs&v=2.1.8"></script>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+
+        <div class="row" id="customerSupport" style="position: fixed; top: 50px; z-index: 5; background-color: #ecf0f5; width: 88%; padding-top: 15px">
+
+            <section style="padding: 0px 15px 15px 15px;" class="content-header">
+                <h1>
+                    <?php echo __("Customer Support"); ?>
+                </h1>
+            </section>
+
+            <div class="col-md-3">
+
+                <div id="callDailer" class="input-group">
+                    <input id="callNumber" placeholder="Please enter number here.." type="text" value="" class="form-control">
+                    <span class="input-group-btn">
+                        <button id="callButton" type="button" class="btn btn-success btn-flat"><i class="fa fa-fw fa-phone"></i> Call</button>
+                        <button style="display: none;" id="hangButton" type="button" class="btn btn-danger btn-flat"><i class="fa fa-fw fa-phone"></i> End</button>
+                    </span>
+                </div>
+
+                <div style="min-height: 80px; margin-left: 10px;">
+
+                    <h3 style="margin-top: 15px;" id="status">Dail a number!</h3>
+                    <?php
+                    if ($selectSipCredentials === false) {
+                        _e("Sorry! No credentials found. This module will not work.");
+                    }
+                    ?>
+                    <div style="padding: 5px; display: none;" class="dndAlert alert-danger">Do not Disturb mode is enabled. No incoming call will work.</div>
+
+                    <h3 style="margin: 0; display: none" id="timer">00:00:00</h3>
+                    <div style="display: none; height: 70px; margin-top: 12px;" id="callReceiver">
+
+                        <button id="callReceiveButton" type="button" class="btn btn-success btn-flat"><i class="fa fa-fw fa-phone"></i> Accept</button>
+                        <button id="IncomingCallHangButton" type="button" class="btn btn-danger btn-flat"><i class="fa fa-fw fa-phone"></i> Reject</button>
+
+                    </div>
+
+                </div>
+
+
+                <!-- Action Buttons -->
+                <a id="muteCall" class="btn btn-app">
+                    <i class="fa fa-microphone"></i> Mute
+                </a>
+                <a id="unmuteCall" style="display: none;" class="btn btn-app">
+                    <i class="fa fa-microphone-slash"></i> Unmute
+                </a>
+                <a id="holdCall" class="btn btn-app">
+                    <i class="fa fa-pause"></i> Hold
+                </a>
+                <a id="unholdCall" style="display: none;" class="btn btn-app">
+                    <i class="fa fa-play"></i> Unhold
+                </a>
+                <a id="transferCall" class="btn btn-app">
+                    <i class="fa fa-arrow-up"></i> Transfer
+                </a>
+                <a id="enableDND" class="btn btn-app">
+                    <i class="fa fa-bell-slash"></i> Enable DND
+                </a>
+                <a id="disableDND" style="display: none;" class="btn btn-app">
+                    <i class="fa fa-bell"></i> Disable DND
+                </a>
+
+                <div style="margin-top: 15px; margin-left: 10px;" class="form-group">
+                    <button id="addNewCase" class="btn btn-primary">Add Case/ Issue</button>
+                    <a data-toggle="modal" data-target="#modalDefault" href="<?php echo full_website_address(); ?>/xhr/?module=marketing&page=newPerson" class="btn btn-primary"><?= __("New Lead"); ?></a>
+                    <!-- <button class="btn btn-primary">View Specimen Copies</button> -->
+                </div>
+
+            </div>
+
+            <div class="col-md-3">
+
+                <div class="box box-info">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Caller Info"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table class="table callerInfo">
+                            <tr>
+                                <td><?php echo __("Name:"); ?></td>
+                                <td></td>
+                            </tr>
+                            <tr>
+                                <td><?php echo __("Type:"); ?></td>
+                                <td></td>
+                            </tr>
+                            <tr>
+                                <td><?php echo __("Desig."); ?></td>
+                                <td></td>
+                            </tr>
+                            <tr>
+                                <td><?php echo __("Address:"); ?></td>
+                                <td></td>
+                            </tr>
+                            <tr>
+                                <td><?php echo __("Last Call:"); ?></td>
+                                <td></td>
+                            </tr>
+                        </table>
+
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+            </div>
+
+            <div class="col-md-3">
+
+                <div class="box box-danger">
+                    <!-- Box header -->
+                    <div class="box-header with-border">
+                        <h3 class="box-title"><?= __("FeedBack"); ?></h3>
+                    </div>
+
+                    <div class="box-body">
+
+                        <div class="form-group">
+                            <textarea name="feedbackArea" id="feedbackArea" cols="30" rows="6" placeholder="Enter feedback here..." class="form-control"></textarea>
+                        </div>
+                        <!-- <div style="margin-bottom: 5px;" class="form-group">
+                              <select name="feedbackReviewer" id="feedbackReviewer" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                                  <option value=""><?= __("Select feedback reviewer"); ?>....</option>
+                              </select>
+                          </div> -->
+                        <div class="row">
+                            <div class="col-md-8">
+                                <div class="form-group">
+                                    <input type="text" placeholder="Caller" name="feedbackCaller" id="feedbackCaller" class="form-control">
+                                </div>
+                            </div>
+                            <div class="col-md-4">
+                                <input id="saveFeedback" type="button" value="Save" class="btn btn-primary">
+                            </div>
+                        </div>
+
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+            </div>
+
+            <div class="col-md-3">
+
+                <div class="box box-primary">
+
+                    <!-- Box header -->
+                    <!-- Box header -->
+                    <div class="box-header with-border">
+                        <h3 class="box-title"><?= __("Message"); ?></h3>
+                    </div>
+
+                    <div class="box-body">
+
+                        <div class="form-group">
+
+                            <textarea name="csSmsText" id="csSmsText" cols="30" rows="6" placeholder="Enter text here..." class="form-control"></textarea>
+                        </div>
+
+                        <div class="row">
+                            <div class="col-md-8">
+                                <div class="form-group">
+                                    <input type="text" placeholder="Enter recipient number" name="csSmsSendTo" id="csSmsSendTo" class="form-control">
+                                </div>
+                            </div>
+                            <div class="col-md-4">
+                                <input id="csSendSMS" type="button" value="Send SMS" class="btn btn-primary">
+                            </div>
+                        </div>
+
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+            </div>
+
+        </div>
+
+        <div style="height: 310px;"></div>
+        <br />
+
+        <div id="test" class="row">
+
+            <div class="col-md-6">
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Person List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body personList">
+                        <table dt-height="30vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=personListForCallCenter" dt-disable-on-type-search class="dataTableWithAjaxExtend table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th><?= __("Person Details"); ?></th>
+                                    <th><?= __("Phone"); ?></th>
+                                    <th><?= __("Address"); ?></th>
+                                    <th><?= __("Specimen Products"); ?></th>
+                                    <th class="no-print no-sort" width="100px"><?= __("Action"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th><?= __("Person Details"); ?></th>
+                                    <th><?= __("Phone"); ?></th>
+                                    <th><?= __("Address"); ?></th>
+                                    <th><?= __("Specimen Products"); ?></th>
+                                    <th><?= __("Action"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Marketing Representative List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table dt-height="30vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=representativeList" dt-disable-on-type-search class="dataTableWithAjaxExtend addToSMSBox table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th width="30px"><?= __("ID"); ?></th>
+                                    <th class="no-sort" width="80px"><?= __("Photo"); ?></th>
+                                    <th><?php echo __("Name"); ?></th>
+                                    <th><?php echo __("Working Area"); ?></th>
+                                    <th><?php echo __("Contact Number"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th><?php echo __("Name"); ?></th>
+                                    <th><?php echo __("Working Area"); ?></th>
+                                    <th><?php echo __("Contact Number"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Library List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table dt-height="30vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=peoples&page=customerList" dt-disable-on-type-search class="dataTableWithAjaxExtend table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th class="col-md-3"><?= __("Name"); ?></th>
+                                    <th><?= __("District"); ?></th>
+                                    <th><?= __("Division"); ?></th>
+                                    <th><?= __("Address"); ?></th>
+                                    <th class="col-md-1"><?= __("Contact"); ?></th>
+                                    <th class="hideit no-print no-sort" width="100px"><?= __("Action"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th><?= __("Customer Name"); ?></th>
+                                    <th><?= __("District"); ?></th>
+                                    <th><?= __("Division"); ?></th>
+                                    <th><?= __("Address"); ?></th>
+                                    <th><?= __("Contact"); ?></th>
+                                    <th><?= __("Action"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+
+
+
+            </div>
+            <!-- col-md-6-->
+
+            <div class="col-md-6">
+
+                <div class="row">
+
+                    <div class="col-md-6">
+
+                        <div class="box">
+                            <div class="box-header with-border">
+                                <h3 class="box-title"><?= __("Quick Feedback"); ?></h3>
+                            </div>
+                            <!-- Box header -->
+                            <div style="max-height: 220px; overflow: auto;" class="box-body quickFeedback">
+
+                                <ul class="todo-list">
+                                    <?php
+                                    $selectFeedback = easySelectA(array(
+                                        "table"     => "notes",
+                                        "fields"    => "note_text",
+                                        "where"     => array(
+                                            "is_trash = 0 and note_type = 'feedback' and note_created_by"   => $_SESSION["uid"]
+                                        )
+                                    ));
+
+                                    if ($selectFeedback !== false) {
+
+                                        foreach ($selectFeedback["data"] as $fKey => $fValue) {
+                                            echo '<li style="cursor:pointer;">' . $fValue["note_text"] . '</li>';
+                                        }
+                                    }
+
+                                    ?>
+
+                                    <li style="cursor:pointer; text-align: center;"><i class="fa fa-plus-circle"></i> Add New</li>
+
+                                </ul>
+
+                            </div>
+                            <!-- box body-->
+                        </div>
+                        <!-- box -->
+
+                    </div>
+
+                    <div class="col-md-6">
+
+                        <div class="box">
+                            <div class="box-header with-border">
+                                <h3 class="box-title"><?= __("Note"); ?></h3>
+                            </div>
+                            <!-- Box header -->
+                            <div style="max-height: 220px; overflow: auto;" class="box-body userNote">
+                                <ul class="todo-list">
+                                    <?php
+                                    $selectFeedback = easySelectA(array(
+                                        "table"     => "notes",
+                                        "fields"    => "note_text",
+                                        "where"     => array(
+                                            "is_trash = 0 and note_type = 'note' and note_created_by"   => $_SESSION["uid"]
+                                        )
+                                    ));
+
+                                    if ($selectFeedback !== false) {
+
+                                        foreach ($selectFeedback["data"] as $fKey => $fValue) {
+                                            echo '<li style="cursor:pointer;">' . $fValue["note_text"] . '</li>';
+                                        }
+                                    }
+
+                                    ?>
+
+                                    <li style="cursor:pointer; text-align: center;"><i class="fa fa-plus-circle"></i> Add New</li>
+
+                                </ul>
+
+                            </div>
+                            <!-- box body-->
+                        </div>
+                        <!-- box -->
+
+                    </div>
+
+                </div>
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Case List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body caseList">
+                        <table dt-height="40vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=caseList" dt-disable-on-type-search class="dataTableWithAjaxExtend table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th><?php echo __("Date"); ?></th>
+                                    <th><?php echo __("Requester"); ?></th>
+                                    <th><?php echo __("Title"); ?></th>
+                                    <th><?php echo __("Priority"); ?></th>
+                                    <th><?php echo __("Type"); ?></th>
+                                    <th><?php echo __("Status"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th><?php echo __("Date"); ?></th>
+                                    <th><?php echo __("Requester"); ?></th>
+                                    <th><?php echo __("Title"); ?></th>
+                                    <th><?php echo __("Priority"); ?></th>
+                                    <th><?php echo __("Type"); ?></th>
+                                    <th><?php echo __("Status"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Product List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table dt-height="40vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=productList" dt-disable-on-type-search class="dataTableWithAjaxExtend table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th style="width: 150px;"><?= __("Product Name"); ?></th>
+                                    <th style="width: 100px;"><?= __("Edition"); ?></th>
+                                    <th style="width: 120px;"><?= __("Category"); ?></th>
+                                    <th style="width: 300px;"><?= __("Description"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th><?= __("Product Name"); ?></th>
+                                    <th>
+                                        <select name="productEdition" id="productEdition" class="form-control select2">
+                                            <option value=""><?= __("All Ed."); ?></option>
+                                            <?php
+
+                                            $selectProductYear = easySelectA(array(
+                                                "table"   => "products",
+                                                "fields"  => "product_edition",
+                                                "groupby" => "product_edition"
+                                            ));
+
+                                            if ($selectProductYear) {
+                                                foreach ($selectProductYear["data"] as $key => $value) {
+                                                    echo "<option value='{$value['product_edition']}'>{$value['product_edition']}</option>";
+                                                }
+                                            }
+
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th>
+                                        <select name="productCategory" id="productCategory" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address(); ?>/info/?module=select2&page=productCategoryList">
+                                            <option value=""><?= __("Category"); ?>...</option>
+                                        </select>
+                                    </th>
+                                    <th><?= __("Description"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+
+
+
+            </div>
+            <!-- col-md-6-->
+
+        </div>
+        <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+</div>
+<!-- /.content-wrapper -->
+<script>
+    // request permission on page load
+    document.addEventListener('DOMContentLoaded', function() {
+
+        if (!Notification) {
+            alert('Desktop notifications not available in your browser.');
+            return;
+        }
+
+        if (Notification.permission !== 'granted') {
+            Notification.requestPermission();
+        }
+
+        // Enable / Disable DND when page is load
+        if( get_options("dnd") === "enable" ) {
+
+            $("#enableDND").hide();
+            $("#disableDND").show();
+            $(".dndAlert").show();
+
+        } else {
+            
+            $("#disableDND").hide();
+            $("#enableDND").show();
+
+        }
+
+    });
+</script>
\ No newline at end of file

programming_language: PHP
filename: call-center.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,850 @@
+<style>
+    
+    .tab-pane .row {
+        margin-top: 10px;
+    }
+
+    .message-item, .call-item {
+        border-bottom: 1px solid whitesmoke;
+        padding: 5px 0;
+    }
+    .message-item p, .call-item p {
+        margin: 2px;
+    }
+
+    .cc-title {
+        margin: 0; 
+        padding-bottom: 10px; 
+        font-size: 20px; 
+        border-bottom: 1px solid #dcdbdb;
+    }
+
+    .numberSearch {
+        padding: 18px 0;
+    }
+
+    .number-dialer-div {
+        border: 1px solid #d2d6de;
+        position: absolute;
+        z-index: 1;
+    }
+
+    .number-dialer-div:focus-within {
+        border-color:#3c8dbc;
+    }
+
+    .number-dialer-div * {
+        border: none;
+    }
+
+    .disable-number-dialer-div {
+        background-color: #eeeeee !important;
+        cursor: not-allowed;
+    }
+
+    .suggestion-numbers {
+        display: none;
+        max-height: 340px;
+        overflow: auto;
+        background-color: white;
+        padding: 10px;
+        box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px, rgba(0, 0, 0, 0.07) 0px 2px 2px, rgba(0, 0, 0, 0.07) 0px 4px 4px, rgba(0, 0, 0, 0.07) 0px 8px 8px, rgba(0, 0, 0, 0.07) 0px 16px 16px;
+    }
+
+    .suggestion-numbers .item {
+        padding: 10px 0 10px 5px;
+        position: relative;
+    }
+
+    .suggestion-numbers .item:not(:last-child) {
+        border-bottom: 1px solid #dcdbdb;
+    }
+
+    .suggestion-numbers .item span {
+        display: block;
+        color: #2e82b2;
+        font-weight: bold;
+        cursor: pointer;
+    }
+
+    .suggestion-numbers .item > button {
+        position: absolute;
+        right: .5em;
+        top: 50%;
+        transform: translate(0,-50%);
+    }
+
+    .call-controller {
+        margin-top: 55px;
+    }
+
+    .call-dialer {
+        min-height: 80px;
+        margin-bottom: 10px;
+        text-align: center;
+    }
+
+    .statistics {
+        position: absolute;
+        width: 100%;
+        bottom: -30px;
+        /* background-color: #ecf0f5; */
+        /* height: 120px; */
+    }
+
+    .agent-live-stats-box {
+        height: 410px;
+        overflow: auto;
+        margin-top: 10px;
+    }
+
+    .agent-live-stats-box p {
+        margin: 0;
+    }
+
+    .agent-live-stats-box .name {
+        font-size: 18px;
+    }
+
+    .agent-live-stats-box .agent {
+        padding: 12px 0;
+        margin: 0;
+    }
+
+    .agent-live-stats-box .agent:not(:last-child) {
+        border-bottom: 1px solid #dcdbdb;
+    }
+
+
+    .call-history {
+        max-height: 320px;
+        overflow: auto;
+    }
+
+
+
+</style>
+
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+
+    <?php
+
+    $selectSipCredentials = easySelectA(array(
+        "table"     => "sip_credentials",
+        "fields"    => "sip_username, sip_password, sip_domain, sip_websocket_addr",
+        "where"     => array(
+            "sip_representative"    => $_SESSION["uid"]
+        )
+    ));
+
+    if ($selectSipCredentials !== false) {
+        $sip = $selectSipCredentials["data"][0];
+        echo "<script> const sipCredentials = {
+                uri: 'sip:{$sip['sip_username']}@{$sip['sip_domain']}',
+                socket: '{$sip['sip_websocket_addr']}',
+                user: '{$sip['sip_username']}',
+                pass: '{$sip['sip_password']}'
+            }; </script>";
+    }
+
+    $getExtentionNumber = easySelectA(array(
+        "table"     => "sip_credentials as sip_credential",
+        "fields"    => "sip_username as extention, concat(emp_firstname, ' ', emp_lastname) as name",
+        "join"      => array(
+            "left join {$table_prefix}users on sip_representative = user_id",
+            "left join {$table_prefix}employees on user_emp_id = emp_id",
+        ),
+        "where" => array(
+            "sip_credential.is_trash = 0"
+        )
+    ));
+
+    if ($getExtentionNumber !== false) {
+
+        echo "<script> const extentionNumbers = " . json_encode($getExtentionNumber["data"]) . "; </script>";
+    }
+
+    ?>
+    <!-- Content Wrapper. Contains page content -->
+    <script async src="<?php echo full_website_address(); ?>/js/?q=cs&v=2.2.6"></script>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+
+      
+        <!-- Left Column -->
+        <div style="height: 86vh" class="col-lg-3 col-md-4">
+
+            <div class="number-dialer-div">
+                <div class="input-group">
+                    <span class="input-group-addon">
+                        <i class="fa fa-search"></i>
+                    </span>
+                    <input type="text" placeholder="Type name or number" class="form-control numberSearch">
+                    <span class="input-group-addon">
+                        <i class="fa fa-caret-down"></i>
+                    </span>
+                </div>
+                <div class="suggestion-numbers"> </div>
+
+            </div>
+
+
+            <div class="call-controller">
+
+
+                <h3 style="margin-top: 10px; margin-bottom: 15px;" id="status"></h3>
+                <h3 style="margin: 0 0 15px 0; display: none;" id="timer">00:00:00</h3>
+                
+
+                <div class="call-dialer">
+                    
+                    <button id="callButton" type="button" class="btn btn-success btn-flat"><i class="fa fa-fw fa-phone"></i> Dial</button>
+                    <button style="display: none;" id="hangButton" type="button" class="btn btn-danger btn-flat"><i class="fa fa-fw fa-phone"></i> End Call</button>
+
+                </div>
+
+                <div style="display: none; min-height: 80px;" id="callReceiver">
+                    
+                    <button id="callReceiveButton" type="button" class="btn btn-success btn-flat"><i class="fa fa-fw fa-phone"></i> Accept</button>
+                    <button id="IncomingCallHangButton" type="button" class="btn btn-danger btn-flat"><i class="fa fa-fw fa-phone"></i> Reject</button>
+
+                </div>
+                
+                <div class="row">
+                    <!-- Action Buttons -->
+                    <a id="muteCall" class="btn btn-app">
+                        <i class="fa fa-microphone"></i> Mute
+                    </a>
+                    <a id="unmuteCall" style="display: none;" class="btn btn-app">
+                        <i class="fa fa-microphone-slash"></i> Unmute
+                    </a>
+                    <a id="holdCall" class="btn btn-app">
+                        <i class="fa fa-pause"></i> Hold
+                    </a>
+                    <a id="unholdCall" style="display: none;" class="btn btn-app">
+                        <i class="fa fa-play"></i> Unhold
+                    </a>
+                    <a id="transferCall" class="btn btn-app">
+                        <i class="fa fa-arrow-up"></i> Transfer
+                    </a>
+                    <a id="enableDND" class="btn btn-app">
+                        <i class="fa fa-bell-slash"></i> Enable DND
+                    </a>
+                    <a id="disableDND" style="display: none;" class="btn btn-app">
+                        <i class="fa fa-bell"></i> Disable DND
+                    </a>
+                </div>
+
+                <div style="margin-top: 15px; margin-left: 10px;" class="form-group">
+                    <button id="addNewCase" class="btn btn-primary">Add Case/ Issue</button>
+                    <a data-toggle="modal" data-target="#modalDefault" href="<?php echo full_website_address(); ?>/xhr/?module=marketing&page=newPerson" class="btn btn-primary"><?= __("New Lead"); ?></a>
+                    <!-- <button class="btn btn-primary">View Specimen Copies</button> -->
+                </div>
+
+
+                <?php
+                if ($selectSipCredentials === false) {
+                    _e("Sorry! No credentials found. This module will not work.");
+                }
+                ?>
+                <div style="padding: 5px; display: none; margin-top: 10px;" class="dndAlert alert-danger">Do not Disturb mode is enabled. No incoming call will work.</div>
+
+            </div>
+
+            <?php if(current_user_can("customer_support_dashboard.View")) { ?>
+                <div style="position: absolute; bottom: -25px; width: 95%;" class="box box-success">
+
+                    <div class="box-header with-border">
+                        <h3 class="box-title">Live status</h3>
+                    </div>
+                    <div class="box-body agent-live-stats-box">
+
+                        <?php 
+                            $selectUserExtension = easySelectA(array(
+                                "table"     => "sip_credentials as sip",
+                                "fields"    => "sip_username as ext, emp_id, emp_firstname, emp_lastname",
+                                "join"      => array(
+                                    "left join {$table_prefix}users as user on user_id = sip_representative",
+                                    "left join {$table_prefix}employees on emp_id = user_emp_id"
+                                ),
+                                "where" => array(
+                                    "user.is_trash = 0 and user_status = 'Active'"
+                                )
+                            ));
+
+                            if( $selectUserExtension !== false ) {
+
+                                foreach($selectUserExtension["data"] as $key => $agent ) {
+
+                                    echo "<div class='row agent'>
+                                            <div class='col-md-3'>
+                                                <img width='50px' height='50px' src='". full_website_address() ."/images/?for=employees&id={$agent["emp_id"]}' class='img-circle' />
+                                            </div>
+                                            <div class='col-md-9'>
+                                                <p class='name'>{$agent['emp_firstname']} {$agent['emp_lastname']}</p>
+                                                <p class='agentExt{$agent['ext']}'>Available</p>
+                                            </div> 
+                                        </div>";
+
+                                }
+
+                            }
+
+                        ?>
+
+                        
+
+                    </div>
+
+                </div>
+            
+            <?php } ?>
+
+            
+        
+        </div>
+
+        <!-- Right Column -->
+        <div style="height: 85vh;" class="col-lg-9 col-md-8">
+
+            <div class="nav-tabs-custom">
+                <ul class="nav nav-tabs call-center-tabs">
+                    <li class=""> <a href="#tab_script" data-toggle="tab">Script</a> </li>
+                    <li class="" > <a href="#tab_leads" data-toggle="tab">Leads</a> </li>
+                    <li class="active"> <a href="#tab_messages" data-toggle="tab">Messages <span class="tabMessageCount"></span> </a> </li>
+                    <li class="hidden_tab" style="display: none;"> <a href="#tab_products" data-toggle="tab">Products</a> </li>
+                    <li class="hidden_tab" style="display: none;" class='feedback_tab'> <a href="#tab_feedback" data-toggle="tab">Feedback</a> </li>
+                </ul>
+                <div class="tab-content">
+
+                    <div class="tab-pane" id="tab_script">
+
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+                        <p>Bangladesh is a land of rivers. Most of her lands are lowings</p>
+
+                    </div> <!-- End Script Tab -->
+
+                    <div class="tab-pane" id="tab_leads">
+
+                        <div class="row">
+
+                            <div class="col-md-8">
+                                
+                                <table class="table callerInfo">
+                                    <tr>
+                                        <td><?php echo __("Name:"); ?></td>
+                                        <td></td>
+                                    </tr>
+                                    <tr>
+                                        <td><?php echo __("Type:"); ?></td>
+                                        <td></td>
+                                    </tr>
+                                    <tr>
+                                        <td><?php echo __("Desig."); ?></td>
+                                        <td></td>
+                                    </tr>
+                                    <tr>
+                                        <td><?php echo __("Address:"); ?></td>
+                                        <td></td>
+                                    </tr>
+                                    <tr>
+                                        <td><?php echo __("Action"); ?></td>
+                                        <td></td>
+                                    </tr>
+          
+                                </table>
+
+                                <div style="display: none" class="dataToCopy">
+
+                                </div>
+
+                                <br/>
+                                <h2 class="cc-title"><?= __("Order/ Service"); ?></h3>
+                                <table class="table callerOrderInfo">
+                                    <thead>
+                                        <tr>
+                                            <th><?php echo __("Date"); ?></th>
+                                            <th><?php echo __("Reference"); ?></th>
+                                            <th><?php echo __("Amount"); ?></th>
+                                            <th><?php echo __("Payment"); ?></th>
+                                            <th style="width: 220px;" type="select" 
+                                                data-options="Order Placed,In Production,Processing,Call not Picked,Confirmed,Hold,Delivered,Cancelled"
+                                                where-to-update="<?php echo full_website_address(); ?>/xhr/?module=my-shop&page=changeSaleStatus"
+                                                class="sort text-center no-print"><?php echo __("Status"); ?>
+                                            </th>
+                                            <th><?php echo __("Action"); ?></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <tr><td class="text-center" colspan="5">Sorry! No order found.</td></tr>
+                                    </tbody>
+                                </table>
+
+                            </div>
+                            <div class="col-md-4">
+
+                                <h2 class="cc-title"><?= __("Call History"); ?> <small style="font-weight: bold" class="call-count"></small> </h3>
+                                <div class="call-history">
+
+                                    <p>No call</p>
+                                    
+                                </div>
+
+                                <br/>
+                                <h2 class="cc-title"><?= __("Cases"); ?></h3>
+                                <div class="case-history">
+
+                                    <p>No Cases</p>
+                                    
+                                </div>
+
+                            </div>
+
+                        </div>
+
+                    </div> <!-- End Leads Tab -->
+
+                    <div class="tab-pane active" id="tab_messages">
+                        
+                        <div class="row">
+
+                            <!-- Send Message Box -->
+                            <div class="col-md-6">
+
+                                <br/>
+                                <div class="form-group">
+                                    <textarea name="csSmsText" id="csSmsText" cols="30" rows="6" placeholder="Enter text here..." class="form-control"></textarea>
+                                </div>
+
+                                <div class="row">
+                                    <div class="col-md-8">
+                                        <div class="form-group">
+                                            <input type="text" placeholder="Enter recipient number" name="csSmsSendTo" id="csSmsSendTo" class="form-control">
+                                        </div>
+                                    </div>
+                                    <div class="col-md-4">
+                                        <input id="csSendSMS" type="button" value="Send SMS" class="btn btn-primary">
+                                    </div>
+                                </div>
+                                
+                            </div> <!-- End Send Message Box -->
+                            
+
+                            <div class="col-md-6">
+
+                                <h2 class="cc-title"><?= __("Notes"); ?></h3>
+                                <div style="max-height: 220px; overflow: auto;" class="box-body userNote">
+
+                                    <ul class="todo-list">
+                                        <?php
+                                        $selectFeedback = easySelectA(array(
+                                            "table"     => "notes",
+                                            "fields"    => "note_text",
+                                            "where"     => array(
+                                                "is_trash = 0 and note_type = 'note' and note_created_by"   => $_SESSION["uid"]
+                                            )
+                                        ));
+
+                                        if ($selectFeedback !== false) {
+
+                                            foreach ($selectFeedback["data"] as $fKey => $fValue) {
+                                                echo '<li style="cursor:pointer;">' . $fValue["note_text"] . '</li>';
+                                            }
+                                        }
+
+                                        ?>
+
+                                        <li style="cursor:pointer; text-align: center;"><i class="fa fa-plus-circle"></i> Add New</li>
+
+                                    </ul>
+
+                                </div>
+                                
+                                <br/>
+                                <h2 class="cc-title"><?= __("Message History"); ?></h3>
+                                <div class="message-history">
+
+                                    <p>No SMS</p>
+                                    
+                                </div>
+
+                            </div>
+
+
+                        </div>
+
+                    </div> <!-- End Message Tab -->
+
+                    <div class="tab-pane" id="tab_products">
+                        
+                    </div> <!-- End Products Tab -->
+
+                    <div class="tab-pane" id="tab_feedback">
+
+                        <div class="row" style="margin-left: 0;">
+
+                            <div class="col-md-6">
+
+                                <div class="form-group">
+                                    <label for="callFeedback"><?= __("Call Feedback"); ?></label>
+                                    <textarea name="callFeedback" id="callFeedback" cols="30" rows="5" placeholder="Enter feedback here..." class="form-control"></textarea>
+                                </div>
+                                
+                                
+                                <div class="row">
+
+                                    <div class="form-group col-md-6">
+                                        <label for="callReason"><?= __("Call Reason"); ?></label>
+                                        <select name="callReason[]" id="callReason" class="form-control select2Ajax" select2-tag="true" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=callReasonList" style="width: 100%;">
+                                            <option value=""><?= __("Select Reason"); ?>....</option>
+                                        </select>
+                                    </div>
+
+                                    <div class="form-group col-md-6">
+                                        <label for="specimenCopyReceived"><?= __("Specimen Copy Received"); ?></label>
+                                        <select name="specimenCopyReceived" id="specimenCopyReceived" class="form-control">
+                                            <option value="">Select one...</option>
+                                            <option value="No">No</option>
+                                            <option value="Yes">Yes</option>
+                                            <option value="Partial">Partial</option>
+                                            <option value="Not Sure">Not Sure</option>
+                                        </select>
+                                    </div>
+
+                                    <div class="form-group col-md-6">
+                                        <label for="feedbackInformative"><?= __("Informative"); ?></label>
+                                        <select name="feedbackInformative" id="feedbackInformative" class="form-control">
+                                            <option value="">Select one...</option>
+                                            <option value="No">No</option>
+                                            <option value="Yes">Yes</option>
+                                        </select>
+                                    </div>
+                                    <div class="form-group col-md-6">
+                                        <label for="SaleOurProduct"><?= __("Sale Our Book"); ?></label>
+                                        <select name="SaleOurProduct" id="SaleOurProduct" class="form-control">
+                                            <option value="">Select one...</option>
+                                            <option value="No">No</option>
+                                            <option value="Yes">Yes</option>
+                                            <option value="Sold Before">Sold Before</option>
+                                        </select>
+                                    </div>
+                                    <div class="form-group col-md-6">
+                                        <label for="userOurProduct"><?= __("Use Our Book"); ?></label>
+                                        <select name="userOurProduct" id="userOurProduct" class="form-control">
+                                            <option value="">Select one...</option>
+                                            <option value="No">No</option>
+                                            <option value="Yes">Yes</option>
+                                            <option value="Used Before">Used Before</option>
+                                        </select>
+                                    </div>
+                                    <div class="form-group col-md-6">
+                                        <label for="mrFeedback"><?= __("MR Feedback"); ?></label>
+                                        <select name="mrFeedback" id="mrFeedback" class="form-control">
+                                            <option value="">Select one...</option>
+                                            <option value="No Comment">No Comment</option>
+                                            <option value="Positive">Positive</option>
+                                            <option value="Negative">Negative</option>                                            
+                                        </select>
+                                    </div>
+                                    
+                                </div>
+                                
+                                <div class="form-group">
+                                    <label for="otherInformation"><?php echo __("Other Info"); ?></label>
+                                    <textarea name="otherInformation" id="otherInformation" cols="30" rows="2" placeholder="Enter any other information here..." class="form-control"></textarea>
+                                </div>
+
+                                <div class="row">
+                                    
+                                    <div class="form-group col-md-6">
+                                        <input type="text" placeholder="Caller" name="feedbackCaller" id="feedbackCaller" class="form-control">
+                                    </div>
+                                    <div class="col-md-6">
+                                        <input id="saveFeedback" type="button" value="Save" class="btn btn-primary">
+                                    </div>
+                                </div>
+
+                            </div>
+
+                            <div class="col-md-6">
+                                <!-- Box header -->
+                                <div style="max-height: 220px; overflow: auto;" class="box-body quickFeedback">
+                                    <ul class="todo-list">
+                                        <?php
+                                        $selectFeedback = easySelectA(array(
+                                            "table"     => "notes",
+                                            "fields"    => "note_text",
+                                            "where"     => array(
+                                                "is_trash = 0 and note_type = 'feedback' and note_created_by"   => $_SESSION["uid"]
+                                            )
+                                        ));
+
+                                        if ($selectFeedback !== false) {
+
+                                            foreach ($selectFeedback["data"] as $fKey => $fValue) {
+                                                echo '<li style="cursor:pointer;">' . $fValue["note_text"] . '</li>';
+                                            }
+                                        }
+
+                                        ?>
+
+                                        <li style="cursor:pointer; text-align: center;"><i class="fa fa-plus-circle"></i> Add New</li>
+
+                                    </ul>
+
+                                </div>
+                            </div>
+
+                        </div>
+                        
+                    </div> <!-- End feedback Tab -->
+
+
+                </div>
+
+            </div>
+
+
+            <?php if(current_user_can("customer_support_dashboard.View")) { ?>
+
+                <div class="statistics">
+
+                    <div class="col-md-3 col-sm-6 col-xs-12">
+                        <div class="info-box">
+                            <span class="info-box-icon bg-green"><i class="fa fa-flag-o"></i></span>
+
+                            <div class="info-box-content">
+                            <span class="info-box-text">Agent In Call</span>
+                            <span class="info-box-number inCallAgent">0</span>
+                            </div>
+                            <!-- /.info-box-content -->
+                        </div>
+                        <!-- /.info-box -->
+                    </div>
+                    <div class="col-md-3 col-sm-6 col-xs-12">
+                        <div class="info-box">
+                            <span class="info-box-icon bg-green"><i class="fa fa-flag-o"></i></span>
+
+                            <div class="info-box-content">
+                            <span class="info-box-text">Busy Agent</span>
+                            <span class="info-box-number busyAgentCount">0</span>
+                            </div>
+                            <!-- /.info-box-content -->
+                        </div>
+                        <!-- /.info-box -->
+                    </div>
+                    <div class="col-md-3 col-sm-6 col-xs-12 ">
+                        <div class="info-box">
+                            <span class="info-box-icon bg-green"><i class="fa fa-flag-o"></i></span>
+
+                            <div class="info-box-content">
+                            <span class="info-box-text">Free Agent</span>
+                            <span class="info-box-number freeAgentCount">0</span>
+                            </div> 
+                            <!-- /.info-box-content -->
+                        </div>
+                        <!-- /.info-box -->
+                    </div>
+                    <div class="col-md-3 col-sm-6 col-xs-12">
+                        <div class="info-box">
+                            <span class="info-box-icon bg-green"><i class="fa fa-flag-o"></i></span>
+
+                            <div class="info-box-content">
+                            <span class="info-box-text">Agent Unavailable</span>
+                            <span class="info-box-number unableAgentCount">0</span>
+                            </div>
+                            <!-- /.info-box-content -->
+                        </div>
+                        <!-- /.info-box -->
+                    </div>
+
+                </div>
+
+            <?php } ?>
+
+        </div>
+
+
+
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+</div>
+<!-- /.content-wrapper -->
+
+<script>
+
+    // request permission on page load
+    document.addEventListener('DOMContentLoaded', function() {
+
+        if (!Notification) {
+            alert('Desktop notifications not available in your browser.');
+            return;
+        }
+
+        if (Notification.permission !== 'granted') {
+            Notification.requestPermission();
+        }
+
+        // Enable / Disable DND when page is load
+        if( get_options("dnd") === "enable" ) {
+
+            $("#enableDND").hide();
+            $("#disableDND").show();
+            $(".dndAlert").show();
+
+        } else {
+            
+            $("#disableDND").hide();
+            $("#enableDND").show();
+
+        }
+
+    });
+
+
+    // Hide the suggestion numbers when escape key presed
+    $(document).on("keydown", ".numberSearch", function(e) {
+        
+        var keyName = e.key;
+        if( keyName === "Escape" ) {
+            $(".suggestion-numbers").html("").slideUp("fast");
+        }
+
+    });
+
+
+    // Hide the suggestion numbers when click outside of the it
+    $(document).mouseup(function(e) {
+
+        var container = $(".number-dialer-div");
+
+        if( !container.is(e.target) && container.has(e.target).length === 0 ) {
+
+            $(".suggestion-numbers").html("").slideUp("fast");
+
+        }
+
+    });
+
+
+    var numberSearchTimeout;
+    $(document).on("input focus", ".numberSearch", function(e) {        
+
+        var searchText = $(this).val();
+
+        if( searchText.length > 1 ) { // If the input length at least three
+
+            clearTimeout( numberSearchTimeout );
+
+            numberSearchTimeout = setTimeout(function() {
+
+                BMS.fn.get("searchContact&s="+ searchText, function(results) {
+
+                    if(results !== "") {
+
+                        var contactSuggestion = "";
+                        results.forEach(item => {
+                            contactSuggestion += `<div class="item">
+                                                    <span onclick="showCallerDetails('${item.number}')" >${item.name} (${item.type})</span>
+                                                    <span onclick="showCallerDetails('${item.number}')">${item.number}</span>
+                                                    <button onclick="dial('${item.number}')" type="button" class="btn btn-success btn-flat callButton"><i class="fa fa-fw fa-phone"></i> Call</button>
+                                                </div>`;
+                        });
+
+                        /** Show the suggestion numbers */
+                        $(".suggestion-numbers").html(contactSuggestion).slideDown("fast");
+
+                    } else {
+
+                        // Hide the suggestion numbers
+                        $(".suggestion-numbers").html("").slideUp("fast");
+                        
+                    }
+
+                });
+                
+
+            }, 400);
+
+
+        } else {
+
+            // Hide the suggestion numbers
+            $(".suggestion-numbers").html("").slideUp("fast");
+
+        }
+    
+    });
+
+
+    
+    <?php if(current_user_can("customer_support_dashboard.View")) { ?>
+
+        function showAgentsStats() {
+
+            setTimeout(() => {
+
+                $.ajax({
+                    url: `${full_website_address}/ami.php`,
+                    timeout: 3000,
+                    success: function(data) {
+
+                        showAgentsStats();
+                        
+                        var data = JSON.parse(data);
+
+                        $(".inCallAgent").html(data.agent_stats.inCallAgent);
+                        $(".busyAgentCount").html(data.agent_stats.busyAgent);
+                        $(".freeAgentCount").html(data.agent_stats.freeAgent);
+                        $(".unableAgentCount").html(data.agent_stats.unableAgent);
+                        
+                        if( Object.keys(data.agent_status).length > 0) {
+
+                            $.each(data.agent_status, function(extens, item) {
+
+                                if(item.state === "") {
+
+                                    $(".agentExt" + extens ).html(`${item.status}`);
+
+                                } else {
+                                    
+                                    $(".agentExt" + extens ).html(`${item.type} (${item.number}), ${item.state}`);
+
+                                }
+
+
+                            });
+
+                        }
+
+                    },
+                    error: function() {
+                        
+                        showAgentsStats();
+
+                    }
+
+                });
+                
+            }, 3000);
+
+        }
+
+        // Initial States
+        showAgentsStats();
+
+
+    <?php } ?>
+
+
+</script>
\ No newline at end of file

programming_language: PHP
filename: case-list-all.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,121 @@
+<!-- Content Wrapper. Contains page content -->
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+        <h1>
+            <?= __("Customer Support"); ?>
+            <a data-toggle="modal" data-target="#modalDefaultMdm" href="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=newCase" class="btn btn-primary"><?= __("New Case"); ?></a>
+        </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+        <div class="row">
+            <div class="col-xs-12">
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Case List"); ?></h3>
+                        <div class="printButtonPosition"></div>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th><?php echo __("Date"); ?></th>
+                                    <th><?php echo __("Case Title"); ?></th>
+                                    <th style="width: 200px;"><?php echo __("Requester"); ?></th>
+                                    <th class="defaultOrder no-sort"><?php echo __("Priority"); ?></th>
+                                    <th class="no-sort"><?php echo __("Type"); ?></th>
+                                    <th class="no-sort"><?php echo __("Status"); ?></th>
+                                    <th class="no-sort"><?php echo __("Assigned To"); ?></th>
+                                    <th class="no-sort"><?php echo __("Belongs To"); ?></th>
+                                    <th class="no-sort"><?php echo __("Last Reply"); ?></th>
+                                    <th class="no-sort"><?php echo __("Posted By"); ?></th>
+                                    <th class="no-sort"><?php echo __("Action"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th class="no-print">
+                                        <input style="width: 160px;" type="text" placeholder="<?= __("Select Date"); ?>" id="caseAddedDate" class="form-control" autocomplete="off">
+                                    </th>
+                                    <th><?php echo __("Case Title"); ?></th>
+                                    <th class="no-print">
+                                        <input style="width: 100%;" type="text" placeholder="<?= __("Search Requester"); ?>" id="searchRequester" class="form-control" autocomplete="off">
+                                    </th>
+                                    <th class="no-print"> 
+                                        <select id="casePriority" class="form-control select2" style="width: 100%">
+                                            <option value="">Priority...</option>
+                                            <?php
+                                                $casePriority = array('Low', 'Medium', 'High', 'Critical');
+                                                foreach($casePriority as $priority) {
+                                                    echo "<option value='{$priority}'>{$priority}</option>";
+                                                }
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th class="no-print"> 
+                                        <select id="caseType" class="form-control select2" style="width: 100%">
+                                            <option value="">Type...</option>
+                                            <?php
+                                                $caseType = array('Refund Request', 'Packaging Issues', 'Delivery Issue', 'Technical Issues', 'Query', 'Damaged Item', 'Exchange', 'Others');
+                                                foreach($caseType as $type) {
+                                                    echo "<option value='{$type}'>{$type}</option>";
+                                                }
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th class="no-print"> 
+                                        <select id="caseStatus" class="form-control select2" style="width: 100%">
+                                            <option value="">Status...</option>
+                                            <?php
+                                                $caseStatus = array('Pending', 'Open', 'Replied', 'Customer Responded', 'Solved', 'Informed', 'On Hold');
+                                                foreach($caseStatus as $status) {
+                                                    echo "<option value='{$status}'>{$status}</option>";
+                                                }
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th>
+                                        <select id="caseAssignTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                                            <option value=""><?= __("Select Assignee"); ?>....</option>
+                                        </select>
+                                    </th>
+                                    <th> 
+                                        <select id="caseBelongsTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=employeeList" style="width: 100%;">
+                                            <option value=""><?= __("Select Belongs to"); ?>....</option>
+                                        </select>
+                                    </th>
+                                    <th><?php echo __("Last Reply"); ?></th>
+                                    <th class="no-sort">
+                                        <select id="casePostedBy" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                                            <option value=""><?= __("Posted By"); ?>....</option>
+                                        </select>
+                                    </th>
+                                    <th><?php echo __("Action"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+            </div>
+            <!-- col-xs-12-->
+        </div>
+        <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+</div>
+<!-- /.content-wrapper -->
+
+<script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=caseList";
+    BMS.FUNCTIONS.dateRangePickerPreDefined({selector: "#caseAddedDate"});
+</script>
\ No newline at end of file

programming_language: PHP
filename: case-list.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,11 @@
+<?php 
+
+if(isset( $_GET["case_id"] )) {
+
+    require "case-reply-view.php";
+
+} else {
+    require "case-list-all.php";
+}
+
+?>
\ No newline at end of file

programming_language: PHP
filename: case-reply-view.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,762 @@
+<!-- Content Wrapper. Contains page content -->
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+        <h1>
+            <?= __("Customer Support"); ?>
+            <a data-toggle="modal" data-target="#modalDefaultMdm" href="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=newCase" class="btn btn-primary"><?= __("New Case"); ?></a>
+        </h1>
+    </section>
+
+    <?php 
+
+        $selectCase = easySelectA(array(
+            "table"     => "cases as cases",
+            "fields"    => "case_id, case_datetime, case_title, case_priority, case_type, case_status, last_reply,
+                            case_site, case_assigned_to, case_belongs_to,
+                            concat(assigned_to.emp_firstname, ' ', assigned_to.emp_lastname) as case_assign_name, 
+                            concat(belongs_to.emp_firstname, ' ', belongs_to.emp_lastname) as case_belongs_to_name,
+                            case_customer, customer_name, customer_phone, customer_email, customer_address,
+                            case_person, person_full_name, person_phone, person_email, person_address,
+                            person_type, person_designation, institute_name, institute_type, upazila_name, district_name, division_name
+                            ",
+            "join"      => array(
+                "left join {$table_prefix}users on user_id = case_assigned_to",
+                "left join {$table_prefix}employees as assigned_to on assigned_to.emp_id = user_emp_id",
+                "left join {$table_prefix}employees as belongs_to on belongs_to.emp_id = case_belongs_to",
+                "left join {$table_prefix}persons on person_id = case_person",
+                "left join {$table_prefix}districts on district_id = person_district",
+                "left join {$table_prefix}divisions on division_id = person_division",
+                "left join {$table_prefix}upazilas on upazila_id = person_upazila",
+                "left join {$table_prefix}institute on institute_id = person_institute",
+                "left join {$table_prefix}customers on customer_id = case_customer",
+                
+
+                "left join (select
+                        max(reply_datetime) as last_reply,
+                        reply_case_id
+                    from {$table_prefix}case_replies
+                    where is_trash = 0
+                    group by reply_case_id
+                ) as replies on replies.reply_case_id = case_id"
+            ),
+            "where"     => array(
+                "cases.is_trash = 0 and cases.case_id"  => $_GET["case_id"]
+            )
+        ));
+
+        if($selectCase === false) {
+
+            echo '<div style="margin-top: 20px" class="col-xs-12"><div class="alert alert-danger">Sorry! No Ticket/ Case found.</div></div>';
+
+        } else {
+
+            $case = $selectCase["data"][0];
+
+    ?>
+
+        <script src="<?php echo full_website_address(); ?>/assets/3rd-party/tinymce_6.1.2/tinymce.min.js"></script>
+        <link rel="stylesheet" href="<?php echo full_website_address(); ?>/assets/3rd-party/viewerjs-main/dist/viewer.min.css">
+        <script src="<?php echo full_website_address(); ?>/assets/3rd-party/viewerjs-main/dist/viewer.min.js"></script>
+
+        <!-- Main content -->
+        <section class="content container-fluid">
+            <div class="row">
+                <div class="col-xs-8">
+
+                    <div class="case-title">
+                        <h1><?php echo $case["case_title"]; ?></h1>
+                        <p><b>Posted on:</b> <?php echo date("d F, Y h:m A", strtotime($case["case_datetime"])) . " (" .  time_elapsed_string($case["case_datetime"])  .")"; ?></p>
+                    </div>
+                    
+                    <div class="case-replies">
+
+                        <form id="submitCaseReply">
+
+                            <textarea name='caseReply' id='replyBox'></textarea>
+                            <div class="box replyForm">
+
+                                <div class="box-body">
+                                    <div class="form-group col-md-6">
+                                        <label for="caseReplyAttachment">Attachment</label>
+                                        <input type="file" name="caseReplyAttachment[]" id="caseAttachment" multiple accept="image/png, image/jpeg" class="form-control">
+                                        <small style='margin-top: 5px; display: block'><b>Note:</b> Max Upload Size: <?php echo $_SETTINGS["MAX_UPLOAD_SIZE"]; ?>MB. Only JPEG and PNG image types are allowed to upload</small>    
+                                    </div>
+                                    <div class="form-group col-md-3">
+                                        <label for="replyMode"><?= __("Reply Mode:"); ?></label>
+                                        <select name="replyMode" id="replyMode" class="form-control" style="width: 100%;">
+                                            <?php 
+                                                $mode = array('Public', 'Private');
+                                                foreach($mode as $mode) {
+                                                    echo "<option value='{$mode}'>{$mode}</option>";
+                                                }
+                                            ?>
+
+                                        </select>
+                                    </div>
+                                    <input type="hidden" name="case_id" value="<?php echo safe_entities($_GET["case_id"]); ?>">
+                                    <input type="hidden" name="caseType" value="<?php echo $case["case_type"]; ?>">
+                                    <div class="form-group col-md-2">
+                                        <br/>
+                                        <button class='btn btn-primary' type='submit'>Submit</button>
+                                    </div>
+
+                                </div>
+                                    
+                                    
+                            </div>
+
+                        </form>
+
+                        <?php 
+
+                            $selectReplies = easySelectA(array(
+                                "table"     => "case_replies as reply",
+                                "fields"    => "reply_id, reply_type, reply_datetime, reply_details, reply_attachment,
+                                                if(emp_firstname is null, customer_name, concat(emp_firstname, ' ', emp_lastname)) as reply_by,
+                                                reply_by_customer
+                                                ",
+                                "join"      => array(
+                                    "left join {$table_prefix}users on user_id = reply_by_agent",
+                                    "left join {$table_prefix}employees on emp_id = user_emp_id",
+                                    "left join {$table_prefix}customers on customer_id = reply_by_customer"
+                                ),
+                                "where"     => array(
+                                    "reply.is_trash = 0 and reply_case_id"    => $_GET["case_id"]
+                                ),
+                                "orderby"   => array(
+                                    "reply_id"  => "DESC"
+                                )
+                            ));
+
+                            if($selectReplies !== false) {
+
+                                foreach($selectReplies["data"] as $reply) {
+
+                                    $time_elaps = time_elapsed_string($reply["reply_datetime"]) . " (" .  date("d F, Y h:m A", strtotime($reply["reply_datetime"]))  .")";
+
+                                    $attachment = "";
+                                    if($reply["reply_attachment"] !== null) {
+
+                                        $listAttachment = unserialize( html_entity_decode($reply["reply_attachment"]) );
+
+                                        foreach($listAttachment as $image) {
+                                            $attachment .= "<li><img width='80' height='80' src='". full_website_address() ."/assets/upload/{$image}'></li>";
+                                        }
+
+                                    }
+
+
+                                    // Define user and reply type
+                                    $userType = "<span><i class='fa fa-user'></i> Staff</span>";
+                                    $replyType = "<span><i class='fa fa-globe'></i> Public</span>";
+                                    $replyClass = 'reply';
+                                    $replyTypeMoveTo = 'Private';
+                                    if( $reply["reply_by_customer"] !== null ) {
+                                        $userType = "<span><i class='fa fa-user'></i> Customer</span>";
+                                    }
+
+                                    if( $reply["reply_type"] === "Private" ) {
+                                        $replyType = "<span><i class='fa fa-lock'></i> Private</span>";
+                                        $replyClass = 'reply private';
+                                        $replyTypeMoveTo = 'Public';
+                                    }
+
+                                    // If there have any attachment then show them
+                                    if($attachment !== "") {
+                                        $attachment = "<div class='attachment'>
+                                                            <p>Attachment:</p>
+                                                            <ul class='imageAttachment'>
+                                                                {$attachment}
+                                                            </ul>
+                                                        </div>";
+                                    }
+                                    
+                                    
+                                    echo "<div class='{$replyClass}'>
+                                            
+                                            <div class='title'>
+                                                <span>{$reply["reply_by"]}</span>
+                                                <span>
+                                                    {$time_elaps}
+                                                
+                                                    <div class='btn-group'>
+                                                        
+                                                        <button type='button' class='btn btn-link' data-toggle='dropdown'>
+                                                            <i class='fa fa-ellipsis-v'></i>
+                                                        </button>
+                                                        <ul class='dropdown-menu dropdown-menu-right' role='menu'>
+
+                                                            <li><a class='deleteEntry' removeParent='.reply' href='". full_website_address() . "/xhr/?module=customer-support&page=deleteCaseReply' data-to-be-deleted={$reply["reply_id"]}'> Delete</a></li>
+                                                            <li> <a class='updateEntry' href='". full_website_address() . "/xhr/?module=customer-support&page=updateCaseReplyType' data-to-be-updated='{$reply["reply_id"]}'>Move to {$replyTypeMoveTo} </a> </li>
+
+                                                        </ul>
+
+                                                    </div>
+                                                </span>
+
+                                            </div>
+                                            <div class='type'>
+                                                {$userType}
+                                                {$replyType}
+                                            </div>
+
+                                            <div class='reply-details'>
+                                                ". str_replace('\n', '</br>', html_entity_decode($reply["reply_details"]) ) ."
+                                            </div>
+                                            $attachment
+                                            
+
+                                        </div>";
+
+                                }
+
+                            }
+
+                        ?>
+
+                    </div>
+      
+
+                </div>
+                <!-- col-xs-8-->
+
+                <div class="col-xs-4">
+
+                    <div class="box box-primary">
+
+                        <div class="box-header with-border">
+                            <h3 class="box-title"><?php echo __("Contact Details"); ?></h3>
+                        </div> <!-- box box-default -->
+
+                        <div class="box-body box-profile">
+
+                            <?php if( $case["case_person"] !== null ) { ?>
+                        
+                                <h3 class="profile-username">
+                                    <?php echo $case["person_full_name"]; ?>
+                                    <small><a data-toggle="modal" href="<?php echo full_website_address(); ?>/xhr/?icheck=false&module=marketing&page=editPerson&id=<?php echo $case["case_person"]; ?>" data-target="#modalDefault"><i class="fa fa-edit"></i></a></small>
+                                </h3>
+                                <p>
+                                    <?php echo $case["person_type"]. ( $case["person_designation"] === null ? "" : " ({$case["person_designation"]})" ) ; ?>,
+                                    <?php echo $case["institute_name"]; ?>
+                                </p>
+
+                                
+                                
+                                <strong><i class="fa fa-book margin-r-5"></i> Contact</strong>
+                                <p class="text-muted">
+                                    <?php echo $case["person_phone"] . ", " . $case["person_email"];  ?>
+                                </p>
+
+                                <a data-toggle="modal" href="<?php echo full_website_address(); ?>/xhr/?module=marketing&page=viewSpecimenProduct&id=<?php echo $case["case_person"]; ?>"  data-target="#modalDefault"> View Specimen Copies</a>
+
+                                <hr>
+
+                                <strong><i class="fa fa-map-marker margin-r-5"></i> Address</strong>
+                                <p class="text-muted"><?php echo $case["person_address"] . ", " . $case["upazila_name"] . ", " . $case["district_name"] . ", " . $case["division_name"]; ?></p>
+
+                                <hr>
+
+                                <strong><i class="fa fa-support margin-r-5"></i> Recent Case/ Tickets</strong>
+                                
+                                
+                                <?php 
+                                    $selectCaseForThisPerson = easySelectA(array(
+                                        "table"     => "cases",
+                                        "fields"    => "case_id, case_title, case_status",
+                                        "where"     => array(
+                                            "is_trash = 0 and case_id != {$_GET["case_id"]} and case_person" => $case["case_person"]
+                                        ),
+                                        "orderby"   => array(
+                                            "case_id"   => "DESC"
+                                        ),
+                                        "limit" => array(
+                                            "start"     => 0,
+                                            "length"    => 5
+                                        )
+                                    ));
+
+                                    if($selectCaseForThisPerson !== false) {
+                                        foreach($selectCaseForThisPerson["data"] as $personCase) {
+                                            echo "<p style='margin: 5px;'><a href='". full_website_address() ."/customer-support/case-list/?case_id={$personCase['case_id']}'>{$personCase['case_title']}</a> ({$personCase['case_status']})</p>";
+                                            
+                                        }
+                                    } else {
+                                        echo '<p class="text-muted">Sorry! No Ticket/ Cases found.</p>';
+                                    }
+
+                                ?>
+
+                                <hr>
+
+                                <strong><i class="fa fa-phone margin-r-5"></i> Call Log</strong>
+
+                                <?php
+
+                                    $selectCalls = easySelectA(array(
+                                        "table"     => "calls",
+                                        "fields"    => "count(*) as totalCall, max(call_datetime) as lastCallTime",
+                                        "where"     => array(
+                                            "client_identity LIKE" => explode(",", $case["person_phone"])[0] . "%"
+                                        ),
+                                        "groupby"   => "client_identity"
+                                    ));
+
+
+                                    if($selectCalls !== false) {
+
+                                        $callStats = $selectCalls["data"][0];
+                                        echo '<p class="text-muted">
+                                                <span class="margin-r-5"><b>Call Count:</b> '. $callStats["totalCall"] .';</span> 
+                                                <span class="margin-r-5"><b>Last Call:</b> '. time_elapsed_string($callStats["lastCallTime"]) .' ('. $callStats["lastCallTime"] .')</span> 
+                                            </p>';
+                                    } else {
+                                        echo '<p class="text-muted">Sorry! No calls found.</p>';
+                                    }
+
+                                ?>
+
+                                
+
+          
+                            <?php } else if( $case["case_customer"] !== null )  { ?>
+
+                                <h3 class="profile-username">
+                                    <?php echo $case["customer_name"]; ?>
+                                    <small><a data-toggle="modal" href="<?php echo full_website_address(); ?>/xhr/?icheck=false&module=peoples&page=editCustomer&id=<?php echo $case["case_customer"]; ?>" data-target="#modalDefault"><i class="fa fa-edit"></i></a></small>
+                                </h3>
+                                
+                                
+                                <strong><i class="fa fa-book margin-r-5"></i> Contact</strong>
+                                <p class="text-muted">
+                                    <?php echo $case["customer_phone"] . ", " . $case["customer_email"];  ?>
+                                </p>
+
+                                <hr>
+
+                                <strong><i class="fa fa-map-marker margin-r-5"></i> Address</strong>
+                                <p class="text-muted"><?php echo $case["customer_address"]; ?></p>
+
+                                <hr>
+
+                                <strong><i class="fa fa-support margin-r-5"></i> Recent Case/ Tickets</strong>
+                                
+                                
+                                <?php 
+                                    $selectCaseForThisCustomer = easySelectA(array(
+                                        "table"     => "cases",
+                                        "fields"    => "case_id, case_title, case_status",
+                                        "where"     => array(
+                                            "is_trash = 0 and case_id != {$_GET["case_id"]} and case_customer" => $case["case_customer"]
+                                        ),
+                                        "orderby"   => array(
+                                            "case_id"   => "DESC"
+                                        ),
+                                        "limit" => array(
+                                            "start"     => 0,
+                                            "length"    => 5
+                                        )
+                                    ));
+
+                                    if($selectCaseForThisCustomer !== false) {
+                                        foreach($selectCaseForThisCustomer["data"] as $customerCase) {
+                                            echo "<p style='margin: 5px;'><a href='". full_website_address() ."/customer-support/case-list/?case_id={$personCase['case_id']}'>{$personCase['case_title']}</a> ({$personCase['case_status']})</p>";
+                                            
+                                        }
+                                    } else {
+                                        echo '<p class="text-muted">Sorry! No Ticket/ Cases found.</p>';
+                                    }
+
+                                ?>
+
+                                <hr>
+
+                                <strong><i class="fa fa-phone margin-r-5"></i> Call Log</strong>
+
+                                <?php
+
+                                    $selectCalls = easySelectA(array(
+                                        "table"     => "calls",
+                                        "fields"    => "count(*) as totalCall, max(call_datetime) as lastCallTime",
+                                        "where"     => array(
+                                            "client_identity LIKE" => explode(",", $case["customer_phone"])[0] . "%"
+                                        ),
+                                        "groupby"   => "client_identity"
+                                    ));
+
+
+                                    if($selectCalls !== false) {
+
+                                        $callStats = $selectCalls["data"][0];
+                                        echo '<p class="text-muted">
+                                                <span class="margin-r-5"><b>Call Count:</b> '. $callStats["totalCall"] .';</span> 
+                                                <span class="margin-r-5"><b>Last Call:</b> '. time_elapsed_string($callStats["lastCallTime"]) .' ('. $callStats["lastCallTime"] .')</span> 
+                                            </p>';
+                                    } else {
+                                        echo '<p class="text-muted">Sorry! No calls found.</p>';
+                                    }
+
+                                ?>
+
+                            <?php } else {
+                                echo '<p class="text-muted">Sorry! No data found.</p>';
+                            }
+                            ?>
+
+                        </div>
+
+                    </div>
+
+                    <form method="post" role="form" id="inlineForm" action="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=updateCase" enctype="multipart/form-data">
+                        <div class="box">
+
+                            <div class="box-header with-border">
+                                <h3 class="box-title"><?php echo __("Case Properties"); ?></h3>
+                            </div> <!-- box box-default -->
+
+                            <div class="box-body">
+
+                                <div class="form-group required">
+                                    <label for="caseTitle"><?= __("Title:"); ?></label>
+                                    <input type="text" name="caseTitle" id="caseTitle" value="<?php echo $case["case_title"]; ?>" class="form-control">
+                                </div>
+
+                                <div class="row">
+
+                                    <div class="form-group col-md-6 required">
+                                        <label for="casePriority"><?= __("Prority:"); ?></label>
+                                        <select name="casePriority" id="casePriority" class="form-control" style="width: 100%;" required>
+                                            <option value=""><?= __("Select Prority"); ?>....</option>
+                                            <?php 
+                                                $priority = array('Low', 'Medium', 'High', 'Critical');
+                                                foreach($priority as $priority) {
+                                                    $selected = $case["case_priority"] === $priority ? "selected" : "";
+                                                    echo "<option {$selected} value='{$priority}'>{$priority}</option>";
+                                                }
+                                            ?>
+
+                                        </select>
+                                    </div>
+
+                                    <div class="form-group col-md-6 required">
+                                        <label for="caseType"><?= __("Type:"); ?></label>
+                                        <select name="caseType" id="caseType" class="form-control" style="width: 100%;" required>
+                                            <option value=""><?= __("Select Type"); ?>....</option>
+                                            <?php 
+                                                $type = array('Refund Request', 'Packaging Issues', 'Delivery Issue', 'Technical Issues', 'Query', 'Damaged Item', 'Exchange', 'Others');
+                                                foreach($type as $type) {
+                                                    $selected = $case["case_type"] === $type ? "selected" : "";
+                                                    echo "<option {$selected} value='{$type}'>{$type}</option>";
+                                                }
+                                            ?>
+
+                                        </select>
+                                    </div>
+
+                                    <div class="form-group col-md-6">
+                                        <label for="caseStatus"><?= __("Status:"); ?></label>
+                                        <select name="caseStatus" id="caseStatus" class="form-control" style="width: 100%;">
+                                            <option value=""><?= __("Select Status"); ?>....</option>
+                                            <?php 
+                                                $status = array('Pending', 'Open', 'Replied', 'Customer Responded', 'Solved', 'Informed', 'On Hold');
+                                                foreach($status as $status) {
+                                                    $selected = $case["case_status"] === $status ? "selected" : "";
+                                                    echo "<option {$selected} value='{$status}'>{$status}</option>";
+                                                }
+                                            ?>
+
+                                        </select>
+                                    </div>
+
+                                    <div class="form-group col-md-6">
+                                        <label for="caseSite"><?= __("Site:"); ?></label>
+                                        <input type="text" name="caseSite" id="caseSite" value="<?php echo $case["case_site"] ?>" class="form-control">
+                                    </div>
+
+                                </div>
+
+
+                                <div class="form-group">
+                                    <label for="caseCustomer"><?= __("Customer:"); ?></label>
+                                    <select name="caseCustomer" id="caseCustomer" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=customerList" style="width: 100%;">
+                                        <option value=""><?= __("Select Customer"); ?>....</option>
+                                        <?php 
+                                            if($case["case_customer"] !== null) {
+                                                echo "<option selected value='{$case["case_customer"]}'>{$case["customer_name"]}</option>";
+                                            }
+                                        ?>
+                                    </select>
+                                </div>
+
+                                <div class="form-group">
+                                    <label for="casePerson"><?= __("Person/ Lead:"); ?></label>
+                                    <select name="casePerson" id="casePerson" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=personList" style="width: 100%;">
+                                        <option value=""><?= __("Select Person/ Lead"); ?>....</option>
+                                        <?php 
+                                            if($case["case_person"] !== null) {
+                                                echo "<option selected value='{$case["case_person"]}'>{$case["person_full_name"]}</option>";
+                                            }
+                                        ?>
+                                    </select>
+                                </div>
+
+                                <div class="form-group">
+                                    <label for="caseAssignTo"><?= __("Assign To:"); ?></label>
+                                    <select name="caseAssignTo" id="caseAssignTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=userList" style="width: 100%;">
+                                        <option value=""><?= __("Select user"); ?>....</option>
+                                        <?php 
+                                            if($case["case_assigned_to"] !== null) {
+                                                echo "<option selected value='{$case["case_assigned_to"]}'>{$case["case_assign_name"]}</option>";
+                                            }
+                                        ?>
+                                    </select>
+                                </div>
+
+                                <div class="form-group">
+                                    <label for="caseBelongsTo"><?= __("Belongs To:"); ?></label>
+                                    <select name="caseBelongsTo" id="caseBelongsTo" class="form-control select2Ajax" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=employeeList" style="width: 100%;">
+                                        <option value=""><?= __("Select Employee"); ?>....</option>
+                                        <?php 
+                                            if($case["case_belongs_to"] !== null) {
+                                                echo "<option selected value='{$case["case_belongs_to"]}'>{$case["case_belongs_to_name"]}</option>";
+                                            }
+                                        ?>
+                                    </select>
+                                </div>
+
+                                <input type="hidden" name="case_id" value="<?php echo safe_entities($_GET["case_id"]); ?>">
+
+                            </div>
+
+                            <div class="box-footer">
+                                <button type="submit" id="jqAjaxButton" class="btn btn-primary"><?php echo __("Update Case"); ?></button>
+                            </div>
+
+                        </div>
+                
+                    </form>
+                </div>
+
+
+            </div>
+            <!-- row-->
+        </section> <!-- Main content End tag -->
+
+    <?php  } ?>
+
+
+</div>
+<!-- /.content-wrapper -->
+
+
+<style>
+
+    .case-title {
+        border-top-left-radius: 10px;
+        border-top-right-radius: 10px;
+        padding: 10px;
+        padding-left: 20px;
+        position: sticky;
+        top: 0;
+        background-color: #fff;
+        box-shadow: 0 2px 2px -2px rgb(34 47 62 / 10%), 0 8px 8px -4px rgb(34 47 62 / 7%);
+        z-index: 1;
+    }
+
+    .case-title h1 {
+        font-size: 24px;
+        font-weight: bold;
+        margin: 0;
+        padding: 0;
+        color: #000
+    }
+    .case-title p {
+        padding-top: 5px;
+        font-size: 14px;
+        color: #767676;
+    }
+
+    .case-replies {
+        height: 720px;
+        overflow: auto;
+    }
+
+    .case-replies::-webkit-scrollbar {
+        width: 4px;
+    }
+
+    .case-replies::-webkit-scrollbar-track {
+        -webkit-box-shadow: inset 0 0 6px #598ecd; 
+        border-radius: 10px;
+    }
+
+    .case-replies::-webkit-scrollbar-thumb {
+        border-radius: 10px;
+        -webkit-box-shadow: inset 0 0 6px #598ecd; 
+    }
+
+    .case-replies .reply {
+        padding: 20px;
+        padding-bottom: 30px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+        border-radius: 5px;
+        background-color: #fff;
+        border: 1px solid #ececec;
+    }
+
+    .case-replies .private {
+        background-color: #f9ecec;
+        border: 1px solid #ececec;
+    }
+
+    .reply .title span:first-child {
+        font-size: 15px;
+        font-weight: 600;
+        color: #598ecd;
+    }
+    .reply .title span:last-child {
+        float: right;
+        color: #767676;
+    }
+
+    .reply .type {
+        color: #767676;
+        font-size: 13px;
+        margin-top: 5px;
+    }
+
+    .reply .type span:first-child {
+        margin-right: 10px;
+    }
+
+    .reply .type span i {
+        margin-right: 5px;
+    }
+
+    .reply .reply-details {
+        font-size: 14px;
+        color: #000;
+        margin-top: 20px;
+        /* white-space: pre-line; */
+    }
+
+    .reply .attachment {
+        margin-top: 30px;
+        padding-top: 5px;
+        border-top: 1px solid #ece8e8;
+    }
+
+    .reply .attachment p {
+        font-weight: bold;
+    }
+
+    .imageAttachment {
+        list-style-type: none;
+    }
+
+    .imageAttachment li {
+        display: inline;
+        margin: 5px;
+        cursor: pointer;
+    }
+
+    .tox-tinymce {
+        border-bottom-right-radius: 0;
+        border-bottom-left-radius: 0;
+    }
+
+    .replyForm {
+        border-bottom-left-radius: 10px;
+        border-bottom-right-radius: 10px;
+        box-shadow: none;
+        border-top: none;
+        margin-top: 5px;
+        padding-top: 10px;
+    }
+
+    hr {
+        margin: 15px 0;
+    }
+
+
+</style>
+
+<script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=caseList";
+    BMS.FUNCTIONS.dateRangePickerPreDefined({selector: "#caseAddedDate"});
+
+    // Initialize the editor
+    tinymce.init({
+        selector: '#replyBox',
+        menubar: false,
+        plugins: 'link',
+        toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | link | outdent indent',
+        statusbar: false,
+        height : 350,
+        default_link_target: "_blank",
+        branding: false,
+        invalid_elements : 'em,input,textarea,button',
+    });
+
+    // Initialz all attachment to viewer
+    $('.imageAttachment').each((index, item) => {
+        //console.log(item);
+        new Viewer( item );
+    });
+
+    /** Add reply to cases */
+    $(document).on("submit", "#submitCaseReply", function(e) {
+
+        e.preventDefault();
+
+        if( $("#replyBox").val() === "" ) {
+            return alert("Please enter reply");
+        }
+
+        var formData = new FormData(this);       // Get all form data and store into formData 
+        /**
+         * Disable all input field until ajax request complete. 
+         */
+        $(this).find("input, select, button, textarea").prop("disabled", true);
+
+        var that = this;
+
+        $.ajax({
+            url: full_website_address + "/xhr/?module=customer-support&page=addCaseReply",
+            type: 'POST',
+            data: formData,
+            cache: false,
+            contentType: false,
+            processData: false,
+            success: function (data, status) {
+
+                if (status == "success") {
+
+
+                    if (data.indexOf("danger") > 1) {
+                        BMS.fn.alertError($(data).text());
+                    } else {
+                        
+                        // clear content
+                        tinymce.get("replyBox").setContent('');
+
+                        // Insert the reply
+                        $(data).insertAfter("#submitCaseReply").hide().show('fast');
+
+                    }
+
+                    $(that).find("input, select, button, textarea").prop("disabled", false);
+
+                }
+
+            }
+
+        });
+
+    });
+
+
+</script>
\ No newline at end of file

programming_language: PHP
filename: dashboard.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,206 @@
+	<!-- Content Wrapper. Contains page content -->
+	<div class="content-wrapper">
+		<!-- Content Header (Page header) -->
+		<section class="content-header">
+			<h1>
+				<?=__("Customer Support Dashboard");?>
+				<small></small>
+			</h1>
+		</section>
+
+		<!-- Main content -->
+		<section class="content">
+		
+			<!-- Chart -->
+			<div class="row">
+				<div class="col-lg-12">
+					<div class="box box-primary">
+						<div class="box-header with-border">
+							<h3 class="box-title"><?php echo __("Call History Overview"); ?></h3>
+						</div>
+						<div class="box-body">
+							<div class="chart">
+								<canvas id="overviewChart" style="height: 380px"></canvas>
+							</div>
+						</div>
+						
+					</div>
+				</div>
+			</div>
+
+			<div class="row">
+				<!-- Top Customer of this product -->
+				<div class="col-sm-12 col-lg-12">
+                    <div class="box">
+                        <div class="box-header">
+                            <h3 class="box-title"><?= __("Agent Wise Statistics"); ?></h3>
+                        </div>
+                        <!-- Box header -->
+                        <div class="box-body">
+                            <table dt-height="30vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=agentWiseCallStatistics" class="dataTableWithAjaxExtend addToSMSBox table table-bordered table-striped table-hover" width="100%">
+                                <thead>
+                                    <tr>
+                                        <th></th>
+                                        <th><?php echo __("Agent Name"); ?></th>
+                                        <th><?php echo __("Talk Time"); ?></th>
+                                        <th><?php echo __("ATT"); ?></th>
+                                        <th><?php echo __("Answered"); ?></th>
+                                        <th><?php echo __("Not Answred"); ?></th>
+                                        <th><?php echo __("Busy"); ?></th>
+                                        <th><?php echo __("Missed"); ?></th>
+                                        <th><?php echo __("Unreachable"); ?></th>
+                                        <th><?php echo __("Total"); ?></th>
+                                    </tr>
+                                </thead>
+                
+                                <tfoot>
+                                    <tr>
+                                        <th></th>
+                                        <th class="no-print">
+                                            <input style="width: 160px;" type="text" placeholder="<?= __("Select Date"); ?>" name="callDateRange" id="callDateRange" class="form-control" autocomplete="off">
+                                        </th>
+                                        <th><?php echo __("Talk Time"); ?></th>
+                                        <th><?php echo __("ATT"); ?></th>
+                                        <th><?php echo __("Answered"); ?></th>
+                                        <th><?php echo __("Not Answred"); ?></th>
+                                        <th><?php echo __("Busy"); ?></th>
+                                        <th><?php echo __("Missed"); ?></th>
+                                        <th><?php echo __("Unreachable"); ?></th>
+                                        <th><?php echo __("Total"); ?></th>
+                                    </tr>
+                                </tfoot>
+                            </table>
+                        </div>
+                        <!-- box body-->
+                    </div>
+                    <!-- box -->
+				</div> <!-- /.Col -->
+
+        
+
+				
+
+			</div> <!-- /.Row -->
+
+
+		</section> <!-- Main content End tag -->
+		<!-- /.content -->
+	</div>
+	<!-- /.content-wrapper -->
+
+	<?php 
+
+		$callData = easySelectD("
+            SELECT db_date, call_status, if(totalCall is null, 0, totalCall) as totalCall FROM `time_dimension`
+            left join ( SELECT
+                    date(call_datetime) as call_date,
+                    count(*) as totalCall,
+                    call_status
+                from {$table_prefix}calls
+                group by date(call_datetime), call_status
+            ) as calls on call_date = db_date
+            where db_date BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) and CURRENT_DATE()
+		");
+        
+
+        $dates = array();
+        $unreachableCall = array();
+        $busyCall = array();
+        $notAnsweredCall = array();
+        $answeredCall = array();
+
+
+        if($callData !== false) {
+
+            foreach($callData["data"] as $key => $call){
+
+                if( !in_array($call["db_date"], $dates) ) {
+                    array_push($dates, $call["db_date"]);
+                }
+
+                // If call status empty then set zero in all call type
+                if( empty($call["call_status"]) ) {
+                    array_push($unreachableCall, 0);
+                    array_push($busyCall, 0);
+                    array_push($notAnsweredCall, 0);
+                    array_push($answeredCall, 0);
+                }
+
+                if( $call["call_status"] === "Unreachable" ) {
+
+                    array_push($unreachableCall, $call["totalCall"]);
+
+                } else if( $call["call_status"] === "Busy" ) {
+
+                    array_push($busyCall, $call["totalCall"]);
+
+                } else if( $call["call_status"] === "Not Answered" ) {
+
+                    array_push($notAnsweredCall, $call["totalCall"]);
+
+                } else if( $call["call_status"] === "Answered" ) {
+
+                    array_push($answeredCall, $call["totalCall"]);
+                    
+                }
+                
+            }
+
+        }
+
+		$callDates = __(json_encode($dates));
+		$unreachableCall = json_encode($unreachableCall);
+        $busyCall = json_encode($busyCall);
+        $notAnsweredCall = json_encode($notAnsweredCall);
+        $answeredCall = json_encode($answeredCall);
+
+	?>
+
+	<script src="<?php echo full_website_address(); ?>/assets/3rd-party/chart.js/Chart.min.js"></script>
+
+<script>
+
+var ctx = document.getElementById('overviewChart');
+var myLineChart = new Chart(ctx, {
+	type: 'line',
+	data: {
+		labels: <?php echo $callDates; ?>,
+		datasets: [
+			{
+				label: "<?= __("Answered"); ?>",
+				borderColor: "green",
+				borderWidth: 2,
+				data: <?php echo $answeredCall; ?>
+			},
+            {
+				label: "<?= __("Not Answered"); ?>",
+				borderColor: "red",
+				borderWidth: 2,
+				data: <?php echo $notAnsweredCall; ?>
+			},
+            {
+				label: "<?= __("Busy"); ?>",
+				borderColor: "blue",
+				borderWidth: 2,
+				data: <?php echo $busyCall; ?>
+			},
+            {
+				label: "<?= __("Unreachable"); ?>",
+				borderColor: "gray",
+				borderWidth: 2,
+				data: <?php echo $unreachableCall; ?>
+			}
+		]
+	},
+	options: {
+		responsive: true,
+		tooltips: {
+			mode: 'index',
+			intersect: false
+		}
+	}
+});
+
+BMS.FUNCTIONS.dateRangePickerPreDefined({selector: "#callDateRange"});
+
+</script>

programming_language: PHP
filename: introductory.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,104 @@
+<?php 
+/**
+ * Module Name: Customer Support
+ * Module URI: https://bumsys.net
+ * Description: A free and open source call center software.
+ * Version: 1.1.0
+ * Developer: Khurshid Alam
+ * Developer URI: https://kmk.alam.dev
+ */
+
+
+// Declaring the module menu
+$menu["Customer Support"] = array (
+    "t_link"    => "#",
+    "title"     => "",
+    "t_icon"    => "fa fa-assistive-listening-systems"
+);
+$menu["Customer Support"]["Dashboard"] = array (
+    "t_link"    => full_website_address() . "/customer-support/dashboard/",
+    "title"     => "Customer Support Dashboard",
+    "t_icon"    => "fa fa-dashboard",
+    "dload"     => true, // This will disable ajax loading
+    "__?"       => current_user_can("customer_support_dashboard.View")
+);
+$menu["Customer Support"]["Call Center"] = array (
+    "t_link"    => full_website_address() . "/customer-support/call-center/",
+    "title"     => "Call Center Dashboard",
+    "t_icon"    => "fa fa-headphones",
+    "dload"     => true,
+    "__?"       => current_user_can("customer_support_call_center.View")
+);
+$menu["Customer Support"]["Call Center Old"] = array (
+    "t_link"    => full_website_address() . "/customer-support/call-center-old/",
+    "title"     => "Call Center Dashboard",
+    "t_icon"    => "fa fa-headphones",
+    "dload"     => true,
+    "__?"       => current_user_can("customer_support_call_center.View")
+);
+$menu["Customer Support"]["Voice Message"] = array (
+    "t_link"    => full_website_address() . "/customer-support/voice-message/",
+    "title"     => "Voice Brodcasting System",
+    "t_icon"    => "fa fa-volume-up",
+    "dload"     => true,
+    "__?"       => current_user_can("customer_support_voice_message.View || customer_support_voice_message.Add || customer_support_voice_message.Edit || customer_support_voice_message.Delete")
+);
+$menu["Customer Support"]["Case List"] = array (
+    "t_link"    => full_website_address() . "/customer-support/case-list/",
+    "title"     => "Case/ Ticket List",
+    "t_icon"    => "fa fa-exclamation-circle",
+    "__?"       => current_user_can("customer_support_cases.View || customer_support_cases.Add || customer_support_cases.Edit || customer_support_cases.Delete")
+);
+$menu["Customer Support"]["My Call History"] = array (
+    "t_link"    => full_website_address() . "/customer-support/my-call-history/",
+    "title"     => "My Call History",
+    "t_icon"    => "fa fa-headphones",
+    "__?"       => current_user_can("customer_support_my_call_history.View || customer_support_my_call_history.Add || customer_support_my_call_history.Edit || customer_support_my_call_history.Delete")
+);
+$menu["Customer Support"]["All Call History"] = array (
+    "t_link"    => full_website_address() . "/customer-support/all-call-history/",
+    "title"     => "All Call History",
+    "t_icon"    => "fa fa-phone",
+    "__?"       => current_user_can("customer_support_all_call_history.View || customer_support_all_call_history.Add || customer_support_all_call_history.Edit || customer_support_all_call_history.Delete")
+);
+$menu["Customer Support"]["SMS"] = array (
+    "t_link"    => full_website_address() . "/customer-support/sms-list/",
+    "title"     => "SMS List",
+    "t_icon"    => "fa fa-comment",
+    "__?"       => current_user_can("customer_support_sms.View || customer_support_sms.Add || customer_support_sms.Edit || customer_support_sms.Delete")
+);
+$menu["Customer Support"]["Notes/ Feedback"] = array (
+    "t_link"    => full_website_address() . "/customer-support/note-list/",
+    "title"     => "Notes/ Feedback List",
+    "t_icon"    => "fa fa-sticky-note",
+    "__?"       => current_user_can("customer_support_note.View || customer_support_note.Add || customer_support_note.Edit || customer_support_note.Delete")
+);
+$menu["Customer Support"]["Representative"] = array (
+    "t_link"    => full_website_address() . "/customer-support/representative-list/",
+    "title"     => "Representative List",
+    "t_icon"    => "fa fa-user",
+    "__?"       => current_user_can("customer_support_representative.View || customer_support_representative.Add || customer_support_representative.Edit || customer_support_representative.Delete")
+);
+
+
+// Add menu in specific position
+add_menu($menu, 7);
+
+
+// Permissions
+add_permission(
+    array(
+        "customer_support_dashboard" => array("View"),
+        "customer_support_call_center" => array("View"),
+        "customer_support_cases" => "",
+        "customer_support_my_call_history" => "",
+        "customer_support_all_call_history" => "",
+        "customer_support_sms" => "",
+        "customer_support_representative" => "",
+        "customer_support_note" => ""
+    )
+)
+
+
+
+?>
\ No newline at end of file

programming_language: PHP
filename: my-call-history.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,97 @@
+<!-- Content Wrapper. Contains page content -->
+<div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+        <h1>
+            <?= __("Customer Support"); ?>
+            <small><?= __("Call List"); ?></small>
+        </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+        <div class="row">
+            <div class="col-xs-12">
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Call List"); ?></h3>
+                        <div class="printButtonPosition"></div>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                                <tr>
+                                    <th></th>
+                                    <th class="px160 defaultOrder"><?php echo __("Date"); ?></th>
+                                    <th><?php echo __("Direction"); ?></th>
+                                    <th class="px120"><?php echo __("Reason"); ?></th>
+                                    <th class="px120"><?php echo __("Status"); ?></th>
+                                    <th><?php echo __("Client"); ?></th>
+                                    <th class="px220"><?php echo __("Specimen Products"); ?></th>
+                                    <th><?php echo __("Duration"); ?></th>
+                                    <th style="width: 420px;"><?php echo __("Feedback"); ?></th>
+                                </tr>
+                            </thead>
+
+                            <tfoot>
+                                <tr>
+                                    <th></th>
+                                    <th class="no-print">
+                                        <input style="width: 160px;" type="text" placeholder="<?= __("Select Date"); ?>" name="callDate" id="callDate" class="form-control" autocomplete="off">
+                                    </th>
+                                    <th>
+                                        <select name="callDirection" id="callDirection" class="form-control select2" style="width: 100%">
+                                            <option value="">Direction...</option>
+                                            <?php
+                                            $callDirection = array('Outgoing', 'Incoming');
+                                            foreach ($callDirection as $Direction) {
+                                                echo "<option value='{$Direction}'>{$Direction}</option>";
+                                            }
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th>
+                                        <select id="callReasonFilter" class="form-control select2Ajax" select2-tag="true" select2-ajax-url="<?php echo full_website_address() ?>/info/?module=select2&page=callReasonList" style="width: 100%;">
+                                            <option value=""><?= __("All Reason"); ?>...</option>
+                                        </select>
+                                    </th>
+                                    <th>
+                                        <select name="callStatus" id="callStatus" class="form-control select2" style="width: 100%">
+                                            <option value="">Status...</option>
+                                            <?php
+                                            $callStatus = array('Answered', 'Missed', 'Rejected', 'Not Answered', 'Busy', 'Unreachable', 'Pending');
+                                            foreach ($callStatus as $status) {
+                                                echo "<option value='{$status}'>{$status}</option>";
+                                            }
+                                            ?>
+                                        </select>
+                                    </th>
+                                    <th><?php echo __("Client"); ?></th>
+                                    <th><?php echo __("Specimen Products"); ?></th>
+                                    <th><?php echo __("Duration"); ?></th>
+                                    <th><?php echo __("Feedback"); ?></th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+            </div>
+            <!-- col-xs-12-->
+        </div>
+        <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+</div>
+<!-- /.content-wrapper -->
+
+<script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=myCallList";
+    BMS.FUNCTIONS.dateRangePickerPreDefined({
+        selector: "#callDate"
+    });
+</script>
\ No newline at end of file

programming_language: PHP
filename: note-list.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,59 @@
+  <!-- Content Wrapper. Contains page content -->
+
+  <div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+      <h1>
+        <?= __("Customer Support"); ?>
+        <small><?= __("Note List"); ?></small>
+      </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+      <div class="row">
+        <div class="col-xs-12">
+          <div class="box">
+            <div class="box-header">
+              <h3 class="box-title"><?= __("Note/ Feedback List"); ?></h3>
+            </div>
+            <!-- Box header -->
+            <div class="box-body">
+              <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                <thead>
+                  <tr>
+                    <th></th>
+                    <th><?php echo __("ID"); ?></th>
+                    <th><?php echo __("Type"); ?></th>
+                    <th><?php echo __("Text"); ?></th>
+                    <th class="no-sort"><?php echo __("Action"); ?></th>
+                  </tr>
+                </thead>
+   
+                <tfoot>
+                  <tr>
+                    <th></th>
+                    <th><?php echo __("ID"); ?></th>
+                    <th><?php echo __("Type"); ?></th>
+                    <th><?php echo __("Text"); ?></th>
+                    <th><?php echo __("Action"); ?></th>
+                  </tr>
+                </tfoot>
+              </table>
+            </div>
+            <!-- box body-->
+          </div>
+          <!-- box -->
+        </div>
+        <!-- col-xs-12-->
+      </div>
+      <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+  </div>
+  <!-- /.content-wrapper -->
+  <script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=noteList";
+  </script>

programming_language: PHP
filename: representative-list.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,65 @@
+  <!-- Content Wrapper. Contains page content -->
+
+  <div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+      <h1>
+        <?= __("Customer Support"); ?>
+        <?php 
+          if(current_user_can("customer_support_representative.Add")) {
+            echo '<a data-toggle="modal" data-target="#modalDefault" href="'. full_website_address() .'/xhr/?module=customer-support&page=newRepresentative" class="btn btn-sm btn-primary"><i class="fa fa-plus"></i> Add</a>';
+          }
+        ?>
+      </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+      <div class="row">
+        <div class="col-xs-12">
+          <div class="box">
+            <div class="box-header">
+              <h3 class="box-title"><?= __("Representative List"); ?></h3>
+            </div>
+            <!-- Box header -->
+            <div class="box-body">
+              <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                <thead>
+                  <tr>
+                    <th></th>
+                    <th><?php echo __("Name"); ?></th>
+                    <th><?php echo __("SIP User"); ?></th>
+                    <th><?php echo __("SIP Domian"); ?></th>
+                    <th><?php echo __("Socket URL"); ?></th>
+                    <th><?php echo __("Action"); ?></th>
+                  </tr>
+                </thead>
+   
+                <tfoot>
+                  <tr>
+                    <th></th>
+                    <th><?php echo __("Name"); ?></th>
+                    <th><?php echo __("SIP User"); ?></th>
+                    <th><?php echo __("SIP Domian"); ?></th>
+                    <th><?php echo __("Socket URL"); ?></th>
+                    <th><?php echo __("Action"); ?></th>
+                  </tr>
+                </tfoot>
+              </table>
+            </div>
+            <!-- box body-->
+          </div>
+          <!-- box -->
+        </div>
+        <!-- col-xs-12-->
+      </div>
+      <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+  </div>
+  <!-- /.content-wrapper -->
+  <script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=callCenterRepresentativeList";
+  </script>

programming_language: PHP
filename: sms-list.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,61 @@
+  <!-- Content Wrapper. Contains page content -->
+
+  <div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+      <h1>
+        <?= __("Customer Support"); ?>
+        <small><?= __("SMS List"); ?></small>
+      </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+      <div class="row">
+        <div class="col-xs-12">
+          <div class="box">
+            <div class="box-header">
+              <h3 class="box-title"><?= __("SMS List"); ?></h3>
+            </div>
+            <!-- Box header -->
+            <div class="box-body">
+              <table id="dataTableWithAjaxExtend" class="table table-bordered table-striped table-hover" width="100%">
+                <thead>
+                  <tr>
+                    <th></th>
+                    <th class="defaultOrder"><?php echo __("Date"); ?></th>
+                    <th><?php echo __("To"); ?></th>
+                    <th><?php echo __("Text"); ?></th>
+                    <th><?php echo __("Status"); ?></th>
+                    <th><?php echo __("Send by"); ?></th>
+                  </tr>
+                </thead>
+   
+                <tfoot>
+                  <tr>
+                    <th></th>
+                    <th><?php echo __("Date"); ?></th>
+                    <th><?php echo __("To"); ?></th>
+                    <th><?php echo __("Text"); ?></th>
+                    <th><?php echo __("Status"); ?></th>
+                    <th><?php echo __("Send by"); ?></th>
+                  </tr>
+                </tfoot>
+              </table>
+            </div>
+            <!-- box body-->
+          </div>
+          <!-- box -->
+        </div>
+        <!-- col-xs-12-->
+      </div>
+      <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+  </div>
+  <!-- /.content-wrapper -->
+  <script>
+    /*Column Defference target column of data table */
+    var DataTableAjaxPostUrl = "<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=smsList";
+  </script>

programming_language: PHP
filename: voice-message.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,102 @@
+<?php 
+
+$selectSipCredentials = easySelectA(array(
+    "table"     => "sip_credentials",
+    "fields"    => "sip_username, sip_password, sip_domain, sip_websocket_addr",
+    "where"     => array(
+        "sip_representative"    => $_SESSION["uid"]
+    )
+));
+
+if($selectSipCredentials !== false) {
+    $sip = $selectSipCredentials["data"][0];
+    echo "<script> const sipCredentials = {
+        uri: 'sip:{$sip['sip_username']}@{$sip['sip_domain']}',
+        socket: '{$sip['sip_websocket_addr']}',
+        user: '{$sip['sip_username']}',
+        pass: '{$sip['sip_password']}'
+    }; </script>";
+}
+
+?>
+
+<!-- Content Wrapper. Contains page content -->
+<script async src="<?php echo full_website_address(); ?>/js/?q=voiceMessage&v=2.0.3"></script>
+  <div class="content-wrapper">
+    <!-- Content Header (Page header) -->
+    <section class="content-header">
+      <h1>
+        <?php echo __("Voice Message Broadcasting System"); ?>
+        <a data-toggle="modal" data-target="#modalDefault" href="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=newVoiceMessageEntry" class="btn btn-sm btn-primary"><i class="fa fa-plus"></i> <?= __("Add New"); ?></a>
+      </h1>
+    </section>
+
+    <!-- Main content -->
+    <section class="content container-fluid">
+
+        <div class="row">
+
+            <div class="col-md-8">
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Voice Message List"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div class="box-body">
+                        <table dt-height="30vh" dt-data-url="<?php echo full_website_address(); ?>/xhr/?module=customer-support&page=voiceMessageList" class="dataTableWithAjaxExtend addToSMSBox table table-bordered table-striped table-hover" width="100%">
+                            <thead>
+                            <tr>
+                                <th></th>
+                                <th><?php echo __("Date"); ?></th>
+                                <th><?php echo __("Description"); ?></th>
+                                <th><?php echo __("Record"); ?></th>
+                                <th><?php echo __("Status"); ?></th>
+                                <th><?php echo __("Action"); ?></th>
+                            </tr>
+                            </thead>
+            
+                            <tfoot>
+                            <tr>
+                                <th></th>
+                                <th><?php echo __("Date"); ?></th>
+                                <th><?php echo __("Description"); ?></th>
+                                <th><?php echo __("Record"); ?></th>
+                                <th><?php echo __("Status"); ?></th>
+                                <th><?php echo __("Action"); ?></th>
+                            </tr>
+                            </tfoot>
+                        </table>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+
+            </div>
+
+            <!-- terminal --> 
+            <div class="col-md-4">
+
+                <div class="box">
+                    <div class="box-header">
+                        <h3 class="box-title"><?= __("Terminal"); ?></h3>
+                    </div>
+                    <!-- Box header -->
+                    <div style="height: 340px; background-color: black; color: white; overflow: auto;" class="box-body">
+                       <ul class="voiceMessageTerminal" style="list-style: none; padding-left: 10px;">
+                           <li>Click Start Sending to initiate the terminal</li>
+                       </ul>
+                    </div>
+                    <!-- box body-->
+                </div>
+                <!-- box -->
+                
+            </div>
+        
+        </div>
+        <!-- row-->
+
+    </section> <!-- Main content End tag -->
+    <!-- /.content -->
+  </div>
+  <!-- /.content-wrapper -->

programming_language: PHP
filename: home2.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,322 @@
+	<!-- Content Wrapper. Contains page content -->
+	<div class="content-wrapper">
+	    <!-- Content Header (Page header) -->
+	    <section class="content-header">
+	        <h1>
+	            <?= __("Dashboard"); ?>
+	            <small></small>
+	        </h1>
+	        <ol class="breadcrumb">
+	            <li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
+	            <li class="active">Dashboard</li>
+	        </ol>
+	    </section>
+
+	    <!-- Main content -->
+	    <section class="content">
+	        <!-- Small boxes (Stat box) -->
+	        <div class="row">
+	            <div class="col-md-4 col-sm-6 col-xs-12">
+	                <!-- small box -->
+	                <div class="small-box bg-green">
+	                    <div class="inner">
+	                        <h3><?php
+                                $selectSoldQnt =  easySelectD("SELECT if(sum(sales_quantity) is null, 0, sum(sales_quantity)) as totalSales FROM {$table_prefix}sales where YEAR(sales_delivery_date) = YEAR(CURRENT_DATE) and is_trash = 0 group by YEAR(sales_delivery_date)");
+
+                                $soldQnt = 0;
+                                if ($selectSoldQnt !== false) {
+                                    $soldQnt = number_format($selectSoldQnt["data"][0]["totalSales"], 2);
+                                }
+
+                                echo __($soldQnt);
+
+                                ?></h3>
+
+	                        <p><?= __("This Year Product Sales"); ?></p>
+	                    </div>
+	                    <div class="icon">
+	                        <i class="fa fa-shopping-bag"></i>
+	                    </div>
+	                    <a href="<?php echo full_website_address(); ?>/sales/pos-sale/" class="small-box-footer"><?= __("Sales List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+	                </div>
+	            </div>
+	            <!-- ./col -->
+	            <div class="col-md-4 col-sm-6 col-xs-12">
+	                <!-- small box -->
+	                <div class="small-box bg-aqua">
+	                    <div class="inner">
+	                        <h3><?php echo __(easySelectD("SELECT count(DISTINCT sales_customer_id) as totalCustomer FROM {$table_prefix}sales")["data"][0]["totalCustomer"]); ?></h3>
+
+	                        <p><?= __("Total Customers"); ?></p>
+	                    </div>
+	                    <div class="icon">
+	                        <i class="fa fa-user"></i>
+	                    </div>
+	                    <a href="<?php echo full_website_address(); ?>/peoples/customer-list/" class="small-box-footer"><?= __("Customers List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+	                </div>
+	            </div>
+	            <!-- ./col -->
+	            <div class="col-md-4 col-sm-6 col-xs-12">
+	                <!-- small box -->
+	                <div class="small-box bg-yellow">
+	                    <div class="inner">
+	                        <h3><?php echo __(easySelectD("SELECT count(product_id) as totalProduct FROM {$table_prefix}products")["data"][0]["totalProduct"]); ?></h3>
+
+	                        <p><?= __("Total Products"); ?></p>
+	                    </div>
+	                    <div class="icon">
+	                        <i class="fa fa-cube"></i>
+	                    </div>
+	                    <a href="<?php echo full_website_address(); ?>/products/product-list/" class="small-box-footer"><?= __("Products List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+	                </div>
+	            </div>
+	            <!-- ./col -->
+	        </div>
+	        <!-- /.row -->
+
+	        <!-- Chart -->
+	        <div class="row">
+	            <div class="col-lg-12">
+	                <div class="box box-primary">
+	                    <div class="box-header with-border">
+	                        <h3 class="box-title"><?= __("Sales Overview"); ?></h3>
+	                    </div>
+	                    <div class="box-body">
+	                        <div class="chart">
+	                            <canvas id="overviewChart" style="height: 300px"></canvas>
+	                        </div>
+	                    </div>
+
+	                    <div class="box-footer">
+	                        <div class="row">
+	                            <div class="col-sm-3 col-xs-6">
+	                                <div class="description-block border-right">
+	                                    <span class="description-percentage text-green"><i class="fa fa-caret-up"></i> 17%</span>
+	                                    <h5 class="description-header">$35,210.43</h5>
+	                                    <span class="description-text">TOTAL REVENUE</span>
+	                                </div>
+	                                <!-- /.description-block -->
+	                            </div>
+	                            <!-- /.col -->
+	                            <div class="col-sm-3 col-xs-6">
+	                                <div class="description-block border-right">
+	                                    <span class="description-percentage text-yellow"><i class="fa fa-caret-left"></i> 0%</span>
+	                                    <h5 class="description-header">$10,390.90</h5>
+	                                    <span class="description-text">TOTAL COST</span>
+	                                </div>
+	                                <!-- /.description-block -->
+	                            </div>
+	                            <!-- /.col -->
+	                            <div class="col-sm-3 col-xs-6">
+	                                <div class="description-block border-right">
+	                                    <span class="description-percentage text-green"><i class="fa fa-caret-up"></i> 20%</span>
+	                                    <h5 class="description-header">$24,813.53</h5>
+	                                    <span class="description-text">TOTAL PROFIT</span>
+	                                </div>
+	                                <!-- /.description-block -->
+	                            </div>
+	                            <!-- /.col -->
+	                            <div class="col-sm-3 col-xs-6">
+	                                <div class="description-block">
+	                                    <span class="description-percentage text-red"><i class="fa fa-caret-down"></i> 18%</span>
+	                                    <h5 class="description-header">1200</h5>
+	                                    <span class="description-text">Total Sales </span>
+	                                </div>
+	                                <!-- /.description-block -->
+	                            </div>
+	                        </div>
+	                        <!-- /.row -->
+	                    </div>
+	                    <!-- /.box-footer -->
+
+	                </div>
+	            </div>
+	        </div>
+
+	        <div class="row">
+	            <!-- Top Customer of this product -->
+	            <div class="col-sm-12 col-lg-6">
+	                <div class="box box-info">
+	                    <div class="box-header">
+	                        <h3 class="box-title"><?= __("Top Sold Products of %d", date("Y")); ?></h3>
+	                    </div>
+	                    <div class="box-body">
+	                        <table class="table table-bordered table-striped table-hover" style="width: 100%;">
+	                            <thead>
+	                                <tr>
+	                                    <th class="no-sort"><?= __("Product Name"); ?></th>
+	                                    <th class="text-right"><?= __("Sold Qnt"); ?></th>
+	                                </tr>
+	                            </thead>
+
+	                            <tbody>
+	                                <?php
+                                    $topProduct = easySelectA(array(
+                                        "table"   => "product_stock as product_stock",
+                                        "fields"  => "product_name, product_unit, sum(stock_item_qty) as totalItemQnt",
+                                        "join"    => array(
+                                            "left join {$table_prefix}products on stock_product_id = product_id"
+                                        ),
+                                        "where"   => array(
+                                            "product_stock.is_trash = 0 and stock_type"  => 'sale',
+                                            ""
+                                        ),
+                                        "having" => array(
+                                            "max(stock_entry_date) >= CONCAT(YEAR(CURRENT_DATE),'-',01,'-',01) AND max(stock_entry_date) <= CONCAT(YEAR(CURRENT_DATE),'-',12,'-',31)"
+                                        ),
+                                        "groupby" => "stock_product_id",
+                                        "orderby" => array(
+                                            "sum(stock_item_qty)" => "DESC"
+                                        ),
+                                        "limit" => array(
+                                            "start"   => 0,
+                                            "length"  => 10
+                                        )
+                                    ));
+                                    $num = 1;
+                                    if ($topProduct) {
+                                        foreach ($topProduct["data"] as $key => $product) {
+                                            echo "<tr>";
+                                            echo  "<td>$num. {$product['product_name']}</td>";
+                                            echo  "<td class='text-right'>" . __(number_format($product['totalItemQnt'], 2)) . " " . __($product['product_unit']) . "</td>";
+                                            echo "</tr>";
+                                            $num++;
+                                        }
+                                    } else {
+                                        echo "
+												<tr>
+													<td class='text-center' colspan='2'>No Data Found!</td>
+												</tr>
+											";
+                                    }
+
+                                    ?>
+	                            </tbody>
+
+	                        </table>
+	                    </div>
+	                </div>
+	            </div> <!-- /.Col -->
+
+	            <!-- Top Customer of this product -->
+	            <div class="col-sm-12 col-lg-6">
+	                <div class="box box-info">
+	                    <div class="box-header">
+	                        <h3 class="box-title"><?= __("Low Product Stock"); ?></h3>
+	                    </div>
+	                    <div class="box-body">
+	                        <table class="table table-bordered table-striped table-hover" style="width: 100%;">
+	                            <thead>
+	                                <tr>
+	                                    <th class="no-sort"><?= __("Product Name"); ?></th>
+	                                    <th class="text-right"><?= __("Left Stock"); ?></th>
+	                                </tr>
+	                            </thead>
+
+	                            <tbody>
+	                                <?php
+
+                                    $select_low_product = easySelectD("
+                                                                    SELECT 
+                                                                        pbs.vp_id as pid, 
+                                                                        product_name, product_unit, 
+                                                                        round(sum(base_stock_in), 2) as base_stock_in,
+                                                                        base_qty
+                                                                    FROM product_base_stock as pbs -- Product Base Stock
+                                                                    left join {$table_prefix}products as product on product.product_id = pbs.vp_id
+                                                                    where batch_id is null or date(batch_expiry_date) > curdate()
+                                                                    GROUP BY pbs.vp_id
+                                                                    order by base_stock_in ASC
+                                                                    limit 0,10
+                                                            ");
+
+                                    $num = 1;
+                                    if ($select_low_product) {
+                                        foreach ($select_low_product["data"] as $key => $product) {
+                                            echo "<tr>";
+                                            echo  "<td>$num. {$product['product_name']}</td>";
+                                            echo  "<td class='text-right'>" . __(number_format($product['base_stock_in'] / $product['base_qty'], 2)) . " " . __($product['product_unit']) . "</td>";
+                                            echo "</tr>";
+                                            $num++;
+                                        }
+                                    } else {
+                                        echo "
+											<tr>
+												<td class='text-center' colspan='2'>No Data Found!</td>
+											</tr>
+										";
+                                    }
+
+                                    ?>
+	                            </tbody>
+
+	                        </table>
+	                    </div>
+	                </div>
+	            </div> <!-- /.Col -->
+
+	        </div> <!-- /.Row -->
+
+
+	    </section> <!-- Main content End tag -->
+	    <!-- /.content -->
+	</div>
+	<!-- /.content-wrapper -->
+
+	<?php
+
+    $salesData = easySelectD("
+			select sales_delivery_date, sum(sales_quantity) as sales_quantity from {$table_prefix}sales where is_trash = 0 and sales_delivery_date >= DATE_SUB(NOW(), INTERVAL 30 DAY) group by sales_delivery_date
+		");
+
+    $dateStart = date('Y-m-d', strtotime('today - 30 days'));
+
+    $i = 0;
+    $newdate = array();
+    $newvalue = array();
+
+    while ($dateStart <= date("Y-m-d")) {
+
+        $dateStart = date("Y-m-d", strtotime("$dateStart + 1 day"));
+
+        if (isset($salesData["data"][$i]) && $salesData["data"][$i]["sales_delivery_date"] == $dateStart) {
+
+            array_push($newdate, $salesData["data"][$i]["sales_delivery_date"]);
+            array_push($newvalue, $salesData["data"][$i]["sales_quantity"]);
+            $i++;
+        } else {
+
+            array_push($newdate, $dateStart);
+            array_push($newvalue, 0);
+        }
+    }
+
+    $salesDate = __(json_encode($newdate));
+    $salesAmount = json_encode($newvalue);
+
+    ?>
+
+	<script src="<?php echo full_website_address(); ?>/assets/3rd-party/chart.js/Chart.min.js"></script>
+
+	<script>
+	    var ctx = document.getElementById('overviewChart');
+	    var myLineChart = new Chart(ctx, {
+	        type: 'line',
+	        data: {
+	            labels: <?php echo $salesDate; ?>,
+	            datasets: [{
+	                label: "<?= __("Sales"); ?>",
+	                borderColor: "green",
+	                borderWidth: 2,
+	                data: <?php echo $salesAmount; ?>
+	            }]
+	        },
+	        options: {
+	            responsive: true,
+	            tooltips: {
+	                mode: 'index',
+	                intersect: false
+	            }
+	        }
+	    });
+	</script>
\ No newline at end of file

programming_language: PHP
filename: home_back.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,473 @@
+	<!-- Content Wrapper. Contains page content -->
+	<div class="content-wrapper">
+		<!-- Content Header (Page header) -->
+		<section class="content-header">
+			<h1>
+				<?=__("Dashboard");?>
+				<small></small>
+			</h1>
+			<ol class="breadcrumb">
+				<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
+				<li class="active">Dashboard</li>
+			</ol>
+		</section>
+
+		<!-- Main content -->
+		<section class="content">
+			<!-- Small boxes (Stat box) -->
+			<div class="row">
+				<div class="col-md-4 col-sm-6 col-xs-12">
+					<!-- small box -->
+					<div class="small-box bg-green">
+						<div class="inner">
+							<h3><?php 
+							$selectSoldQnt =  easySelectD("SELECT if(sum(sales_quantity) is null, 0, sum(sales_quantity)) as totalSales FROM {$table_prefix}sales where YEAR(sales_delivery_date) = YEAR(CURRENT_DATE) and is_trash = 0 group by YEAR(sales_delivery_date)");
+							
+							$soldQnt = 0;
+							if($selectSoldQnt !== false) {
+								$soldQnt = number_format($selectSoldQnt["data"][0]["totalSales"], 2);
+							}
+							
+							echo __($soldQnt);
+							
+							?></h3>
+
+							<p><?= __("This Year Product Sales"); ?></p>
+						</div>
+						<div class="icon">
+							<i class="fa fa-shopping-bag"></i>
+						</div>
+						<a href="<?php echo full_website_address(); ?>/sales/pos-sale/" class="small-box-footer"><?= __("Sales List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+					</div>
+				</div>
+				<!-- ./col -->
+				<div class="col-md-4 col-sm-6 col-xs-12">
+					<!-- small box -->
+					<div class="small-box bg-aqua">
+						<div class="inner">
+						<h3><?php echo __(easySelectD("SELECT count(DISTINCT sales_customer_id) as totalCustomer FROM {$table_prefix}sales")["data"][0]["totalCustomer"]); ?></h3>
+
+							<p><?= __("Total Customers"); ?></p>
+						</div>
+						<div class="icon">
+							<i class="fa fa-user"></i>
+						</div>
+						<a href="<?php echo full_website_address(); ?>/peoples/customer-list/" class="small-box-footer"><?= __("Customers List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+					</div>
+				</div>
+				<!-- ./col -->
+				<div class="col-md-4 col-sm-6 col-xs-12">
+					<!-- small box -->
+					<div class="small-box bg-yellow">
+						<div class="inner">
+							<h3><?php echo __(easySelectD("SELECT count(product_id) as totalProduct FROM {$table_prefix}products")["data"][0]["totalProduct"]); ?></h3>
+
+							<p><?= __("Total Products"); ?></p>
+						</div>
+						<div class="icon">
+							<i class="fa fa-cube"></i>
+						</div>
+						<a href="<?php echo full_website_address(); ?>/products/product-list/" class="small-box-footer"><?= __("Products List"); ?> <i class="fa fa-arrow-circle-right"></i></a>
+					</div>
+				</div>
+				<!-- ./col -->
+			</div>
+			<!-- /.row -->
+
+			<!-- Chart -->
+			<div class="row">
+				<div class="col-lg-12">
+					<div class="box box-primary">
+						<div class="box-header with-border">
+							<h3 class="box-title"><?= __("Sales Overview"); ?></h3>
+
+                            <select style="width: 200px; display: inline; float: right;" id="salesOverviewType">
+                                <option value="daily">Daily</option>
+                                <option selected value="weekly">Weekly</option>
+                                <option value="monthly">Monthly</option>
+                            </select>
+
+						</div>
+						<div class="box-body">
+							<div class="chart">
+								<canvas id="salesOverviewChart" style="height: 320px"></canvas>
+							</div>
+						</div>
+						
+					</div>
+				</div>
+			</div>
+
+			<div class="row">
+
+                <!-- Customers Need to get Attention -->
+				<div class="col-sm-12 col-lg-6">
+					<div class="box box-success">
+						<div class="box-header">
+							<h3 class="box-title"><?= __("Customers Need to get attention"); ?></h3>
+						</div>
+						<div class="box-body">
+							<table class="table table-bordered table-striped table-hover" style="width: 100%;">
+								<thead>
+									<tr>
+										<th class="no-sort"><?= __("Customer Name"); ?></th>
+										<th class="text-right"><?= __("Previous Year"); ?></th>
+										<th class="text-right"><?= __("Running Year"); ?></th>
+										<th class="text-right"><?= __("Increase Rate"); ?></th>
+									</tr>
+								</thead>
+								
+								<tbody>
+									<?php
+										
+                                        /**
+                                         * See here to know how to caculat parcentage
+                                         * https://www.bbc.co.uk/bitesize/guides/zpjmjty/revision/2
+                                         * 
+                                         * 
+                                         * percentage increase = increased number ÷ original number × 100
+                                         * percentage decrease = decreased number ÷ original number × 100
+                                         * 
+                                         */
+                                        $getPurchaseIncreasedCustomer = easySelectA(array(
+                                            "table"     => "customers",
+                                            "fields"    => "customer_id, customer_name, upazila_name, district_name,
+                                                            round(previous_year_total_sales, 2) as previous_year_total_purchase, 
+                                                            round(current_year_total_sales, 2) as current_year_total_purchase,
+                                                            round( ( current_year_total_sales - previous_year_total_sales ) / previous_year_total_sales * 100) as increased_rate
+                                                            ",
+                                            "join"      => array(
+                                                "left join {$table_prefix}upazilas on customer_upazila = upazila_id",
+                                                "left join {$table_prefix}districts on customer_district = district_id",
+                                                "left join (
+                                                    select
+                                                        sales_customer_id,
+                                                        sum( CASE WHEN YEAR(sales_delivery_date) = YEAR( CURDATE() - INTERVAL 1 YEAR ) THEN sales_grand_total END ) as previous_year_total_sales,
+                                                        sum( CASE WHEN YEAR(sales_delivery_date) = YEAR( CURDATE() ) THEN sales_grand_total END ) as current_year_total_sales
+                                                    from ro_sales
+                                                    where is_trash = 0
+                                                    group by sales_customer_id
+                                                ) as customer_sale on sales_customer_id = customer_id"
+                                            ),
+                                            "where" => array(
+                                                "previous_year_total_sales is not null and previous_year_total_sales < current_year_total_sales and current_year_total_sales > 100000"
+                                            ),
+                                            "orderby"   => array(
+                                                "increased_rate"    => "DESC"
+                                            ),
+                                            "limit" => array(
+                                                "start"     => 0,
+                                                "length"    => 10
+                                            )
+                                        
+                                        ));
+
+
+										$num = 1;
+										if($getPurchaseIncreasedCustomer !== false) {
+
+											foreach($getPurchaseIncreasedCustomer["data"] as $key => $customer) {
+												echo "<tr>";
+												echo  "<td>{$num}. <a title='Show More Details' href='". full_website_address() ."/reports/customer-report/?cid={$customer['customer_id']}'>{$customer['customer_name']}, {$customer['upazila_name']}, {$customer['district_name']}</a></td>";
+                                                
+												echo  "<td class='text-right'>". to_money($customer['previous_year_total_purchase']) ."</td>";
+												echo  "<td class='text-right'>". to_money($customer['current_year_total_purchase']) ."</td>";
+												echo  "<td class='text-right'> <span class='description-percentage text-green'><i class='fa fa-caret-up'></i> {$customer['increased_rate']}%</span></td>";
+                                                
+												echo "</tr>";
+												$num++;
+											}
+
+										} else {
+
+											echo "
+												<tr>
+													<td class='text-center' colspan='2'>No Data Found!</td>
+												</tr>
+											";
+										}
+
+									?>
+								</tbody>
+
+							</table>
+						</div>
+					</div>
+				</div> <!-- /.Col -->
+
+                <!-- Alerming Customer -->
+				<div class="col-sm-12 col-lg-6">
+					<div class="box box-danger">
+						<div class="box-header">
+							<h3 class="box-title"><?= __("Alerming Customer"); ?></h3>
+						</div>
+						<div class="box-body">
+							<table class="table table-bordered table-striped table-hover" style="width: 100%;">
+								<thead>
+									<tr>
+										<th class="no-sort"><?= __("Customer Name"); ?></th>
+										<th class="text-right"><?= __("Previous Year"); ?></th>
+										<th class="text-right"><?= __("Running Year"); ?></th>
+										<th class="text-right"><?= __("Descrease Rate"); ?></th>
+									</tr>
+								</thead>
+								
+								<tbody>
+									<?php
+										
+                                        /**
+                                         * See here to know how to caculat parcentage
+                                         * https://www.bbc.co.uk/bitesize/guides/zpjmjty/revision/2
+                                         * 
+                                         * 
+                                         * percentage increase = increased number ÷ original number × 100
+                                         * percentage decrease = decreased number ÷ original number × 100
+                                         * 
+                                         */
+                                        $getPurchaseIncreasedCustomer = easySelectA(array(
+                                            "table"     => "customers",
+                                            "fields"    => "customer_id, customer_name, upazila_name, district_name,
+                                                            round(previous_year_total_sales, 2) as previous_year_total_purchase, 
+                                                            round(current_year_total_sales, 2) as current_year_total_purchase,
+                                                            round( ( previous_year_total_sales - current_year_total_sales ) / previous_year_total_sales * 100) as decreased_rate
+                                                            ",
+                                            "join"      => array(
+                                                "left join {$table_prefix}upazilas on customer_upazila = upazila_id",
+                                                "left join {$table_prefix}districts on customer_district = district_id",
+                                                "left join (
+                                                    select
+                                                        sales_customer_id,
+                                                        sum( CASE WHEN YEAR(sales_delivery_date) = YEAR( CURDATE() - INTERVAL 1 YEAR ) THEN sales_grand_total END ) as previous_year_total_sales,
+                                                        sum( CASE WHEN YEAR(sales_delivery_date) = YEAR( CURDATE() ) THEN sales_grand_total END ) as current_year_total_sales
+                                                    from ro_sales
+                                                    where is_trash = 0
+                                                    group by sales_customer_id
+                                                ) as customer_sale on sales_customer_id = customer_id"
+                                            ),
+                                            "where" => array(
+                                                "previous_year_total_sales is not null and previous_year_total_sales > current_year_total_sales and previous_year_total_sales > 100000"
+                                            ),
+                                            "orderby"   => array(
+                                                "decreased_rate"    => "DESC"
+                                            ),
+                                            "limit" => array(
+                                                "start"     => 0,
+                                                "length"    => 10
+                                            )
+                                        
+                                        ));
+
+
+										$num = 1;
+										if($getPurchaseIncreasedCustomer !== false) {
+
+											foreach($getPurchaseIncreasedCustomer["data"] as $key => $customer) {
+												echo "<tr>";
+												echo  "<td>{$num}. <a title='Show More Details' href='". full_website_address() ."/reports/customer-report/?cid={$customer['customer_id']}'>{$customer['customer_name']}, {$customer['upazila_name']}, {$customer['district_name']}</a></td>";
+                                                
+												echo  "<td class='text-right'>". to_money($customer['previous_year_total_purchase']) ."</td>";
+												echo  "<td class='text-right'>". to_money($customer['current_year_total_purchase']) ."</td>";
+												echo  "<td class='text-right'> <span class='description-percentage text-red'><i class='fa fa-caret-down'></i> {$customer['decreased_rate']}%</span></td>";
+                                                
+												echo "</tr>";
+												$num++;
+											}
+
+										} else {
+
+											echo "
+												<tr>
+													<td class='text-center' colspan='2'>No Data Found!</td>
+												</tr>
+											";
+										}
+
+									?>
+								</tbody>
+
+							</table>
+						</div>
+					</div>
+				</div> <!-- /.Col -->
+            
+				<!-- Top Customer of this product -->
+				<div class="col-sm-12 col-lg-6">
+					<div class="box box-info">
+						<div class="box-header">
+							<h3 class="box-title"><?= __("Top Sold Products of %d", date("Y")); ?></h3>
+						</div>
+						<div class="box-body">
+							<table class="table table-bordered table-striped table-hover" style="width: 100%;">
+								<thead>
+									<tr>
+										<th class="no-sort"><?= __("Product Name"); ?></th>
+										<th class="text-right"><?= __("Sold Qnt"); ?></th>
+									</tr>
+								</thead>
+								
+								<tbody>
+									<?php
+										$topProduct = easySelectA(array(
+											"table"   => "product_stock as product_stock",
+											"fields"  => "product_name, product_unit, sum(stock_item_qty) as totalItemQnt",
+											"join"    => array(
+												"left join {$table_prefix}products on stock_product_id = product_id"
+											),
+											"where"   => array(
+													"product_stock.is_trash = 0 and stock_type"  => 'sale',
+													""
+											),
+											"having" => array(
+												"max(stock_entry_date) >= CONCAT(YEAR(CURRENT_DATE),'-',01,'-',01) AND max(stock_entry_date) <= CONCAT(YEAR(CURRENT_DATE),'-',12,'-',31)"
+											),
+											"groupby" => "stock_product_id",
+											"orderby" => array(
+												"sum(stock_item_qty)" => "DESC"
+											),
+											"limit" => array(
+												"start"   => 0,
+												"length"  => 10
+											)
+										));
+										$num = 1;
+										if($topProduct) {
+											foreach($topProduct["data"] as $key => $product) {
+												echo "<tr>";
+												echo  "<td>$num. {$product['product_name']}</td>";
+                                                echo  "<td class='text-right'>". __(number_format($product['totalItemQnt'], 2)) . " " . __($product['product_unit']) ."</td>";
+												echo "</tr>";
+												$num++;
+											}
+										} else {
+											echo "
+												<tr>
+													<td class='text-center' colspan='2'>No Data Found!</td>
+												</tr>
+											";
+										}
+
+									?>
+								</tbody>
+
+							</table>
+						</div>
+					</div>
+				</div> <!-- /.Col -->
+
+				<!-- Top Customer of this product -->
+				<div class="col-sm-12 col-lg-6">
+					<div class="box box-info">
+						<div class="box-header">
+							<h3 class="box-title"><?= __("Low Product Stock"); ?></h3>
+						</div>
+						<div class="box-body">
+							<table class="table table-bordered table-striped table-hover" style="width: 100%;">
+								<thead>
+									<tr>
+										<th class="no-sort"><?= __("Product Name"); ?></th>
+										<th class="text-right"><?= __("Left Stock"); ?></th>
+									</tr>
+								</thead>
+								
+								<tbody>
+								<?php
+
+									$select_low_product = easySelectD("
+                                                                    SELECT 
+                                                                        pbs.vp_id as pid, 
+                                                                        product_name, product_unit, 
+                                                                        round(sum(base_stock_in), 2) as base_stock_in,
+                                                                        base_qty
+                                                                    FROM product_base_stock as pbs -- Product Base Stock
+                                                                    left join {$table_prefix}products as product on product.product_id = pbs.vp_id
+                                                                    where batch_id is null or date(batch_expiry_date) > curdate()
+                                                                    GROUP BY pbs.vp_id
+                                                                    order by base_stock_in ASC
+                                                                    limit 0,10
+                                                            ");
+
+									$num = 1;
+									if($select_low_product) {
+										foreach($select_low_product["data"] as $key => $product) {
+											echo "<tr>";
+											echo  "<td>$num. {$product['product_name']}</td>";
+											echo  "<td class='text-right'>". __(number_format($product['base_stock_in']/$product['base_qty'], 2)) . " " . __($product['product_unit']) ."</td>";
+											echo "</tr>";
+											$num++;
+										}
+									} else {
+										echo "
+											<tr>
+												<td class='text-center' colspan='2'>No Data Found!</td>
+											</tr>
+										";
+									}
+
+								?>
+								</tbody>
+
+							</table>
+						</div>
+					</div>
+				</div> <!-- /.Col -->
+
+			</div> <!-- /.Row -->
+
+
+		</section> <!-- Main content End tag -->
+		<!-- /.content -->
+	</div>
+	<!-- /.content-wrapper -->
+
+	<script src="<?php echo full_website_address(); ?>/assets/3rd-party/chart.js/Chart.min.js"></script>
+
+<script>
+
+
+/** Weekly Sales */
+var ctx = document.getElementById('salesOverviewChart');
+var salesOverviewCharts = new Chart(ctx, {
+	type: 'line',
+	data: {},
+	options: {
+		responsive: true,
+		tooltips: {
+			mode: 'index',
+			intersect: false,
+            callbacks: {
+                label: function(tooltipItem, data) {
+                    return format_number(tooltipItem.yLabel)
+                }
+            }
+		}
+	}
+});
+
+
+/** When Document Ready Then load the chart */
+$(function() {
+
+    BMS.fn.get("salesOverviewChartData&type=weekly", function(data) {
+
+        salesOverviewCharts.data = data;
+
+        salesOverviewCharts.update();
+
+    });
+
+});
+
+/** Update Sales  */
+$(document).on("change", "#salesOverviewType", function() {
+
+    BMS.fn.get("salesOverviewChartData&type="+  $(this).val() , function(data) {
+
+        salesOverviewCharts.data = data;
+
+        salesOverviewCharts.update();
+
+    });
+
+});
+
+</script>

programming_language: PHP
filename: footer.php
change_type: ModificationType.MODIFY
diff: @@ -244,7 +244,7 @@
     <footer class="main-footer">
         <!-- To the right -->
         <div class="pull-right hidden-xs">
-            Version 2.1.1
+            Version 2.2.0
         </div>
         <!-- Default to the left -->
         <strong>Copyright &copy; <?php echo date("Y"); ?> <a href="https://bumsys.org/"><span
@@ -255,7 +255,7 @@
     <!-- ./wrapper -->
 
     <!-- Include all Header JS -->
-    <script src="<?php echo full_website_address(); ?>/js/?q=foot&v=2.1.1"></script>
+    <script src="<?php echo full_website_address(); ?>/js/?q=foot&v=2.2.0"></script>
 
 <!-- 
     <script>

programming_language: HTML
filename: header.php
change_type: ModificationType.MODIFY
diff: @@ -10,10 +10,10 @@
     <link rel="shortcut icon" href="<?php echo full_website_address() . "/assets/images/logo.png" ?>" type="image/x-icon">
 
     <!-- Include all CSS -->
-    <link rel="stylesheet" href="<?php echo full_website_address(); ?>/css/?v=2.1.1">
+    <link rel="stylesheet" href="<?php echo full_website_address(); ?>/css/?v=2.2.0">
 
     <!-- Include all Header JS -->
-    <script src="<?php echo full_website_address(); ?>/js/?q=head&v=2.1.1"></script>
+    <script src="<?php echo full_website_address(); ?>/js/?q=head&v=2.2.0"></script>
 
 
     <script>

programming_language: PHP