1if (typeof GLO === 'undefined') { GLO = {}; } 2if (GLO.Staff == undefined) { GLO.Staff = {}; } 3if (GLO.Communicate == undefined) { GLO.Communicate = {}; } 4 5if (typeof SA === 'undefined') { var SA = (function() { }); } 6if (SA.Profile === undefined) { SA.Profile = {}; } 7 8GLO.Staff = (function() { 9 function _conStaff() { } 10 11 _conStaff.hasEmail = function(staffId) { 12 var jsonStaff = _getStaffJson(staffId); 13 14 if (jsonStaff && !UTIL.isEmpty(jsonStaff.email)) { 15 return true; 16 } else { 17 var aProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?open=staff=' + staffId + '\', this, event, true);">Profile -> Staff</a>'; 18 var msg1 = '<p>To receive a text message please go to ' + aProfile + ' and add the <b>Email Address</b></p>'; 19 var htm = '<div id="pop-warn-staff-missing-phone">' + msg1 + '</div>'; 20 21 GLO.Popup.Warning.open(htm, 'Unable to Send Email'); 22 return false; 23 } 24 } 25 26 _conStaff.hasText = function(staffId, isUseSmsGateway) { 27 var jsonStaff = _getStaffJson(staffId); 28 var warnLabel = 'phone number'; 29 30 if (jsonStaff && !UTIL.isEmpty(jsonStaff.mobile_phone)) { 31 if (isUseSmsGateway && !UTIL.isEmpty(jsonStaff.mobile_provider)) { 32 warnLabel = 'phone company <i class="narrow-text">(to enable texts)</i>'; 33 } else { 34 return true; 35 } 36 } else { 37 38 } 39 40 var aProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?open=staff=' + staffId + '\', this, event, true);">Profile -> Staff</a>'; 41 var msg1 = '<p>To receive a text message please go to ' + aProfile + ' and add the <b>' + warnLabel + '</b></p>'; 42 var htm = '<div id="pop-warn-staff-missing-phone">' + msg1 + '</div>'; 43 44 GLO.Popup.Warning.open(htm, 'Unable to Send Text') 45 return false; 46 } 47 48 function _displayMissingContactWarning(messageFormat, isMissingSmsGateway) { 49 if (messageFormat == 3) { 50 if (isMissingSmsGateway) { 51 var h1 = 'Texting You Is Disabled'; 52 var msg1 = '<p>To send yourself a sample text message please enable text messaging for yourself</p>'; 53 var msg3 = '<p>Next to your phone number check the <b style="color: black;">Text Me</b> checkbox</p>'; 54 } else { 55 var h1 = 'Your Mobile Phone Number is Empty'; 56 var msg1 = '<p>To send yourself a sample text message please add your mobile phone to your profile</p>'; 57 var msg3 = 'and add your mobile phone'; 58 } 59 } else { 60 var h1 = 'Missing Your Email'; 61 var msg1 = '<p>To send yourself a sample email please add your email to your profile</p>'; 62 var msg3 = 'and add your email address'; 63 } 64 65 var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;'; 66 var a = '<a href="' + GLO.Link.WebsiteDomain + 'provider/profile/1" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>'; 67 var msg2 = '<div style="margin-top: 12px; margin-bottom: 12px;">Go to ' + a + '</div>'; 68 69 msg1 = '<div style="font-size: 16px;">' + msg1 + '</div>'; 70 var htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">' + h1 + '</h1><div class="friendly-msg4">' + msg1 + msg2 + msg3 + '</div></div>'; 71 new GLO.Popup.Warning(htm); 72 } 73 74 function _getStaffJson(staffId) { 75 if (SA.StaffContact && SA.StaffContact.length > 0) { 76 for (var i=0; i < SA.StaffContact.length; i++) { 77 if (staffId == SA.StaffContact[i].id) { 78 return SA.StaffContact[i]; 79 } 80 } 81 } 82 83 return null; 84 } 85 86 return _conStaff; 87})(); 88 89 90GLO.Staff.Filter = (function() { //use to set staff filter --> GLO.Report.initStaffFilter() 91 function _constructor(name) { } 92 _constructor.isReportPortal = false; 93 _constructor.isReportFilterEasyQuery = false; 94 var _intervalCounter = 0, _sfilterInterval = null; 95 96 _constructor.initOnPageLoad = function() { 97 var jfilter = $('#top-staffName #staff-filter'); 98 99 if (GLO.Info.isMobile()) { 100 var jfOpt = jfilter; 101 _initMobile(jfilter); 102 } else { 103 var jfOpt = jfilter.find('optgroup#staff-filter-s'); 104 } 105 106 if (jfOpt.find('option').length === 1) { 107 if (GLO.Info.isMobile()) { 108 jfilter.remove(); 109 } else { 110 var jloc = jfilter.find('#location-filter-sg').find('option'); 111 112 if (jloc.length > 0) { 113 var htm = _getLocationDropDown(jloc); 114 } else { 115 var htm = '<span style="padding-right: 6px; color: #999;">' + SA.Resource.Hi + ' ' + UTIL.maxString(GLO.Info.getStaffName(), 20, true) + '</span>'; 116 } 117 118 jfilter.closest('#top-staffName').html(htm); 119 jfilter.remove(); 120 } 121 } 122 123 var fGroupVal = GLO.Uri.query('sfiltergroup'); 124 125 if (!UTIL.isEmpty(fGroupVal)) { 126 if (fGroupVal == '4') { fGroupVal = 'house'; } 127 128 jfilter.val(fGroupVal); 129 } 130 131 _initHelloBar(); 132 } 133 function _initMobile(jfilter) { 134 if ($('#calendar').length === 0) { return; } 135 GLO.Info.init(); 136 if (GLO.Info.isIndependentPackage()) { return; } 137 if (GLO.Info.roleType < 100) { return ''; } 138 139 var jopt = UserPortal.getStaffDropDown().find('option'); 140 var i = 0, staffCount = jopt.length, staffWidthMax = parseInt((innerWidth - 30)/36); 141 142 if (jopt.eq(0).text() === 'Anyone' || UTIL.coalesceString(jopt.eq(0).attr('staff_ids')).indexOf(',') !== -1) { 143 i = 1; 144 } 145
146 if (staffCount - i < 12 || staffCount - staffWidthMax - i < 5) { return; } 147 148 if (GLO.Staff.Filter.getHouseStaff().split(',').length > staffWidthMax + 4) { 149 jfilter.find('option[value="house"]').remove(); 150 } 151 152 //jfilter.find('option[value="today"]').remove(); 153 jfilter.find('option[value="all"]').remove(); 154 jfilter.prepend('<optgroup id="staff-filter-staff-group"></optgroup>'); 155 var sids = '', name1 = jopt.eq(i).text(); 156 157 if (staffWidthMax > 12) { 158 staffWidthMax = 12; 159 } else if (staffWidthMax < 8) { 160 staffWidthMax = 8; 161 } 162 163 for (; i < staffCount; i++) { 164 if (i > 0 && i % staffWidthMax === 0) { 165 if (i + 2 === staffCount) { 166 sids += ',' + jopt.eq(i).attr('value'); 167 var name2 = _getName2(jopt, i); 168 _addStaffGroup(jfilter, sids, name1, name2); 169 return; 170 } else { 171 var name2 = _getName2(jopt, i-1); 172 _addStaffGroup(jfilter, sids, name1, name2); 173 } 174 175 sids = ''; 176 name1 = jopt.eq(i).text(); 177 } 178 179 if (sids !== '') { sids += ','; } 180 sids += jopt.eq(i).attr('value'); 181 } 182 183 var name2 = _getName2(jopt, i-1); 184 _addStaffGroup(jfilter, sids, name1, name2); 185 } 186 function _getName2(jopt, iterator) { 187 if (!UTIL.isEmpty(jopt.eq(iterator).attr('staff_ids'))) { //= Anyone 188 --iterator; 189 } 190 191 return jopt.eq(iterator).text(); 192 } 193 function _addStaffGroup(jfilter, sids, name1, name2) { 194 var option = '<option class="sfilter-staff-group" staff_ids="' + sids + '">' + name1 + ' - ' + name2 + '</option>'; 195 jfilter.find('#staff-filter-staff-group').append(option); 196 } 197 _constructor.init = function() { 198 var jdup = $('#sFilter-list .dup-viewProfile'); 199 200 if (GLO.Info.isIPad) { 201 var jHeader = $('#search-bar').css({ "margin-bottom": "25px" }); 202 jHeader.find('#top-staffName').css({ "font-size": "77%" }); 203 jHeader.find('#top-searchBox').css({ "width": "11em", "font-size": "85%" }); 204 205 GLO.UI.initAnimateLink(jdup, 2, GLO.UI.pinkify); 206 } else if (GLO.Info.isMobile()) { 207 var imgDirectory = GLO.Data.cdnDirectory + 'image/icon/arrow/aug2012/'; 208 209 GLO.UI.initAnimateLink(jdup, 2, GLO.UI.pinkify); 210 } 211 212 $("#sFilter-list").find("tr:odd").addClass('EveryOtherRow'); 213 214 var tbl = $('#sFilter-list'); 215 if (tbl.height() < 450) { tbl.height(450); } 216 217 var id = GLO.Uri.query('id'); 218 var idType = GLO.Uri.query('type'); 219 220 if (!UTIL.isEmpty(id) && !UTIL.isEmpty(idType)) { 221 if (idType == 's') { 222 $('#sFilter-list tr#trStaff' + id + ' .staffCheck').prop('checked', true); 223 } else if (idType == 'sg') { 224 var jDD = $('#ServicesOffered'); 225 jDD.val(id); 226 GLO.Staff.Filter.changeServiceTypeDD(jDD[0]); 227 } 228 } else { 229 var strIDS = GLO.Uri.url('sfilter'); 230 231 if (!UTIL.isEmpty(strIDS)) { 232 var ids = String(strIDS).split(','); 233 var tbl = $('#sFilter-list tr'); 234 var rowCnt = tbl.length; 235 236 for (var row=0; row < rowCnt; row++) { 237 for (var i=0; i < ids.length; i++) { 238 if ( tbl.eq(row).attr('id').substr(7) == ids[i] ) { 239 tbl.eq(row).find('>td input:checkbox.staffCheck').prop('checked', true); 240 } 241 } 242 } 243 } 244 } 245 } 246 247 function _initHelloBar() { 248 if ($('#staffFilter').length > 0) { 249 if ($('#create-appt-staff1 #Staff_id').find('option').length === 1) { 250 GLO.Staff.Filter.removeFilter(); //= remove staff filter hello bar if business package only has 1 staff member. 251 } 252 } 253 } 254 255 function _getLocationDropDown(jloc) { 256 var bgc = GLO.Data.provider.backgroundColor; 257 var pid = GLO.Data.provider.id; 258 var pname = GLO.Data.provider.name; 259 var htm = '<select id="location-filter" onchange="GLO.Staff.Filter.changeLocation(this, event)" style="color: rgb(' + bgc + ');">' 260 + '<option value="' + pid + '" style="background-color: rgba(' + bgc + ',.4);" provider_color_vc="' + bgc + '" selected="selected">' + pname + '</option>'; 261 262 for (var i=0; i < jloc.length; i++) { 263 htm += jloc.eq(i).outerHTML(); 264 } 265 266 return htm + '</select>'; 267 } 268 269 _constructor.checkBox = function(element) { 270 var checkbox = $(element); 271 if (checkbox.attr('name') !== 'staffCheck') { checkbox = checkbox.find('input'); } 272 273 checkbox.prop('checked', !checkbox[0].checked); 274 } 275 276 _constructor.changeServiceTypeDD = function(element) { 277 var jStaffRows = $('#sFilter-list tr'); 278 var arr; 279 280 for (var i=0; i < jStaffRows.length; i++) { 281 arr = jStaffRows.eq(i).attr('sg_ids').split(','); 282 283 if (arr.has(element.value) && element.value != '') { 284 jStaffRows.eq(i).find('.staffCheck').prop('checked', true); 285 } else { 286 jStaffRows.eq(i).find('.staffCheck').prop('checked', false); 287 } 288 } 289 } 290 291 _constructor.clickHeaderOption = function(element) { 292 //if (element.value == '') { document.location = GLO.Link.Page.Provider.StaffFilter + '?type=custom'; } 293 } 294 295 _constructor.displayQuickView = function(thisDD, ev) {
296 if ((ev.ctrlKey || ev.altKey) && $(thisDD).find('option:selected').parent().attr('id') == 'staff-filter-s') { 297 Wiz5.openStaffQuickView(thisDD.value); 298 ev.preventDefault(); 299 return false; 300 } 301 } 302 303 function _loadWorkingTodayOrCurrentDay() { 304 var dt = GLO.Calendar.cal.fullCalendar('getView').start; 305 var btnAdd = '<span class="btnAdd"><a style="padding: 8px 16px 6px;" onclick="GLO.Staff.Filter.reloadStaffWorking'; 306 var clearFilter, currDay = '', today = btnAdd + '()">Today</a></span>'; 307 308 if (!UTIL.isSameDay(new Date(GLO.Data.provider.now_dt), dt)) { 309 var currDay = btnAdd + '(\'' + dt.toGloDate() + '\')">' + dt.getWeekDayString(GLO.Info.isMobile()) + ', ' + dt.toSADate(true) + '</a></span>'; 310 } 311 312 var msg = '<div style="font-weight: bold;">Filter by staff working on which day?</div>'; 313 var htm = '<div id="pop-filter-staff-working-today">' + msg + '<div>' + today + currDay + '</div></div>'; 314 var h1 = 'Select Day'; 315 316 var jpop = GLO.Popup.Confirm.open(htm, h1).getPopup(); 317 jpop.find('h1').css({ "margin-bottom": 0 }); 318 jpop.find('.msg').css({ "margin-bottom": 0, "padding-top": 0 }); 319 jpop.find('.btnYes').remove(); 320 jpop.find('.btnNo').addClass('btnCancel').removeClass('btnNo').css({ "float": "none", "margin": "0", "padding": "0" }).find('>a').css({ "letter-spacing": "1px" }).text('Close'); 321 } 322 323 function _setFilterToUrl() { 324 var sfilter = String(UTIL.coalesce(GLO.Uri.query('sfiltergroup'), GLO.Uri.query('sfilter'), 'all')).toLowerCase(); 325 $('#staff-filter').val(sfilter); 326 } 327 328 function _loadWorkingToday(isDiffDay) { 329 var isToday = GLO.Calendar.isToday(); 330 var dtLastUsed = new Date($('#staff-filter').find('#staff-filter-diffday').attr('date')); 331 var dtCalendar = new Date(GLO.Calendar.cal.fullCalendar('getView').start); 332 333 if (!isDiffDay && !isToday) { 334 if (!UTIL.isSameDay(dtLastUsed, dtCalendar)) { 335 _loadWorkingTodayOrCurrentDay(); 336 _setFilterToUrl(); 337 return; 338 } 339 } else if (isDiffDay && isToday) { 340 _openSelectDayPopup(); 341 //_setSelectDiffDayWarning(); 342 _setFilterToUrl(); 343 return; 344 } 345 346 if (isDiffDay) { 347 _constructor.reloadStaffWorking(dtCalendar); 348 } else { 349 _constructor.reloadStaffWorking(); 350 } 351 } 352 353 function _openSelectDayPopup() { 354 var msg = '<div id="pop-select-day">' 355 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 356 + '<label for="New_d" style="font-weight: bold;">Select Day</label>' 357 + '<input id="New_d" type="text" style="width: 100px; letter-spacing: 1px;"/>' 358 + '</div>'; 359 var jpop = GLO.Popup.Info.open(msg, 'Select Day').getPopup(); 360 jpop.find('.msg').css({ "padding-top": "0" }); 361 362 jpop.find('#New_d').datepicker({ 363 showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths() 364 , onSelect: GLO.Staff.Filter.staffWorkingOnDateSelect, minDate: "-6M", maxDate: "+6M" 365 }); 366 jpop.find('#New_d').blur(); 367 } 368 369 _constructor.staffWorkingOnDateSelect = function() { 370 var jpop = $('#pop-select-day').closest('.glopop'); 371 var jdt = jpop.find('#New_d').blur(); 372 var dt = new Date(jdt.val()); 373 var dtLabel = dt.getWeekDayString(true) + ' ' + dt.toSADate(true); 374 var msg = 'Navigating Calendar to <b style="color: #4F81BD; white-space: nowrap;">' + dtLabel + '</b><br/>and only displaying staff that work that day'; 375 376 GLO.Popup.close(jpop); 377 var ojProcessing = GLO.Popup.Processing.open(msg, 'Navigating Calendar'); 378 379 setTimeout(function() { 380 ojProcessing.close(); 381 GLO.Staff.Filter.reloadStaffWorking(dt); 382 }, 1200); 383 } 384 385 function _setSelectDiffDayWarning() { 386 var fn = function() { $('#staff-filter').focus(); }; 387 var css = 'margin-bottom: 12px; text-align: left;'; 388 var icss = 'white-space: nowrap; font-weight: bold;'; 389 390 var msg1 = '<div style="' + css + '">
390Use this option to only display the staff that work on a specific day</div>'; 391 var msg2 = '<div style="' + css + '">Navigate to the desired day on the calendar, then in the staff filter select <i style="' + icss + '">"Working Different Day"</i></div>'; 392 var msg3 = '<div style="' + css + 'margin-top: 6px; padding-top: 8px; border-top: 1px solid rgba(200,200,240,.8);text-align: center;">Select <i style="' + icss + '">"All"</i> in the staff filter to display all staff</div>'; 393 394 var jpop = GLO.Popup.Info.open(msg1 + msg2 + msg3, 'Navigate Calendar, then Filter Staff by Day', fn).getPopup(); 395 jpop.find('.msg').css({ "padding-top": "0" }); 396 } 397 398 function _createStaffObject(sid, startTime, endTime, iStart, iEnd, color) { 399 var order = 999, thumbnail = null; 400 401 for (var i=0; i < GLO.staffResources.length; i++) { 402 if (GLO.staffResources[i].id == sid) { 403 thumbnail = GLO.staffResources[i].thumbnail; 404 order = i; 405 break; 406 } 407 } 408 409 return { "id": sid, "order": order, "thumbnail": $.trim(thumbnail) 410 , "start_tm": startTime, "end_tm": endTime, "start_sr": iStart, "end_sr": iEnd 411 , "color": color, "smids": [], "breaks": [], "clockInAndOut": [] }; //if have more than 1 clock-ins, other than most recent clock-in put in -> clockInAndOut 412 } 413 414 //1. lookup staff normal off time -> GLO.resourceHours 415 //2. staff adjusted day -> GLO.AdjustedHours 416 //3. business closed due to holiday -> GLO.Data.holidays (not needed: GLO.closedDates), only include staff that adjusted day to be open 417 //4. day marked off with off time -> calEvents 418 _constructor.staffWorkingOnDay = function(dayDate, calEvents) { //= this version does
418NOT rely on data in calendar 419 var dayOfWeek = dayDate.getDay(); 420 var arrStaff = []; 421 422 for (var i=0; i < GLO.resourceHours.length; i++) { 423 var role = UTIL.coalesceInt(GLO.resourceHours[i].role, 0); 424 425 if (role > 99) { 426 var sid = GLO.resourceHours[i].id; 427 var hrs = GLO.Schedule.lookupStaffNormalHours(dayDate, sid); //var hrs = GLO.resourceHours[i].normalHours[dayOfWeek]; 428 var isAdjusted = (hrs.length > 3 && UTIL.parseBool(hrs[3])); 429 430 if (!UserPortal.Calendar.isHoliday(dayDate) || isAdjusted) { 431 var tmStart = hrs[0], tmEnd = hrs[1]; 432 var iStart = UTIL.timeToInt(tmStart), iEnd = UTIL.timeToInt(tmEnd); 433 434 if (GLO.isPOS && iEnd - iStart <= 15) { 435 var tmClockIn = _isClockedIn(sid, calEvents); 436 437 if (UTIL.isValidTime(tmClockIn)) { 438 var tmStart = tmClockIn, tmEnd = _getProviderEndTimeToday(); 439 var iStart = UTIL.timeToInt(tmStart), iEnd = UTIL.timeToInt(tmEnd); 440 } 441 } 442 443 if (iEnd - iStart > 15) { 444 if (UserPortal.staffPerformsClientService(sid)) { 445 var ojStaff = _createStaffObject(sid, tmStart, tmEnd, iStart, iEnd, GLO.resourceHours[i].color); 446 ojStaff.name = UserPortal.getStaffName(sid); //for debugging 447 448 if (GLO.resourceHours[i].walkin_signin_sr > 0) { 449 ojStaff.walkin_signin_sr = GLO.resourceHours[i].walkin_signin_sr; 450 } 451 452 if (_isWorkingOnCurrentDay2(dayDate, ojStaff, calEvents)) { 453 ojStaff.is_first_available_fl = UserPortal.isFirstAvailable(sid); 454 arrStaff.push(ojStaff); 455 } 456 } 457 } 458 } 459 } 460 } 461 462 return arrStaff; 463 } 464 465 function _getProviderEndTimeToday() { 466 var hrType = new Date().getDay() + 1; 467 var endTime; 468 469 for (var i=0; i < GLO.ProviderHours.length; i++) { 470 if (GLO.ProviderHours[i].hours_type_cd == hrType) { 471 endTime = GLO.ProviderHours[i].end_tm; 472 break; 473 } 474 } 475 476 if (UTIL.isValidTime(endTime)) { 477 return endTime; 478 } else { 479 return GLO.calendarMaxTime; 480 } 481 } 482 function _isClockedIn(staffId, calEvents) { 483 for (var i=0; i < calEvents.length; i++) { 484 if (staffId == calEvents[i].staff_id) { 485 if (calEvents[i].appt_status_cd == 201 && UTIL.isDate(calEvents[i].checkin_dt) && UTIL.isEmpty(calEvents[i].checkout_dt)) { 486 return new Date(calEvents[i].checkin_dt).toGloTime(); 487 } 488 } 489 } 490 491 return null; 492 } 493 494 function _staffWorkingOn(dayDate, isCurrDay) { 495 var dayOfWeek = dayDate.getDay(); 496 var arrStaff = []; 497 //var intMinTime = UTIL.timeToInt(GLO.Calendar.minTime), intMaxTime = UTIL.timeToInt(GLO.Calendar.maxTime); 498 //var bizStart = UTIL.joinDateAndTime(dayDate, GLO.Calendar.minTime), bizEnd = UTIL.joinDateAndTime(dayDate, GLO.Calendar.maxTime); 499 500 for (var i=0; i < GLO.resourceHours.length; i++) { 501 var sid = GLO.resourceHours[i].id; 502 var role = UTIL.coalesceInt(GLO.resourceHours[i].role, 0); 503 var hrs = GLO.Schedule.lookupStaffNormalHours(dayDate, sid); //var hrs = GLO.resourceHours[i].normalHours[dayOfWeek]; 504 var iStart = UTIL.timeToInt(hrs[0]); 505 var iEnd = UTIL.timeToInt(hrs[1]); 506 507 if (iEnd - iStart > 15 && role > 99) { 508 if (!isCurrDay || _isWorkingOnCurrentDay(sid, dayDate, iStart, iEnd)) { 509 if (UserPortal.staffPerformsClientService(sid)) { 510 arrStaff.push({ "id": sid, "start_tm": hrs[0], "end_tm": hrs[1] }); 511 } 512 } 513 } 514 } 515 516 return arrStaff; 517 } 518 519 /* OVERVIEW of Label Appt-Status (Priority) 520 21 Checked-In (1 or 21) now >= svc time = BUSY | SVC ends in 15 min YELLOW 521 2 Sign-In (2) CLIENT WAITING PINK 522 5 NOW (5) APPT NOW (starts within 15 minutes) GRADIENT 523 524 39 Break Time (10) ON BREAK DARK GREY 525 41 Upcoming Off Time (11) BREAK in 5 min (starts within 30 minutes) LIGHT GREY 526 527 42 UPCOMING (29) now - 1 hr <= 0 = FREE | APPT in 45 min PURPLE 528 29 LATE (42) CLIENT LATE (15-30 minutes late) LIGHT PURPLE rgba(120, 0,200, .2) 529 */ 530 531 function _updateStaffStatusWithAnotherEvent(ojStaff, ev) { 532 if (UTIL.isEmptyObject(ojStaff.status)) { //= status empty if staff done working for the day 533 //var eventXml = UTIL.htmlEncode(UTIL.jsonToXml(ev)); 534 //GLO.Log.insertSimple('_isWorkingOnCurrentDay2() No ojStaff', eventXml, 'warning'); 535 return; 536 } /* else if (ev.appt_status_cd != ojStaff.status.appt_status_cd) { //these will often NOT match, for example appt status = 10 (new) + staff status = 42 (upcoming)
537 var eventXml = 'eventXml (' + ev.appt_status_cd + '):' + UTIL.htmlEncode(UTIL.jsonToXml(ev)); 538 var staffXml = 'staffXml (' + ojStaff.status.appt_status_cd + '):' + UTIL.htmlEncode(UTIL.jsonToXml(ojStaff)); 539 var logMsg = '_isWorkingOnCurrentDay2() Status: Staff Card vs Event \n\n' + staffXml + ' | ' + eventXml; 540 541 GLO.Log.insertSimple('Staff Card vs Event', logMsg, 'warning'); 542 } */ 543 544 var now = new Date(); 545 546 if (now > new Date(ojStaff.status.event.start) && now < new Date(ojStaff.status.event.end)) { 547 ojStaff.status.otherServices.push(ev); 548 } else if (now > new Date(ev.start) && now < new Date(ev.end)) { 549 ojStaff.status.otherServices.push(ojStaff.status.event); 550 ojStaff.status.event = ev; 551 } else { 552 var ev1 = UTIL.coalesceInt( (new Date(ev.start) - new Date()) / (1000 * 60), 0); 553 var ev2 = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0); 554 var ev0 = Math.abs(ev1) < Math.abs(ev2) ? Math.abs(ev1) : Math.abs(ev2); 555 556 var oj1 = UTIL.coalesceInt( (new Date(ojStaff.status.event.start) - new Date()) / (1000 * 60), 0); 557 var oj2 = UTIL.coalesceInt( (new Date(ojStaff.status.event.end) - new Date()) / (1000 * 60), 0); 558 var oj0 = Math.abs(oj1) < Math.abs(oj2) ? Math.abs(oj1) : Math.abs(oj2); 559 560 if (ev0 < oj0) { 561 ojStaff.status.otherServices.push(ojStaff.status.event); 562 ojStaff.status.event = ev; 563 } else { 564 ojStaff.status.otherServices.push(ev); 565 } 566 } 567 } 568 function _updateStaffStatusForCheckin(ojStaff, ev) { 569 var endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0); 570 571 //ojStaff.status.event.push(ev); //for now this accepts just 1 event (is not an array), additional events for the staff on the same ticket go to: ojStaff.status.other 572 573 ojStaff.status.label = _getStaffStatusLabelForCheckin(ev, endsIn); 574 ojStaff.status.description = 'Staff has ' + (ojStaff.status.otherServices.length + 1) + ' services on this ticket'; 575 } 576 function _getStaffStatusLabelForCheckin(ev, endsIn) { 577 if (endsIn > 0 && endsIn < 60) { 578 return 'Service <i>ends in</i> ' + endsIn + ' <i>min</i>'; 579 } else if (endsIn <= -240) { 580 ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago'; 581 return 'VERY OLD Check-In'; 582 } else if (endsIn <= -60) { 583 ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago'; 584 return 'OLD Check-In'; 585 } else if (endsIn <= 0) { 586 ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago'; 587 return 'Service Ends Soon'; 588 } else { 589 return 'BUSY'; 590 } 591 } 592 function _getStaffStatusLabel(ev, apptStatus) { 593 var startsIn = UTIL.coalesceInt( (new Date(ev.start) - new Date()) / (1000 * 60), 0); 594 var endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0); 595 596 if (apptStatus == 21) { 597 return _getStaffStatusLabelForCheckin(ev, endsIn); 598 } else if (apptStatus == 5) { 599 if (startsIn > 0) { 600 return 'APPT <i>in</i> ' + startsIn + ' <i>min</i>'; 601 } else if (startsIn > -5) { 602 return 'APPT NOW'; 603 } else { 604 return 'APPT ' + Math.abs(startsIn) + ' <i>min late</i>'; 605 } 606 } else if (apptStatus == 2) { 607 var signinWait = UTIL.coalesceInt( (new Date() - new Date(ev.signin_dt)) / (1000 * 60), 0); 608 return 'SIGN-IN ' + signinWait + ' <i>min ago</i>'; 609 } else if (apptStatus == 39) { 610 if (endsIn < 60) { 611 return 'BREAK <i>ends in</i> ' + endsIn + ' <i>min</i>'; 612 } else { 613 return 'ON BREAK'; 614 } 615 } else if (apptStatus == 41) { 616 return 'BREAK <i>starts in</i> ' + startsIn + ' <i>min</i>'; 617 } else if (apptStatus == 42 && startsIn < 60) { 618 return 'APPT <i>starts in</i> ' + startsIn + ' <i>min</i>'; 619 } else if (apptStatus == 29) { 620 return 'CLIENT ' + Math.abs(startsIn) + ' <i>min</i> LATE'; 621 } else { 622 return 'AVAILABLE'; 623 } 624 } 625 function _getStaffStatus(ev, apptStatus, priority) {
626 var label = _getStaffStatusLabel(ev, apptStatus); 627 var description = ''; 628 629 return { "label": label, "description": description, "appt_status_cd": apptStatus, "priority": priority, "event": ev, "otherServices": [] }; 630 } 631 function _setStaffStatus(ojStaff, ev, apptStatus, priority) { 632 var objStatus = _getStaffStatus(ev, apptStatus, priority); 633 634 if (ojStaff.status && ojStaff.status.priority) { 635 if (ojStaff.status.priority > priority) { 636 _changeStaffStatus(ojStaff, objStatus); 637 } else if (ojStaff.status.priority = priority) { 638 if (objStatus.apptStatus == 21) { //= use current. 639 if (new Date(objStatus.event.start) < new Date() && new Date(objStatus.event.end) > new Date()) { 640 _changeStaffStatus(ojStaff, objStatus); 641 } else if (new Date(objStatus.event.start) > new Date() && objStatus.event.staff_id == ojStaff.status.event.staff_id) { 642 _changeStaffStatus(ojStaff, objStatus); 643 } else { 644 ojStaff.status.other.push(objStatus); 645 } 646 } else if (objStatus.apptStatus == 39) { //= use latest. 647 if (new Date(objStatus.event.end) > new Date(ojStaff.status.event.end)) { 648 _changeStaffStatus(ojStaff, objStatus); 649 } else { 650 ojStaff.status.other.push(objStatus); 651 } 652 } else { //= use first. 653 if (new Date(objStatus.event.start) < new Date(ojStaff.status.event.start)) { 654 _changeStaffStatus(ojStaff, objStatus); 655 } else { 656 ojStaff.status.other.push(objStatus); 657 } 658 } 659 } else { 660 ojStaff.status.other.push(objStatus); 661 } 662 } else { 663 objStatus.other = []; 664 ojStaff.status = objStatus; 665 } 666 } 667 function _changeStaffStatus(ojStaff, objStatus) { 668 objStatus.other = ojStaff.status.other; 669 objStatus.other.push({ "label": ojStaff.status.label, "description": ojStaff.status.description, "appt_status_cd": ojStaff.status.apptStatus, "priority": ojStaff.status.priority }); 670 671 ojStaff.status = objStatus; 672 } 673 674 function _isInCalendarStaffFilter(staffId) { //= if on calendar: check staff in filter or staff who do client services (with accessType < 4) 675 if (GLO.Calendar === undefined) { 676 return true; 677 } 678 679 var arrStaff = GLO.staffResources; 680 681 if (GLO.staffResourcesAll && GLO.staffResourcesAll.length) { 682 arrStaff = GLO.staffResourcesAll; 683 } 684 685 for (var i=0; i < arrStaff.length; i++) { 686 if (arrStaff[i].id == staffId) { 687 return true; 688 } 689 } 690 691 return false 692 } 693 694 function _isWorkingOnCurrentDay2(dayDate, ojStaff, calEvents) { 695 var offHourSGID = UserPortal.getOffTimeServiceGroupId(); 696 var internalSGID = UserPortal.getInternalServiceGroupId(); 697 var day = new Date(dayDate.toGloDate()); 698 var faId = UserPortal.getFirstAvailableStaffId(); 699 700 ojStaff.now_count_sr = ojStaff.service_count_sr = ojStaff.upcoming_count_sr = ojStaff.past_count_sr = ojStaff.checkin_count_sr = ojStaff.checkout_count_sr = ojStaff.cancel_count_sr = 0; 701 ojStaff.signin_count_sr = ojStaff.late_count_sr = 0; 702 703 if (calEvents) { 704 for (var i=0; i < calEvents.length; i++) { 705 var ev = calEvents[i]; 706 var evStaffId = UTIL.coalesceInt(ev.staff_id, faId); 707 708 if (evStaffId == ojStaff.id) { 709 if (ev.service_group_id == offHourSGID) { 710 if (ojStaff.end_sr > 0) { //= day NOT already blocked off. 711 var eventStart = new Date(ev.start), eventEnd = new Date(ev.end); 712 var istart = UTIL.timeToInt(eventStart.toGloTime()), iend = UTIL.timeToInt(eventEnd.toGloTime()); 713 var isEventStartsOnPrevDay = (new Date(eventStart.toGloDate()) < day); 714 var isEventEndsOnLaterDay = (new Date(eventEnd.toGloDate()) > day); 715 716 if (isEventStartsOnPrevDay || istart <= ojStaff.start_sr) { //= personal time event: starts on previous day OR starts before/on day's start 717 ojStaff.start_sr = iend; 718 ojStaff.start_tm = eventEnd.toGloTime(); 719 } 720 721 if (isEventEndsOnLaterDay || iend >= ojStaff.end_sr) { 722 ojStaff.end_sr = istart; 723 ojStaff.end_tm = eventStart.toGloTime(); 724 } 725 726 if ((isEventStartsOnPrevDay && isEventEndsOnLaterDay) || ojStaff.end_sr - ojStaff.start_sr < 15) { 727 ojStaff.start_sr = ojStaff.end_sr = 0; 728 ojStaff.start_tm = ojStaff.end_tm = null; 729 } 730 731 if (istart > ojStaff.start_sr && ojStaff.end_sr > iend && !isEventStartsOnPrevDay && !isEventEndsOnLaterDay) { //= is mid day break 732 ojStaff.breaks.push({ "start_tm": eventStart.toGloTime(), "end_tm": eventEnd.toGloTime(), "service_vc": ev.service_name_vc, "start_sr": istart, "end_sr": iend }); 733 734 if (eventEnd > new Date()) { 735 if (new Date() > eventStart) { 736 _setStaffStatus(ojStaff, ev, 39, 10); 737 } else if (new Date().addMinutes(30) > eventStart) { 738 _setStaffStatus(ojStaff, ev, 41, 11); 739 } 740 } 741 } 742 } 743 } else if (ev.service_group_id == internalSGID) { 744 if (UTIL.isDate(ev.checkin_dt) && (!UTIL.isDate(ojStaff.clockin_dt) || new Date(ev.checkin_dt) > ojStaff.clockin_dt) //= get day's last clock-in 745 && UTIL.isToday(ev.checkin_dt)) { //= verify checkin is not from previous day (probably because staff forgot to clock-out) 746 ojStaff.clockin_dt = new Date(ev.checkin_dt); 747 748 if (ojStaff.clockin_dt > ojStaff.clockout_dt) { 749 ojStaff.clockInAndOut.push({ "clockin_dt": new Date(ojStaff.clockin_dt), "clockout_dt": new Date(ojStaff.clockout_dt) }); 750 ojStaff.clockout_dt = null; 751 } 752 } 753 754 if (UTIL.isDate(ev.checkout_dt) && (!UTIL.isDate(ojStaff.clockout_dt) || new Date(ev.checkout_dt) > ojStaff.clockout_dt) //= get day's last clock-out 755 && UTIL.isToday(ev.checkin_dt)) { //= verify checkin is not from previous day (probably because staff forgot to clock-out) 756 ojStaff.clockout_dt = new Date(ev.checkout_dt); 757 } 758 } else { 759 ++ojStaff.service_count_sr; 760 var dtStart = new Date(ev.start); 761 762 if (ojStaff.smids.has(ev.schedule_multi_id)) { 763 _updateStaffStatusWithAnotherEvent(ojStaff, ev); 764 765 if (ev.appt_status_cd == 21 && ojStaff.status && ojStaff.status.appt_status_cd == 21) { 766 _updateStaffStatusForCheckin(ojStaff, ev); 767 } 768 } else { 769 ojStaff.smids.push(ev.schedule_multi_id); 770 771 if (ev.appt_status_cd == 22) { //CHECK-OUT: UTIL.isDate(ev.checkout_dt) || ev.appt_status_cd == 120 772 ++ojStaff.checkout_count_sr; 773 } else if (ev.appt_status_cd == 21 || ev.appt_status_cd == 25) { //CHECK-IN, READY-To-PAY: UTIL.isDate(ev.checkin_dt) 774 ++ojStaff.checkin_count_sr; 775 776 if (ev.appt_status_cd == 21) {
777 var priority = 1, endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0); 778 779 if (endsIn <= -60) { 780 priority = 21; 781 } 782 783 _setStaffStatus(ojStaff, ev, 21, priority); 784 } 785 } else if (ev.appt_status_cd == 13 || ev.appt_status_cd == 14) { //NO-SHOW or LATE-CANCEL 786 ++ojStaff.cancel_count_sr; 787 } else if (UTIL.isDate(ev.signin_dt) && new Date(ev.signin_dt).toGloDate() == new Date().toGloDate()) { //SIGN-IN: ev.appt_status_cd == 2 788 ++ojStaff.signin_count_sr; 789 _setStaffStatus(ojStaff, ev, 2, 2); 790 791 } else if (dtStart > new Date().addMinutes(-15) && dtStart < new Date().addMinutes(15)) { //NOW: ev.appt_status_cd == 5 792 ++ojStaff.now_count_sr; 793 _setStaffStatus(ojStaff, ev, 5, 5); 794 } else if (new Date() > dtStart && dtStart > new Date().addMinutes(-90)) { //LATE: ev.appt_status_cd == 29 795 ++ojStaff.late_count_sr; 796 797 if (dtStart > new Date().addMinutes(-30)) { 798 _setStaffStatus(ojStaff, ev, 29, 29); 799 } 800 } else if (dtStart > new Date()) { //UPCOMING: ev.appt_status_cd >= 40 && ev.appt_status_cd <= 49 801 ++ojStaff.upcoming_count_sr; 802 _setStaffStatus(ojStaff, ev, 42, 42); 803 } else { //PAST: ev.appt_status_cd >= 90 && ev.appt_status_cd <= 99 804 ++ojStaff.past_count_sr; 805 } 806 } 807 } 808 } 809 } 810 } 811 812 if (!_isInCalendarStaffFilter(ojStaff.id)) { 813 return false; 814 } else if (ojStaff.start_sr + 15 > ojStaff.end_sr) { 815 return false; 816 } else { 817 return true; 818 } 819 } 820 function _isWorkingOnCurrentDay(sid, dayDate, iStart, iEnd) { //= checks to see if staff has marked day off with personal time event(s) 821 var isFoundStaff = false, calEvents = GLO.Calendar.cal.fullCalendar('clientEvents'); 822 823 for (var i=0; i < calEvents.length; i++) { 824 var calEvent = calEvents[i]; 825 826 if (calEvent.staff_id == sid) { 827 isFoundStaff = true; 828 829 if (calEvent.className.has('cal-monthDayPersonal')) { 830 var day = new Date(dayDate.toGloDate()); 831 832 if (new Date(calEvent.start.toGloDate()) < day) { //= personal time event starts on previous day. 833 var begin = 0; 834 } else { 835 var begin = UTIL.timeToInt(calEvent.start.toGloTime()); 836 } 837 838 if (new Date(calEvent.end.toGloDate()) > day) { //= personal time event ends on day afterwards. 839 var end = 60 * 24; 840 } else { 841 var end = UTIL.timeToInt(calEvent.end.toGloTime()); 842 } 843 844 if (begin <= iStart && end >= iEnd) { 845 iStart = end; 846 } 847 } 848 } else if (isFoundStaff) { 849 break; 850 } 851 } 852 853 if (iStart + 15 > iEnd) { 854 return false; 855 } else { 856 return true; 857 } 858 } 859 860 function _isCurrentDayOnCalendar(dt) { 861 if (GLO.Calendar === undefined) { return false; } 862 863 var dtCalendar = new Date(GLO.Calendar.cal.fullCalendar('getView').start).toGloDate(); 864 var dt = new Date(dt).toGloDate(); 865 866 if (dtCalendar === dt) { 867 return true; 868 } else { 869 return false; 870 } 871 } 872 873 _constructor.reloadStaffWorking = function(dt) { 874 if (UTIL.isDate(dt)) { 875 dt = new Date(dt); 876 } else { 877 dt = new Date(); 878 } 879 880 var isCurrDay = _isCurrentDayOnCalendar(dt); 881 var arrStaff = _staffWorkingOn(dt, isCurrDay); 882 883 if (arrStaff.length === 0) { 884 var msg = '<div id="pop-warn-no-staff-working">No Staff Work are working on <b>' + dt.getWeekDayString() + ' ' + dt.toSADate(true) + '</b></div>'; 885 GLO.Popup.Warning.open(msg, 'No Staff Working'); 886 _setFilterToUrl(); 887 return; 888 } 889
890 var url = _getStaffWorkingOnUrl(arrStaff, dt); 891 892 GLO.Popup.close($('#pop-filter-staff-working-today').closest('.glopop')); 893 894 if (_mustReloadPage(arrStaff, dt, url)) { return; } 895 896 _setStaffWorking(arrStaff); 897 _constructor.reloadStaffCalendar(dt, url, true); 898 } 899 900 _constructor.reloadStaffCalendar = function(dt, url, isWorkingOnly) { 901 var dtLabel = dt.getWeekDayString(true) + ' ' + dt.toSADate(true); 902 903 _changeUrl(url, dtLabel); 904 _reorderCalendar_WorkoutOnDay(dtLabel, isWorkingOnly); 905 _updateStaffFilter_DiffDay(dt, dtLabel, isWorkingOnly); 906 907 if (GLO.Info.isMobile()) { 908 setTimeout(function() { 909 GLO.Calendar.cal.fullCalendar('resize_sa'); 910 }, 280); 911 } 912 } 913 914 function _updateStaffFilter_DiffDay(dt, dtLabel, isWorkingOnly) { 915 var sfiltergroup = GLO.Uri.query('sfiltergroup'); 916 if (sfiltergroup !== 'today' && sfiltergroup !== 'diffday' && sfiltergroup !== 'workingonly') { return; } 917 918 var jfilter = $('#staff-filter'); 919 var jtoday = jfilter.find('#staff-filter-today'); 920 var jdiffday = jfilter.find('#staff-filter-diffday'); 921 922 if (!isWorkingOnly) { 923 jtoday.prop('selected', true); 924 jdiffday.remove(); 925 } else if (GLO.Calendar.isToday()) { 926 jtoday.prop('selected', true); 927 928 if (jdiffday.length > 0) { 929 jdiffday.text('Working Different Day'); 930 } else { 931 jtoday.after('<option value="diffday" id="staff-filter-diffday">Working Different Day</option>'); 932 } 933 } else { 934 if (jdiffday.length > 0) { 935 jdiffday.text('Working ' + dtLabel).attr('date', dt.toGloDate()).prop('selected', true); 936 } else { 937 jtoday.after('<option value="diffday" id="staff-filter-diffday" date="' + dt.toGloDate() + '" selected="selected">Working ' + dtLabel + '</option>'); 938 } 939 } 940 } 941 942 _constructor.loadStaffWorkingOnly = function() { 943 if (GLO.Calendar !== undefined) { 944 var dtDay = GLO.Calendar.cal.fullCalendar('getView').visStart; 945 } else { 946 var dtDay = new Date(); 947 } 948
949 var url = _getStaffWorkingOnlyUrl(dtDay); 950 951 if (String(UTIL.coalesce(GLO.Uri.query('sfilter'), 'all')).toLowerCase() != 'all') { 952 var msg = 'Re-loading Calendar to include all staff working on ' + dtDay.toGloDateString(true, true); 953 GLO.Popup.Processing.open(msg, 'Re-loading Calendar'); 954 955 setTimeout(function() { 956 document.location = url; 957 }, 100); 958 } else { 959 _changeUrl(url, 'Only Staff Working'); 960 GLO.Calendar.refreshEvents(true, true); 961 } 962 } 963 964 function _changeUrl(url, label, forceUrl) { 965 try { 966 window.history.pushState('', label, url); 967 } catch (e) { 968 if (forceUrl) { 969 document.location = url; 970 } 971 } 972 973 //GLO.Calendar.displayHomeButton(); 974 } 975 976 function _reorderCalendar_WorkoutOnDay(dtLabel, isWorkingOnly) { //= similar to: _reorderCalendar 977 if (isWorkingOnly) { 978 var msg = 'Re-loading Calendar for staff working on ' + dtLabel + '...'; 979 } else { 980 var msg = 'Updating Calendar...'; 981 } 982 983 var ojProcessing = GLO.Popup.Processing.open(msg, 'Re-loading Calendar'); 984 GLO.Schedule.Calendar.reloadCalendar(null, ojProcessing); 985 } 986 987 function _setStaffWorking(arrStaff) { 988 var arrResource = GLO.staffResourcesAll.slice(); 989 990 for (var a = arrResource.length - 1; a >= 0; a--) { 991 var found = false; 992 993 for (var b=0; b < arrStaff.length; b++) { 994 if (arrResource[a].id == arrStaff[b].id) { 995 found = true; 996 break; 997 } 998 } 999 1000 if (!found) { 1001 arrResource.splice(a, 1); 1002 } 1003 } 1004 1005 GLO.staffResources = arrResource; 1006 } 1007 1008 _constructor.hasStaffInList = function(arrStaff, arrResourceList) { 1009 for (var a=0; a < arrStaff.length; a++) { 1010 var hasStaff = false, sid = arrStaff[a].id; 1011 1012 for (var r=0; r < arrResourceList.length; r++) { 1013 if (sid == arrResourceList[r].id) { 1014 hasStaff = true; 1015 break; 1016 } 1017 } 1018 1019 if (!hasStaff) { 1020 return false; 1021 } 1022 } 1023 1024 return true; 1025 } 1026 function _mustReloadPage(arrStaff, dt, url, isCheckOnly) { 1027 if (GLO.isFrontDeskCalendar) { 1028 //var sfilter = String(UTIL.coalesce(GLO.Uri.query('sfilter'), 'all')).toLowerCase(); 1029 1030 if (isCheckOnly && arrStaff.length === 1) { //= must redirect to individual calendar. 1031 return true; 1032 } else if (GLO.Staff.Filter.hasStaffInList(arrStaff, GLO.staffResourcesAll)) { 1033 return false; 1034 } else if (isCheckOnly) { 1035 return true; 1036 } 1037 } 1038 1039 if (!isCheckOnly && url !== document.location.href) { 1040 var msg = 'Re-loading Calendar for staff working on ' + dt.getWeekDayString() + ' ' + dt.toSADate(true); 1041 GLO.Popup.Processing.open(msg, 'Re-loading Calendar'); 1042 1043 setTimeout(function() { 1044 document.location = url; 1045 }, 100); 1046 } 1047 1048 return true; 1049 } 1050 1051 function _staffArrayToString(arrStaff) { 1052 var str = ''; 1053 1054 for (var a=0; a < arrStaff.length; a++) { 1055 if (a > 0) { str += ','; } 1056 str += arrStaff[a].id; 1057 } 1058 1059 return str; 1060 } 1061 1062 function _getStaffWorkingOnlyUrl(dtDay) { 1063 var url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=all&sfiltergroup=workingonly'; 1064 var hash = '#vw=resourceDay&dt='; 1065 1066 if (UTIL.isToday(dtDay)) { 1067 hash += 'today'; 1068 } else { 1069 hash += dtDay.toGloDate(); 1070 } 1071 1072 return url + hash; 1073 } 1074 1075 function _getStaffWorkingOnUrl(arrStaff, dt) { 1076 var url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=' + _staffArrayToString(arrStaff) + '&sfiltergroup='; 1077 var mid = '#vw=resourceDay&dt='; 1078 1079 if (UTIL.isSameDay(dt, new Date(GLO.Data.provider.now_dt))) { 1080 url += 'today' + mid + 'today'; 1081 } else { 1082 url += 'diffday' + mid + dt.toGloDate(); 1083 } 1084 1085 return url; 1086 } 1087 1088 _constructor.loadOnlyStaffWorking = function(dtDay) { 1089 if (!UTIL.isDate(dtDay)) { 1090 var dtDay = GLO.Calendar.cal.fullCalendar('getView').start; 1091 } 1092 1093 /*_staffWorkingOn(dtDay, isCurrDay) 1094 _setDaysOff_resourceDay(dtSt, dtEnd) 1095 1096 lookup days off based on 1097 GLO.Data.holidays + GLO.closedDates -> biz level 1098 GLO.resourceHours + GLO.AdjustedHours -> staff level 1099 */ 1100 } 1101 1102 function _changeUrlFromHeader(queryString) { 1103 $('#top-staffName #staff-filter #only-staff-working').text('Only Staff Working'); 1104 1105 document.location = document.location.origin + document.location.pathname + '?' + queryString; 1106 //GLO.Calendar.displayHomeButton(); 1107 } 1108 1109 _constructor.changeHeader = function(element) { 1110 var jOption = $(element).find(':selected'); 1111 var id = jOption.attr('value'); 1112 1113 if (jOption.attr('value') === 'inventory') { 1114 document.location = GLO.Link.Page.Provider.Home + 'Inventory/'; 1115 } else if (id === 'workingonly') { 1116 GLO.Staff.Filter.loadStaffWorkingOnly(); 1117 1118 } else if (id === 'today') { //depreciated in favor of workingonly 1119 _loadWorkingToday(false); 1120 } else if (id === 'diffday') { //depreciated in favor of workingonly 1121 _loadWorkingToday(true); 1122 1123 } else if (jOption.parent().attr('id') == 'location-filter-sg') { 1124 _changeLocation(jOption); 1125 } else if (jOption.attr('value') == '' || jOption.attr('value') == '-99') { 1126 _constructor.open(); 1127 } else if (jOption.val() === 'house') { 1128 if (_constructor.isReportPortal) { 1129 GLO.Report.changeStaffFilter(jOption); 1130 } else { 1131 var sfilter = _constructor.getHouseStaff(); 1132 _changeUrlFromHeader('sfiltergroup=4&sfilter=' + sfilter); //document.location = document.location.origin + document.location.pathname + '?sfiltergroup=4&sfilter=' + sfilter; 1133 } 1134 } else if (jOption.val() === 'not-house') { 1135 if (_constructor.isReportPortal) { 1136 GLO.Report.changeStaffFilter(jOption); 1137 } else { 1138 var sfilter = _constructor.getNotHouseStaff(); 1139 _changeUrlFromHeader('sfiltergroup=5&sfilter=' + sfilter); //document.location = document.location.origin + document.location.pathname + '?sfiltergroup=5&sfilter=' + sfilter; 1140 } 1141 } else if ($('#report-main').length === 1 || $('.report-search-header:visible').length === 1) { 1142 GLO.Report.changeStaffFilter(jOption); //$('.report-search-header:visible').find('.btnSearch a').click(); 1143 } else if (GLO.MyAppts.isActivityView) { 1144 _changeFilterOnActivityView(jOption); 1145 } else if (jOption.parent().attr('id') == 'staff-filter-sg') { 1146 var dt = UTIL.cleanString(GLO.Uri.hash('dt'));
1147 document.location = GLO.Link.Page.Provider.SetFilter + '?type=sg&id=' + id + '&dt=' + dt; 1148 } else if (jOption.parent().attr('id') == 'staff-filter-staff-group') { 1149 //document.location = GLO.Info.http + document.location.host + '/calendar?dt=' + UTIL.cleanString(GLO.Uri.hash('dt')) + '&sfilter=' + jOption.attr('staff_ids'); 1150 _changeUrlFromHeader('dt=' + UTIL.cleanString(GLO.Uri.hash('dt')) + '&sfilter=' + jOption.attr('staff_ids')); 1151 } else if (_constructor.isReportFilterEasyQuery) { 1152 document.location = document.location.origin + document.location.pathname + '?sfilter=' + element.value; 1153 } else if (jOption.attr('value') == 'all') { 1154 _constructor.gotoSchedule(id, 'all'); 1155 } else { //if (jOption.parent().attr('id') == 'staff-filter-s') 1156 _constructor.gotoSchedule(id); 1157 } 1158 } 1159 1160 function _changeFilterOnActivityView(jOption) { 1161 GLO.Report.changeStaffFilter(jOption); 1162 1163 if ($('#myAppointments-wait').length > 0) { 1164 GLO.WaitList.refreshActivityView(); 1165 } 1166 1167 $('#staffPortal-main').find('.appt-list-search:visible').find('.btnSearch > a:visible').click(); 1168 } 1169 1170 function _changeLocation(joption) { 1171 var pid = joption.attr('value'); 1172 var pnm = joption.text(); 1173 var pc = joption.css('background-color').replace('.2', '.6'); 1174 1175 _constructor.switchLocation(pid, pnm, pc); 1176 } 1177 1178 _constructor.changeLocation = function(select, event) { 1179 var joption = $(select).find(':selected'); 1180 var pid = joption.attr('value'); 1181 var pnm = joption.text(); 1182 var pc = 'rgba(' + joption.attr('provider_color_vc') + ',.6)'; 1183 1184 _constructor.switchLocation(pid, pnm, pc); 1185 } 1186 1187 _constructor.switchLocation = function(providerId, providerName, providerColor, urlGoTo) { 1188 urlGoTo = UTIL.coalesceString(urlGoTo, document.location.pathname + document.location.search + document.location.hash); 1189 var url = GLO.Link.WebsiteDomain + 'provider/SwitchProvider?newpid=' + providerId + '&url=' + encodeURIComponent(urlGoTo); 1190 1191 var msg = '<div> <h1 class="friendly-msg4">Loading New Location</h1> <div class="friendly-msg4">Changing Location to ' + providerName + '...</div> </div>'; 1192 var ojProcessing = new GLO.Popup.Processing(msg); 1193 var jprocessing = ojProcessing.getPopup(); 1194 jprocessing.css({ "background-color": providerColor, "color": "White" }); 1195 1196 setTimeout(function() { 1197 document.location = url; 1198 }, 200); 1199 } 1200 1201 _constructor.switchLocationTo = function(providerId, warningMessage) { 1202 var jdd = $('#staff-filter').find('#location-filter-sg'); 1203 1204 if (jdd.length === 0) { jdd = $('#location-filter'); } 1205 1206 var jopt = jdd.find('option[value="' + providerId + '"]'); 1207 1208 if (jopt.length === 0) { 1209 htm = '<div class="friendly-responsive">' + warningMessage + '</div>'; 1210 new GLO.Popup.Warning(htm); 1211 } else { 1212 _changeLocation(jopt); 1213 } 1214 } 1215 1216 _constructor.getHouseStaff = function() { 1217 var dt = UTIL.cleanString(GLO.Uri.hash('dt')); 1218 var jstaff = UserPortal.getStaffDropDown().find('option'); 1219 var sfilter = ''; 1220 1221 for (var i=0; i < jstaff.length; i++) { 1222 var js = jstaff.eq(i); 1223 1224 if (UTIL.coalesceInt(js.attr('merchant_type_cd'), 99) < 20) { 1225 if (sfilter !== '') { sfilter += ','; } 1226 sfilter += js.attr('value'); 1227 } 1228 } 1229 1230 return sfilter + ',-9'; 1231 } 1232 _constructor.getNotHouseStaff = function() { 1233 var dt = UTIL.cleanString(GLO.Uri.hash('dt')); 1234 var jstaff = UserPortal.getStaffDropDown().find('option'); 1235 var sfilter = ''; 1236 1237 for (var i=0; i < jstaff.length; i++) { 1238 var js = jstaff.eq(i), sid = js.attr('value'); 1239 1240 if (!UTIL.isEmpty(sid) && UTIL.coalesceInt(js.attr('merchant_type_cd'), 99) > 19) { 1241 if (sfilter !== '') { sfilter += ','; } 1242 sfilter += sid; 1243 } 1244 } 1245 1246 return sfilter + ',-5'; 1247 } 1248 1249 _constructor.staffHasClientService = function(js) { 1250 1251 } 1252 1253 function _revertBackToAllStaff(staffIds, groupType, dt, uri, qs) { 1254 if (staffIds === 'all' && groupType === 'all' && GLO.staffResourcesAll && GLO.staffResourcesAll.length) { 1255 GLO.staffResources = GLO.staffResourcesAll; 1256 //GLO.staffResourcesAll = undefined; 1257 1258 _constructor.reloadStaffCalendar(new Date(dt), uri + 'calendar' + qs); 1259 return true; 1260 } 1261 1262 return false; 1263 } 1264 1265 function _getGoToScheduleUri(uri, staffIds, groupType) { 1266 if ($('#staffPortal-main:visible').length === 1) { 1267 uri += 'apptportal'; 1268 } else if ($('#reminder-day-view:visible').length === 1) { 1269 uri += 'reminders'; 1270 } else { //if (GLO.Calendar !== undefined) { //if ($('#calendar .fc-view:visible').length === 1 || $('.fc-view-resourceDay:visible').length === 1) { 1271 if (GLO.Info.providerPackage === 1) { 1272 uri += 'calendar'; 1273 } else if (groupType === 'all' || staffIds === '' || String(staffIds).indexOf(",") != -1) { 1274 uri += 'calendar'; 1275 } else { 1276 uri += 'calendarOne'; 1277 } 1278 } 1279 1280 return uri; 1281 } 1282 1283 function _getStaffIdArray(sids) { 1284 var arrStaff = [], arrTemp = String(sids).split(','); 1285 1286 for (var i=0; i < arrTemp.length; i++) { 1287 arrStaff.push({ "id": arrTemp[i] }); 1288 } 1289 1290 return arrStaff; 1291 } 1292 1293 function _getDateFromUriHashKey(hashKey) { 1294 var dt = GLO.Uri.hash(hashKey).toLowerCase(); 1295 1296 if (dt === 'tomorrow') { 1297 dt = new Date(); 1298 dt = new Date(dt.setDate(dt.getDate() + 1)); 1299 } else if (!UTIL.isDate(dt)) { 1300 dt = new Date(); 1301 } else { 1302 dt = new Date(UTIL.replaceAll(dt, '-', '/')); //if do NOT replace '-' with '/', then this actually subtracts 1 day from date 1303 } 1304 1305 return dt; 1306 } 1307 1308 _constructor.gotoSchedule = function(staffIds, groupType, jbtn, isAllowInactive) { 1309 $('#top-staffName #staff-filter #only-staff-working').text('Only Staff Working'); 1310 1311 if (staffIds === undefined) { 1312 staffIds = UTIL.cleanString($('#staff-filter').val()); 1313 1314 if (staffIds === '' && GLO.Info.isMobile()) { 1315 staffIds = UTIL.cleanString($('#staff-filter').find('option:first').val()); 1316 } 1317 } 1318 1319 var dt = _getDateFromUriHashKey('dt'); 1320 var qs = '?sfilter=' + staffIds + '#dt=' + dt.toGloDate(true), uri = GLO.Link.Page.Provider.Home; 1321 var arrStaff = _getStaffIdArray(staffIds); 1322 1323 if (_revertBackToAllStaff(staffIds, groupType, dt, uri, qs)) { 1324 return; 1325 } 1326 1327 var uri = _getGoToScheduleUri(uri, staffIds, groupType); 1328 var currURI = document.location.origin + document.location.pathname + document.location.search; 1329 var newURI = uri + qs.substring(0, qs.indexOf('#')); 1330 1331 if (GLO.Calendar !== undefined) { 1332 qs += '&vw=' + GLO.Uri.hash('vw'); 1333 } 1334 1335 if (!_mustReloadPage(arrStaff, dt, uri + qs, true)) { 1336 _setStaffWorking(arrStaff); 1337 _constructor.reloadStaffCalendar(dt, uri + qs, true); 1338 1339 $.modal.close(); 1340 return; 1341 } 1342 1343 if (currURI == newURI) { 1344 GLO.Popup.Info.open('You did not change the current filter', 'Schedule Filter'); 1345 GLO.Log.insert('You did not change the current filter'); 1346 } else { 1347 if (jbtn) { 1348 GLO.UI.Form.beginProcessing(jbtn); 1349 } else if (GLO.Info.isMobile(true)) { 1350 GLO.UI.animate(2); 1351 } 1352 1353 setTimeout(function() { 1354 document.location = uri + qs; //document.location = GLO.Link.Page.Provider.SetFilter + qs; 1355 }, 100); 1356 } 1357 } 1358 1359 _constructor.open = function(message, fnOnLoadComplete) { 1360 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"}); 1361 var uri = GLO.Link.Page.Provider.StaffFilter + '?type=custom&ispartial=1&dt=' + UTIL.getDateString(); 1362 var pop = $('#pop-temp'); 1363 1364 pop.html(throbber).load(uri, function() { 1365 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 1366
1367 var modalHeight = 640, jmodal = $('#simplemodal-container'); 1368 var staffCount = jmodal.find('#sFilter-list > tbody > tr').length; 1369 1370 $('#simplemodal-container, .simplemodal-data, #simplemodal-container .shadow-content0').css({ "padding": "0" }); 1371 jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 1372 1373 if (innerWidth < 780) { 1374 var popWidth = innerWidth * .9; 1375 1376 if (popWidth < 320) { popWidth = 320; } 1377 } else { 1378 var popWidth = 760; 1379 } 1380 1381 if (GLO.Info.isMobile()) { 1382 modalHeight = jmodal.find('#sfilter-container').outerHeight() - 60; 1383 } else if (innerHeight > 900 && staffCount > 10) { 1384 modalHeight = 840; 1385 1386 var jtbl = jmodal.find('#sFilter-list-container'); 1387 jtbl.height(jtbl.height() + 200); 1388 } else if (modalHeight < innerHeight) { 1389 modalHeight += 48; //need space for buttons at bottom of popup. 1390 } 1391 1392 if (modalHeight > innerHeight) { 1393 jmodal.find('#sfilter-instructions').remove(); 1394 jmodal.find('#sfilter-container .sFilter-buttons').css({ "bottom": "-2px" }); 1395 modalHeight = innerHeight - 20; 1396 1397 var tblHeight = modalHeight - (jmodal.find('h2').height() + jmodal.find('#sfilter-staff-table thead').height() + jmodal.find('.sFilter-buttons').height()); 1398 jmodal.find('#sFilter-list-container').css({ "height": tblHeight + "px" }); 1399 } 1400 1401 jmodal.css({ "max-height": modalHeight + "px" }); 1402 $.modal.update(modalHeight, popWidth); 1403 GLO.Staff.Filter.init(message); 1404 1405 if (fnOnLoadComplete) { fnOnLoadComplete(jmodal, message); } 1406 _addResizeCalendarToFitScreen(jmodal); 1407 }); 1408 1409 pop.modal(); 1410 $.modal.update(300, 300); 1411 1412 var jfilter = $('select#staff-filter'); 1413 1414 if (jfilter.find('option#staff-filter-change').length === 0) { 1415 jfilter.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>'); 1416 } 1417 1418 _initDisplayMessage(message); 1419 } 1420 1421 function _addResizeCalendarToFitScreen(jmodal) { 1422 var mode = _constructor.getFitScreenMode(); 1423 1424 if (mode === 0 || innerWidth < 800) { return; } 1425 1426 if (mode === 1) { 1427 var btnText = 'Wide Calendar', btnTitle = 'Makes the staff columns on the calendar normal width'; 1428 } else { 1429 var btnText = 'Fit All Staff', btnTitle = 'Shrinks the staff columns on the calendar so there is no need to scroll left/right'; 1430 } 1431 1432 var left = 8, h2 = jmodal.find('h2'); 1433 1434 if (h2.find('#select-language-icon-globe:visible').length > 0) { left = 50; } 1435 1436 var btn = '<span id="btnFitCalendar" class="btnAdd" style="left: ' + left + 'px;" title="' + btnTitle + '"><a onclick="GLO.Staff.Filter.fitCalendarToScreen()">' + btnText + '</a></span>'; 1437 h2.prepend(btn); 1438 } 1439 1440 _constructor.displayFitScreenIcon = function() { 1441 var mode = _constructor.getFitScreenMode(); 1442 1443 if (mode === 0 || innerWidth < 600) { return; } 1444 1445 if (mode === 1) { 1446 var icon = '⥅'; //↭ 1447 var btnTitle = 'Wide Calendar: Revert the staff columns on the calendar to normal width'; 1448 } else { 1449 var icon = '⥆'; 1450 var btnTitle = 'Fit to Screen: Shrinks the staff columns on the calendar so there is no need to scroll left/right'; 1451 } 1452 1453 icon = '<b id="fit-screen-icon" onclick="GLO.Staff.Filter.fitCalendarToScreen()" title="' + btnTitle + '">' + icon + '</b>'; 1454 $('.fc-header-right').prepend(icon); 1455 } 1456 1457 _constructor.getFitScreenMode = function() { 1458 if (!GLO.isFrontDeskCalendar || !GLO.staffResources || GLO.staffResources.length === 0) { return 0; } 1459 if (GLO.Info.isIPad || GLO.Mobile.isTablet) { return 0; } 1460 1461 var minWidth = GLO.staffResources.length * 100; 1462 var avgColWidth = parseInt((innerWidth - 43)/GLO.staffResources.length); 1463 var fitCookie = $.cookies.get('fit-calendar'); 1464 var isFitCalendar = UTIL.parseBool(fitCookie); 1465 1466 if (isFitCalendar) { //= is in fit to screen mode 1467 return 1; 1468 } else if (UTIL.isEmpty(fitCookie) && UserPortal.Calendar.isWorkingOnly()) { 1469 return 1; 1470 } else if (UTIL.isEmpty(fitCookie) && minWidth > innerWidth && avgColWidth > 40) { //= is default (staff columns on calendar have min width) 1471 return 1; 1472 } else if (minWidth > innerWidth && avgColWidth > 28) { //= is default (staff columns on calendar have min width) 1473 return -1; 1474 } else { 1475 return 0; 1476 } 1477 } 1478 1479 _constructor.fitCalendarToScreen = function() { 1480 var isFitCalendar = UTIL.parseBool($.cookies.get('fit-calendar')); 1481 1482 if (isFitCalendar) { 1483 var msg = 'Resetting Calendar to Wide View...'; 1484 isFitCalendar = '0'; 1485 } else { 1486 var msg = 'Setting Calendar to Fit Screen...'; 1487 isFitCalendar = '1'; 1488 } 1489 1490 //var expireDate = new Date(); 1491 //expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1)); 1492 UTIL.setCookie('fit-calendar', isFitCalendar); //$.cookies.set('fit-calendar', isFitCalendar, { "expiresAt": expireDate });
1493 1494 GLO.Popup.Processing.open(msg, 'Reseting Calendar'); 1495 1496 setTimeout(function() { 1497 location.reload(); 1498 }, 100); 1499 } 1500 1501 _constructor.initAutoLoadForCalendar = function(jmodal, message) { 1502 var btnClose = '<span class="btnClose btnOk"> <a class="ignore-animate" onclick="$.modal.close()">Close</a> </span>'; 1503 var modalHeight = jmodal.height(); 1504 1505 var jh2 = jmodal.find('h2').css({ "margin-bottom": 0, "background-color": "rgb(0, 160, 220)" }); 1506 var h2Height = jh2.height(); 1507 1508 var jinfo = jmodal.find('#sfilter-instructions').html(message); 1509 var jh1 = jinfo.find('h1'); 1510 1511 jh2.text(jh1.text()); 1512 jh1.remove(); 1513 jmodal.find('#wiz5-SendText').replaceWith(btnClose); 1514 1515 var msgHeight = jmodal.find('#staff-filter-message').height(); 1516 var j = jmodal.find('#sFilter-list-container'); 1517 1518 if (modalHeight + msgHeight < innerHeight) { 1519 $.modal.update(modalHeight + msgHeight, null); 1520 } else { 1521 j.height(j.height() - msgHeight); 1522 } 1523 1524 var trs = j.find('tbody').find('tr'); 1525 1526 for (var i=0; i < trs.length; i++) { 1527 if (trs.eq(i).hasClass('has-appt')) { 1528 trs.eq(i).find('.sfilter-column-checkbox .staffCheck').prop('checked', true); 1529 } 1530 } 1531 1532 _sfilterInterval = setInterval(GLO.Staff.Filter.closeFilterOnRotateToLandscape); 1533 } 1534 1535 _constructor.closeFilterOnRotateToLandscape = function() { 1536 ++_intervalCounter; 1537 1538 if (GLO.Info.isLandscape()) { 1539 $.modal.close(); 1540 clearInterval(_sfilterInterval); 1541 } else if (_intervalCounter > 9) { 1542 clearInterval(_sfilterInterval); 1543 } 1544 } 1545 1546 function _initDisplayMessage(message) { 1547 if (message) { 1548 var jmodal = $('#simplemodal-container'); 1549 jmodal.find('#imgThrobber').css({ "margin-top": "40px", "margin-bottom": "0" }).before(message); 1550 jmodal.css({ "padding": 0 }).find('.simplemodal-data').css({ "padding": 0 }); 1551 1552 var w = parseInt(innerWidth * .9), h = 300; 1553 1554 if (w < 550) { 1555 h = 400; 1556 } 1557 1558 $.modal.update(h, w); 1559 } 1560 } 1561 1562 _constructor.filterStaff = function(isAllowInactive) { 1563 /* SUMMARY: 1564 1. filters staff portal to only these staff member(s) 1565 2. displays "Filter" tab, indicating that a filter is in effect - can click on filter to (view filter / update filter / remove filter) 1566 */ 1567 1568 var radioList = $('.staffCheck:checked'); 1569 var radioCount = radioList.size(); 1570 var staff_ids = ''; 1571 1572 if (radioCount === 0) { 1573 GLO.Popup.Warning(SA.Resource.PleaseSelectBox); 1574 return; 1575 } else { 1576 radioList.each(function() { 1577 staff_ids += $(this).parent().parent().attr('id').substr(7) + ','; 1578 }); 1579 } 1580 1581 if (GLO.Uri.url('inactive') == '1') { 1582 staff_ids = GLO.Uri.url('activestaff') + staff_ids; 1583 } 1584 1585 staff_ids = staff_ids.substr(0, staff_ids.length - 1); 1586 1587 if (_constructor.isReportPortal) { 1588 GLO.Report.setStaffFilter(staff_ids); 1589 $.modal.close(); 1590 1591 var dd = $('#staff-filter').val(''); 1592 1593 if (dd.find('option#staff-filter-change').length === 0) { 1594 dd.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>'); 1595 } 1596 1597 setTimeout(function() { 1598 var jsearch = $('.report-search-header:visible').find('.btnSearch > a'); 1599 1600 if (GLO.Report.portalName == 'payroll-days') { 1601 $('#payroll-report-date-period .btnAdd.selected > a').click(); //GLO.Report.Payroll.search(); 1602 return; 1603 } else if (jsearch.length === 0) { 1604 jsearch = $('#bd-page .fa-refresh'); //= Incorrect Payment report 1605 } 1606 1607 jsearch.click(); 1608 }, 100); 1609 } else if (GLO.MyAppts.isActivityView) { 1610 GLO.Uri.query('sfilter', staff_ids); 1611 $('#staffPortal-main').find('.appt-list-search:visible').find('.btnSearch > a:visible').click(); 1612 } else { 1613 var jbtn = $('#wiz5-SeeAppointments'); 1614 _constructor.gotoSchedule(staff_ids, null, jbtn, isAllowInactive); 1615 } 1616 } 1617 1618 _constructor.unDeleteStaff = function() { 1619 var radioList = $('.staffCheck:checked'); 1620 var radioCount = radioList.size(); 1621 var staffList = ''; 1622 1623 if (radioCount === 0) { 1624 GLO.Popup.Warning(SA.Resource.PleaseSelectBox2); 1625 return; 1626 } else { 1627 radioList.each(function() { 1628 staffList += '<li style="margin-left: 16px; text-indent: 0; letter-spacing: 1px; line-height: 140%; font-size: large;">' + $(this).closest('tr').find('td').eq(1).find('a').text() + '</li>'; 1629 }); 1630 1631 var msg = '<div id="msg-undo-delete-staff"><p>' + SA.Resource.ReActivateConfirm + '</p>'; 1632 msg += '<ol>' + staffList + '</ol> </div>'; 1633 1634 GLO.Popup.Confirm(msg, GLO.Staff.Filter.unDeleteStaffConfirmed); 1635 } 1636 } 1637 1638 _constructor.unDeleteStaffConfirmed = function(staffId) { 1639 var radioList = $('.staffCheck:checked'); 1640 var radioCount = radioList.size(); 1641 var staffIds = ''; 1642 1643 radioList.each(function() { 1644 staffIds += $(this).parent().parent().attr('id').substr(7) + ','; 1645 }); 1646
1647 var uri = GLO.Link.Object.Provider.Ajax + 'unDeleteStaff'; 1648 var btnSave = $('.wiz5-UndoDelete').parent(); 1649 1650 GLO.UI.Form.beginProcessing(btnSave); 1651 1652 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { staff_ids: staffIds } }) 1653 .success(function(data, textStatus, jqXHR) { 1654 var msg = '<div> <h1 class="friendly-msg4">Staff Successfully Un-Deleted</h1> <div class="friendly-msg4">' + SA.Resource.StaffReActivateSuccess + '</div> </div>'; 1655 new GLO.Popup.Info(msg, function() { location.reload(); }); 1656 }) 1657 .error(function(jqXHR, textStatus, errorThrown) { 1658 new GLO.Popup.Error('Unable to re-active these staff members at this time'); 1659 GLO.UI.Form.resetProcessing(); 1660 }); 1661 } 1662 1663 _constructor.removeFilter = function() { 1664 if ($('#report-main').length === 1) { 1665 $('#staffFilter').remove(); 1666 1667 var sdd = $('#staff-filter'); 1668 sdd.val(sdd.find('option:first').attr('value')); 1669 1670 GLO.Report.changeStaffFilter(); 1671 } else { 1672 var url = GLO.Link.Page.Provider.ClearFilter; 1673 1674 var dt = GLO.Uri.url('dt'); 1675 if (!UTIL.isEmpty(dt)) { url += '?dt=' + dt; } 1676 1677 document.location = url; 1678 } 1679 1680 $('#doc3').css({ "margin-top": "0" }); 1681 } 1682 1683 _constructor.viewDeleted = function(btn) { 1684 if (GLO.Info.displayPaidPackageRequired()) { return; } 1685 1686 var radioList = $('.staffCheck:checked'); 1687 var staff_ids = ''; 1688 1689 radioList.each(function() { 1690 staff_ids += $(this).parent().parent().attr('id').substr(7) + ','; 1691 }); 1692 1693 if (btn && btn.text) { 1694 GLO.Uri.gotoUriWithSpinner('provider/staffFilter?inactive=1&activestaff=' + staff_ids, btn, event, true); 1695 } else { 1696 document.location = '/provider/staffFilter?inactive=1&activestaff=' + staff_ids; 1697 } 1698 } 1699 1700 return _constructor; 1701})(); 1702 1703 1704GLO.Schedule = (function() { 1705 function _conSchedule() { } 1706 1707 _conSchedule.gotoMonthView = function(ev) { 1708 var calPage = _getCalendarPage(); 1709 _gotoView(ev, 'provider/' + calPage, false, 'vw=month'); 1710 } 1711 1712 _conSchedule.gotoWeekView = function(ev) { 1713 var calPage = _getCalendarPage(); 1714 _gotoView(ev, 'provider/' + calPage, false, 'vw=agendaWeek'); 1715 } 1716 1717 _conSchedule.gotoDayView = function(ev) { 1718 var calPage = _getCalendarPage(); 1719 _gotoView(ev, 'provider/' + calPage, false, 'vw=agendaDay'); 1720 } 1721 1722 _conSchedule.gotoListView = function(ev) { 1723 _gotoView(ev, 'provider/apptportal', true); 1724 } 1725 1726 _conSchedule.gotoReminderView = function(ev) { 1727 _gotoView(ev, 'provider/reminders', true); 1728 } 1729 1730 _conSchedule.gotoCalendarAdminView = function(ev) { 1731 _gotoView(ev, 'provider/calendar', true); 1732 } 1733 1734 function _getCalendarPage() { 1735 var sfilter = GLO.Uri.query('sfilter'); 1736 var calPage = 'calendar'; 1737 1738 if (GLO.Info.providerPackage !== 1) { 1739 if (parseInt(GLO.Info.providerPackage) > 200) { 1740 if (sfilter.indexOf(",") === -1 || sfilter.toLowerCase() === 'all') { 1741 calPage = 'CalendarOne' 1742 } 1743 } 1744 } 1745 1746 if (!UTIL.isEmpty(sfilter)) { calPage += '?sfilter=' + sfilter; } 1747 return calPage; 1748 } 1749 1750 function _gotoView(ev, url, mustGetStaffFilter, hash) { 1751 url = GLO.Link.WebsiteDomain + url; 1752 if (url.indexOf("?") === -1) { url += '?'; } else { url += '&'; } 1753 1754 if (mustGetStaffFilter) { 1755 var sfilter = GLO.Uri.query('sfilter'); 1756 1757 if (!UTIL.isEmpty(sfilter)) { url += 'sfilter=' + sfilter; } 1758 } 1759
1760 var sg = GLO.Uri.url('sfiltergroup'); 1761 if (!UTIL.isEmpty(sg)) { 1762 if (url.indexOf("?") === -1) { url += '?'; } else { url += '&'; } 1763 url += 'sfiltergroup=' + sg; 1764 } 1765 1766 url += '#'; 1767 if (!UTIL.isEmpty(hash)) { url += hash; } 1768 1769 var dt = GLO.Uri.url('dt'); 1770 if (!UTIL.isEmpty(dt)) { url += '&dt=' + dt; } 1771 1772 if (ev && ev.ctrlKey) { 1773 window.open(url); 1774 } else { 1775 document.location = url; 1776 } 1777 } 1778 1779 _conSchedule.lookupStaffNormalHours = function(dt, resourceId, ignoreAdjust) { 1780 var tmStart, tmEnd, id = null, isAdjust = false, day = dt.getDay(); 1781 1782 if (resourceId && GLO.resourceHours) { 1783 var rNormalHrArr = _getResourceNormalHoursArray(resourceId); 1784 1785 if (rNormalHrArr) { 1786 tmStart = rNormalHrArr[day][0]; 1787 tmEnd = rNormalHrArr[day][1]; 1788 } else if (GLO.Calendar !== undefined) { // = if is deleted staff there time isn't in the JS array. 1789 tmStart = GLO.Calendar.minTime; 1790 tmEnd = GLO.Calendar.maxTime; 1791 } 1792 } else { 1793 if (UTIL.isEmpty(resourceId)) { resourceId = UserPortal.getStaffFilterString(); } 1794 1795 tmStart = GLO.StaffWeekHours[day][0]; 1796 tmEnd = GLO.StaffWeekHours[day][1]; 1797 } 1798 1799 if (!ignoreAdjust) { 1800 var arr = UTIL.findObjectInArray(GLO.AdjustedHours, resourceId); 1801 1802 if (arr) { 1803 arr = arr["hrs"]; 1804 var sdt = (dt.getMonth() + 1) + '/' + dt.getDate() + '/' + dt.getFullYear(); 1805 1806 for (var i=0; i < arr.length; i++) { 1807 if (sdt === arr[i][1]) { 1808 if (arr[i][0]) { 1809 id = arr[i][0]; 1810 } 1811 1812 if (arr[i][2]) { 1813 tmStart = arr[i][2]; 1814 isAdjust = true; 1815 } 1816 1817 if (arr[i][3]) { 1818 tmEnd = arr[i][3]; 1819 isAdjust = true; 1820 } 1821 1822 break; 1823 } 1824 } 1825 } 1826 } 1827 1828 return [tmStart, tmEnd, id, isAdjust]; 1829 } 1830 1831 function _getResourceNormalHoursArray(resourceId) { 1832 var i = 0; 1833 var len = GLO.resourceHours.length; 1834 1835 for (; i < len; i++) { 1836 if (resourceId == GLO.resourceHours[i].id) { 1837 return GLO.resourceHours[i].normalHours; 1838 } 1839 } 1840 } 1841 1842 _conSchedule.Calendar = (function() { //functions shared by individual calendar + admin calendar. 1843 function _conCalendar() { } 1844 1845 _conCalendar.reloadCalendar = function(fn, ojProcessing) { 1846 $('#calTemporary').append($('#calCustom-buttons')); 1847 $('#calendar').fullCalendar('destroy'); 1848 $('#calendar').find('#cal-fixed-header').remove(); 1849 1850 if (fn) { 1851 fn(); 1852 } 1853 1854 if (ojProcessing && ojProcessing.close) { ojProcessing.close(); } 1855 UI.closeAllPopups(); 1856 1857 UserPortal.Calendar.createFrontDeskCalendar(); 1858 $("table.fc-agenda-days > thead > tr > th").click(GLO.Calendar.resourceHeaderClick); 1859 1860 if (GLO.Info.isMobile(true)) { 1861 setTimeout(function() { 1862 GLO.Mobile.setupHeader(GLO.Info.isMobile()); 1863 //$('#calendar').find('.fc-view-resourceDay thead:first').css({ "position": "relative" }); //.find('th.fc-agenda-gutter.fc-last').addClass('hideX'); 1864 $(window).scroll(); 1865 }, 500); 1866 } 1867 } 1868 1869 _conCalendar.getInactiveAttributes = function(calEv) { 1870 var inactiveCode = UTIL.cleanString(calEv.inactive_cd); 1871 var retval = ' inactive_cd="' + inactiveCode + '"'; 1872 1873 if (!UTIL.isEmpty(inactiveCode)) { 1874 if (inactiveCode == '1') {
1875 var staffName = $('#inactiveStaffBar .hello-bar-label a#inactive-staff' + calEv.staff_id).text(); 1876 retval += ' inactive_vc="' + staffName + '"'; 1877 } else if (inactiveCode == '2') { 1878 retval += ' inactive_vc="' + calEv.service_group_name_vc + '"'; 1879 } else if (inactiveCode == '4') { 1880 retval += ' inactive_vc="' + calEv.staff_vc + '"'; 1881 } else if (inactiveCode == '5') { 1882 retval += ' inactive_vc="Resource"'; 1883 } 1884 } 1885 1886 return retval; 1887 } 1888 1889 _conCalendar.getOtherAttributes = function(calEv) { 1890 var attributes = '', signin = calEv.signin_dt; 1891 1892 if (UTIL.isDate(signin)) { 1893 attributes += ' signin_dt="' + signin + '"'; 1894 } 1895 1896 if (calEv.phone_message_status_cd) { 1897 attributes += ' confirm_status_cd="' + calEv.phone_message_status_cd + '"'; 1898 } 1899 1900 if (!UTIL.isEmpty(calEv.multi_ticket_id)) { 1901 attributes += ' multi_ticket_id="' + calEv.multi_ticket_id + '"'; 1902 } 1903 1904 if (!UTIL.isEmpty(calEv.form_provider_id)) { 1905 attributes += ' form_provider_id="' + calEv.form_provider_id + '"'; 1906 } 1907 1908 return attributes; 1909 } 1910 1911 return _conCalendar; 1912 })(); 1913 1914 return _conSchedule; 1915})(); 1916 1917GLO.Communicate.Message = (function() { 1918 function _conMsg() { } 1919 1920 _conMsg.open = function() { 1921 var oj = $('.staffCheck:checked'); 1922 var ij = oj.size(); 1923 1924 if (ij === 0) { 1925 oj = $('#staffCheck'); 1926 1927 if (oj.size() === 1) { 1928 oj.prop('checked', true); 1929 ij = 1; 1930 } else { 1931 GLO.Popup.Warning(SA.Resource.PleaseSelectBox3); 1932 return; 1933 } 1934 } 1935 1936 if (ij > 0) { 1937 var phone = '', staffName = '', staffId = '', noPhoneCount = 0, noPhoneList = ''; 1938 1939 for (var i=0; i < ij; i++) { 1940 var tmp = oj.eq(i).parent().parent().find('td').eq(1); 1941 var phoneOrEmail = tmp.attr('phone'); 1942 1943 if (UTIL.isEmpty(phoneOrEmail) || UTIL.isEmpty(tmp.attr('mobileProvider'))) { 1944 phoneOrEmail = tmp.attr('email'); 1945 } 1946 1947 if (UTIL.isEmpty(phoneOrEmail)) { 1948 if (noPhoneCount !== 0) { noPhoneList += ', '; } 1949 noPhoneList += tmp.text(); 1950 1951 oj.eq(i).prop('checked', false); 1952 noPhoneCount++; 1953 } else { 1954 if (!UTIL.isEmpty(phone)) { 1955 phone += ','; 1956 staffName += ','; 1957 staffId += ','; 1958 } 1959 1960 phone += phoneOrEmail; 1961 staffName += tmp.text(); 1962 staffId += tmp.closest('tr').attr('id').replace('trStaff', ''); 1963 } 1964 } 1965 1966 var yesPhoneCount = ij - noPhoneCount; 1967 1968 if (yesPhoneCount > 0) { 1969 _open2(staffName, staffId, phone); 1970 } 1971 1972 if (noPhoneCount > 0) { 1973 var header = 'Staff Missing Phone / Email' 1974 var msgOptin = '<span class="narrow-text" style="display: inline;">(or have not opted in by selecting their phone company)</span>'; 1975 var msgBad = ' do not have a mobile phone number ' + msgOptin + ' and do not have an email'; 1976 var msgGood = 'This message will be sent to the other '; 1977 var words = SA.Resource.Members.toLowerCase(); 1978 var p1 = '<p style="margin-bottom: 16px; line-height: 1.4;">'; 1979 1980 if ((ij - noPhoneCount) === 1) { var words = SA.Resource.Member.toLowerCase(); } 1981 1982 if (noPhoneCount === 1 && ij > 1) { 1983 GLO.Popup.Warning.open(p1 + noPhoneList + msgBad + '</p>' + p1 + msgGood + yesPhoneCount + ' ' + SA.Resource.Staff.toLowerCase() + ' ' + words + '</p>', header); 1984 } else if (yesPhoneCount > 0) { 1985 noPhoneList = ' <span class="narrow-text" style="display: inline; font-weight: bold;">(' + noPhoneList + ')</span>'; 1986 var htmNoPhone = p1 + noPhoneCount + ' ' + SA.Resource.SelectedStaffMembers.toLowerCase() + noPhoneList + msgBad + '</p>'; 1987 var htmYesPhone = p1 + msgGood + yesPhoneCount + ' ' + SA.Resource.Staff.toLowerCase() + ' ' + words + '</p>'; 1988 1989 GLO.Popup.Warning.open(htmNoPhone + htmYesPhone, header); 1990 } else if (ij === 1) { 1991 var msgOptin = ' <span class="narrow-text" style="display: inline;">(and opt-in by selecting their phone company)</span>'; 1992 1993 var msg1 = p1 + SA.Resource.StaffMissingPhone + msgOptin + ' and does not have an email</p>'; 1994 var msg2 = p1 + SA.Resource.ToSendTextTo + ' ' + staffName + ' ' + SA.Resource.PleaseAddPhone + msgOptin + '</p>'; 1995 var msg3 = p1 + 'Or add an email address for the staff</p>'; 1996 var htm = '<div id="pop-warn-staff-missing-contact-info">' + msg1 + msg2 + msg3 + '</div>'; 1997 1998 GLO.Popup.Warning.open(htm, header); 1999 } else { 2000 var msg1 = p1 + SA.Resource.NoneOfSelectedStaff + ' ' + msgOptin + ' and has no email</p>'; 2001 var msg2 = p1 + SA.Resource.ToSendTextToStaff + '</p>'; 2002 var msg3 = p1 + 'To send an email please add an email for the staff</p>'; 2003 var htm = '<div id="pop-warn-staff-missing-contact-info">' + msg1 + msg2 + msg3 + '</div>'; 2004 2005 GLO.Popup.Warning.open(htm, header); 2006 } 2007 2008 ij = ij - noPhoneCount; 2009 } 2010 } 2011 } 2012 2013 function _open2(names, ids, phones) { 2014 var jpop = $('#pop-sendtext'); 2015 var ojpop = new GLO.Popup.Custom(jpop); 2016 jpop = ojpop.getPopup(); //.addClass('no-persist'); 2017 2018 if (false && GLO.Info.isMobile(false)) { 2019 jpop.find('.pop-buttons-parent').prepend('<a id="send-sms" href="sms:+' + phones + '">SMS</a>'); 2020 jpop.find('#send-sms').click(); 2021 ojpop.close(); 2022 } else { 2023 jpop.find('.pop-buttons-parent').remove(); 2024 2025 jpop.find('#TextMsg-Person').text(names); 2026 jpop.find('#TextMsg-PersonId').val(ids); 2027 jpop.find('#TextMsg-Phone').text(phones); 2028 } 2029 } 2030 2031 _conMsg.sendText = function() { 2032 var url = GLO.Link.WebsiteDomain + 'message/send'; 2033 2034 var jpop = $('#pop-sendtext:visible'); 2035 var jsave = jpop.find('.btnSave'); 2036 GLO.UI.Form.beginProcessing(jsave); 2037 2038 var msg = jpop.find('textarea').val(); 2039 var staffIds = jpop.find('#TextMsg-PersonId').val(); 2040
2041 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { msgFormat: 3, message: msg, staff_ids: staffIds } }) 2042 .success(function(data, textStatus, jqXHR) { 2043 _processSendMessageResponse(jpop, jsave, data); 2044 }) 2045 .error(function(jqXHR, textStatus, errorThrown) { 2046 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2047 }); 2048 2049 $.modal.close(); 2050 } 2051 2052 _conMsg.openGeneric = function(label, msg, sid, sname, isSaveAppt, mtype, action) { 2053 var htmRadio = '', style = 'width: 460px; text-align: center;'; 2054 2055 if (GLO.Data.provider.staff_text_alert_format_cd > 19 && GLO.Data.provider.staff_text_alert_format_cd < 40) { 2056 var inAppChecked = '', textChecked = ''; 2057 2058 if (GLO.Data.provider.staff_text_alert_format_cd == 20) { 2059 inAppChecked = ' checked="checked"'; 2060 } else if (GLO.Data.provider.staff_text_alert_format_cd == 30) { 2061 textChecked = ' checked="checked"'; 2062 } 2063 2064 var rdoInApp = '<input type="radio" id="Send_InApp_Format_cd" name="Staff_Text_Alert_cd" value="5"' + inAppChecked + '/> <label for="Send_InApp_Format_cd">In-App Notification</label>'; 2065 var rdoText = '<input type="radio" id="Send_Text_Format_cd" name="Staff_Text_Alert_cd" value="3"' + textChecked + '/> <label for="Send_Text_Format_cd">Text Message</label>'; 2066 2067 var inApp = '<span id="generic-format-inapp" class="generic-format">' + rdoInApp + '</span>'; 2068 var text = '<span id="generic-format-text" class="generic-format">' + rdoText + '</span>'; 2069 var htmRadio = '<div id="generic-message-format">' + inApp + text + '</div>'; 2070 } 2071 2072 if ($(window).width() < 480) { 2073 style = 'width: 310px; text-align: center;'; 2074 } 2075 2076 var msg = $('<div staff_id="' + sid + '" message_type_cd="' + UTIL.cleanString(mtype) + '" id="pop-send-generic-text" style="' + style + '">' 2077 + htmRadio 2078 + '<input type="hidden" id="Text_Staff_id" value="' + sname + '"/>' 2079 + '<h2 style="padding: 6px 0; letter-spacing: 1px;">' + label + '</h2>' 2080 + '<textarea id="generic-message" rows="4" maxlength="140">' + msg + '</textarea>' 2081 + '</div>'); 2082 2083 var fnSave = function() { GLO.Communicate.Message.sendTextGeneric(isSaveAppt, action); }; 2084 2085 var ojpop = new GLO.Popup.Custom(msg, fnSave); 2086 jpop = ojpop.getPopup().addClass('no-persist'); 2087 2088 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 2089 jbtns.find('.btnSave').find('a').text('Send'); 2090 2091 _checkStaffAlertSetting(sname, sid); 2092 } 2093 function _checkStaffAlertSetting(sname, sid) { 2094 if (!UTIL.isNumber(sid)) { 2095 return; 2096 } 2097 2098 var url = GLO.Link.WebsiteDomain + 'wizard2/GetStaffConfigData?staff=' + sid; 2099 var jpop = $('#pop-send-generic-text').closest('.glopop'); 2100 2101 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 2102 .success(function(data, textStatus, jqXHR) { 2103 var jdata = $(data); 2104 var hasPushEnabled = UTIL.parseBool(jdata.attr('push_enabled_fl')); 2105 2106 if (jdata.hasClass('success')) { 2107 if (!UTIL.Validate.phone(jdata.attr('phone'))) { 2108 var msg = '<p style="margin: 8px 0; letter-spacing: 1px; text-align: center;">' + sname + ' profile has no phone number</p>'; 2109 jpop.find('#generic-message-format').html(msg); 2110 return; 2111 } 2112 2113 if (GLO.Data.provider.staff_text_alert_format_cd == 10) { 2114 jpop.find('#generic-format-text').remove(); 2115 } else if (UTIL.parseBool(jdata.attr('text_on_checkin_fl'))) { 2116 jpop.find('#Send_Text_Format_cd').prop('checked', true); 2117 } 2118 2119 if (!hasPushEnabled) { 2120 var link = '<a onclick="GLO.Uri.gotoUri2(\'help#tab=message&id=faq-message-staff-in-app-notifications\')">In-App Notifications Not Enabled</a>'; 2121 var htmText = '<div style="margin: 8px 0; letter-spacing: 1px;">' + link + '</div>'; 2122 2123 jpop.find('#generic-format-inapp').remove(); 2124 jpop.find('#generic-message-format').after(htmText); 2125 } else if (UTIL.parseBool(jdata.attr('inapp_on_checkin_fl'))) { 2126 jpop.find('#Send_InApp_Format_cd').prop('checked', true); 2127 } 2128 } 2129 }) 2130 .error(function(jqXHR, textStatus, errorThrown) { 2131 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2132 }); 2133 }
2134 _conMsg.sendTextGeneric = function(isSaveAppt, action) { 2135 var j = $('#pop-send-generic-text'); 2136 var msg = j.find('#generic-message').val(); 2137 var msgType = j.attr('message_type_cd'); 2138 2139 var staffId = j.attr('staff_id'); 2140 var staffName = j.find('#Text_Staff_id').val(); 2141 var staffTextAlertFormat = UTIL.coalesceInt(j.find('#Staff_Text_Alert_cd').val(), 3); 2142 2143 var url = GLO.Link.WebsiteDomain + 'message/send'; 2144 var jpop = j.closest('.glopop'); 2145 var jsave = jpop.find('.btnSave'); 2146 2147 GLO.UI.Form.beginProcessing(jsave); 2148 2149 if (isSaveAppt) { 2150 UserPortal.getEditAppt().find('#ba-SaveEdit > a').click(); 2151 } 2152 2153 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "msgFormat": staffTextAlertFormat, "mtype": msgType, "message": msg, "staff_ids": staffId, "label": action } }) 2154 .success(function(data, textStatus, jqXHR) { 2155 _processSendMessageResponse(jpop, jsave, data, staffName); 2156 }) 2157 .error(function(jqXHR, textStatus, errorThrown) { 2158 GLO.Popup.close($('#pop-send-generic-text').closest('.glopop')); 2159 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2160 }); 2161 } 2162 2163 function _processSendMessageResponse(jpop, jsave, data, staffNames) { 2164 var msg = '', jdata = $(data); //GLO.UI.Form.resetProcessing(); 2165 var isSuccess = false, header = 'Message Not Sent'; 2166 var isWarning = jdata.hasClass('warning') || jdata.find('li[warning_cd]').length; 2167 2168 if (jdata.hasClass('success')) { 2169 isSuccess = true; 2170 header = 'Message Sent'; 2171 2172 if (!UTIL.isEmpty(staffNames)) { 2173 msg = '<p>' + staffNames + ' Notified</p>'; 2174 } 2175 } 2176 2177 if (jdata.find('li[error_cd]').length || isWarning) { 2178 var htm = '<div id="pop-success-send-custom-message">' + msg + data + '</div>'; 2179 var jpop = GLO.Popup.Custom.openSimple(htm, header); 2180 2181 GLO.Popup.Custom.singleButton(jpop, 'Close'); 2182 //GLO.Popup.Error.open(msg + jdata.outerHTML(), header); 2183 //GLO.Popup.Warning.open(msg + jdata.outerHTML(), header); 2184 } else if (isWarning && jdata.find('#bulk-deliverability-score').length) { 2185 var ojpop = new GLO.Popup.Custom(jdata); 2186 var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score'); 2187 2188 GLO.Popup.Custom.singleButton(jpop, 'Close'); 2189 ojpop.realign(); ojpop.realign(); 2190 2191 GLO.UI.Form.resetProcessing(jsave); 2192 return; 2193 } else if (isSuccess) { 2194 GLO.Popup.Success.open(msg, header); 2195 } else { 2196 var htm = '<div id="pop-warning-send-custom-message"><p>Unable to send message</p><p>Please try again later</p></div>'; 2197 GLO.Popup.Warning.open(htm, header); 2198 GLO.UI.Form.resetProcessing(jsave); 2199 return; 2200 } 2201 2202 GLO.Popup.closeIfExist($('#pop-send-generic-text').closest('.glopop')); 2203 GLO.Popup.closeIfExist($('#pop-sendtext').closest('.glopop')); 2204 } 2205 2206 _conMsg.view = function(msgId, isText) { //= used for viewing reminders from Reminder View 2207 var url = GLO.Link.WebsiteDomain + 'message/' + msgId + '?ispartial=1&dt=' + UTIL.getDateString(); 2208 2209 GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') ); 2210 2211 GLO.Popup.Processing.open('Opening Reminder Sent To Client...'); 2212 viewTemplate(url); 2213 } 2214 2215 function viewTemplate(uri, isText) { 2216 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "110px auto"}); 2217 var pop = $('#pop-temp'); 2218 2219 pop.html(throbber).load(uri, function() { 2220 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 2221 GLO.Popup.closeIfExist($('.pop-processing').closest('.glopop')); 2222 2223 var jModal = $('#simplemodal-container').addClass('view-message'); 2224 jModal.draggable({ "handle": "#msg-header" }).find('#msg-header').css({ "cursor": "move", "min-width": "640px" }); 2225 2226 jModal.css({ "height": "auto", "width": "auto", "padding": "0" }); 2227 jModal.find('.simplemodal-data').css({ "padding": "0" }); 2228
2229 jModal.find('.sdiff-appt, #view-appt-link').css({ "margin": "auto" }); 2230 jModal.find('#msg-header-left').css({ "text-align": "left" }); 2231 2232 jModal.find('#body_style.text-reminder').css({ "color": "#222" }); 2233 jModal.find('a').css({ "text-decoration": "none" }); 2234 var mh = jModal.height() + 50, mw = (jModal.width() + 15); 2235 2236 if (innerWidth < mw) { 2237 mw = parseInt(innerWidth * .99); 2238 } 2239 2240 if (mh < 240) { 2241 mh = 240; 2242 } else if (mh > innerHeight && !GLO.Info.isMobile()) { 2243 mh = parseInt(innerHeight * .9); 2244 } 2245 2246 $.modal.update(mh, mw); 2247 2248 jModal.find('.simplemodal-wrap').addClass('scrollable-for-mac').css({ "overflow": "auto" }); 2249 $(window).trigger('resize.simplemodal'); 2250 2251 jModal.find('#msg-header').css({ "border-top-left-radius": "5px" }); 2252 }); 2253 2254 pop.modal(); 2255 $.modal.update(300, 300); 2256 } 2257 2258 return _conMsg; 2259})(); 2260 2261GLO.Hours = (function() { //?? Should this be WIZ.Hours and go in wizard.js ?? 2262 var hourChangeInProgress = false; 2263 function _constructor(name) { } 2264 _constructor.loading = true; 2265 2266 _constructor.openViewAdjustedTimes = function(btn) { 2267 var htm = '<div id="pop-time-adjust-summary">' + $('#time-adjust-summary-container').html() + '</div>'; 2268 var jpop = GLO.Popup.Custom.openSimple(htm, 'Open / Close Time Adjusted'); 2269 var jtbl = jpop.find('#time-adjust-summary-table'); 2270 2271 UI.initTableSorter(jtbl); 2272 GLO.Popup.Custom.singleButton(jpop, 'Close'); 2273 } 2274 _constructor.openEditAdjustedTime = function(btn) { 2275 var tr = $(btn).closest('tr'); 2276 var staffId = tr.closest('table').attr('staff'); 2277 var staffName = $.trim($('#wiz5-popupHours #wiz5-staffName').text()); 2278 2279 var day = tr.attr('day'); 2280 var tmOpen = $.trim(tr.find('.time-adjust-open').text()).replace('normal', ''); 2281 var tmClose = $.trim(tr.find('.time-adjust-close').text()).replace('normal', ''); 2282 2283 _constructor.openEditAdjustedTimePopup(staffId, staffName, day, tmOpen, tmClose); 2284 } 2285 _constructor.openEditAdjustedTimePopup = function(staffId, staffName, day, tmOpen, tmClose) { 2286 var openEdit = '<input type="text" id="Adjust_Open_tm" name="Adjust_Open_tm" class="is-time-picker" value="' + tmOpen + '" pattern="[0-9]*">'; 2287 var closeEdit = '<input type="text" id="Adjust_Close_tm" name="Adjust_Close_tm" class="is-time-picker" value="' + tmClose + '" pattern="[0-9]*">'; 2288 2289 var labelOpen = '<label for="Adjust_Open_tm">Open</label>'; 2290 var labelClose = '<label for="Adjust_Close_tm">Close</label>'; 2291 2292 var htmOpen = '<div class="adjust-time-edit-row">' + labelOpen + openEdit + '</div>'; 2293 var htmClose = '<div class="adjust-time-edit-row">' + labelClose + closeEdit + '</div>'; 2294 2295 var header = staffName + ' ' + new Date(day).toGloDateString(true, true); //Open/Close Time Adjusted on 2296 var htm = '<div id="pop-edit-adjusted-day" staff="' + staffId + '" day="' + day + '">' + htmOpen + htmClose + '</div>'; 2297 var jpop = GLO.Popup.Custom.openSimple(htm, header, GLO.Hours.saveAdjustedTime); 2298 2299 var btnReset = '<span class="btnDelete btnReset" style="margin: 0;"><a onclick="GLO.Hours.resetAdjustedTime()" style="position: absolute; left: 6px;">Reset</a></span>'; 2300 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" }); 2301 2302 jbtns.find('.btnCancel').css({ "float": "none", "position": "relative", "display": "inline-block", "width": "80px", "margin": 0, "padding": 0, "font-weight": "bold" }); 2303 jbtns.find('.btnSave').css({ "width": "80px", "margin": 0 }).after(btnReset); 2304 2305 UI.timeMask('#Adjust_Open_tm'); 2306 UI.timeMask('#Adjust_Close_tm', '11:59 am'); 2307 2308 UI.setTimeMaskValue(jpop.find('#Adjust_Open_tm'), tmOpen); 2309 UI.setTimeMaskValue(jpop.find('#Adjust_Close_tm'), tmClose); 2310 } 2311 _constructor.saveAdjustedTime = function() { 2312 var jpop = $('#pop-edit-adjusted-day'); 2313 var staffId = jpop.attr('staff'); 2314 var day = jpop.attr('day'); 2315 var open = UI.getTimeMaskValue(jpop.find('#Adjust_Open_tm')); 2316 var close = UI.getTimeMaskValue(jpop.find('#Adjust_Close_tm')); 2317 2318 var url = GLO.Link.Object.AppointmentAjax + 'AdjustDaysNormalHoursPopup?day=' + day + '&staff=' + staffId + '&open=' + open + '&close=' + close; 2319 jpop = jpop.closest('.glopop'); 2320 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 2321
2322 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 2323 .success(function(data, textStatus, jqXHR) { 2324 GLO.UI.Form.resetProcessing(); 2325 2326 if ($(data).hasClass('warning') || $(data).hasClass('error')) { 2327 GLO.Popup.Warning.open(data, 'Unable to Change Open / Close'); 2328 return; 2329 } 2330 2331 GLO.Popup.closeIfExist(jpop); 2332 GLO.Popup.closeIfExist( $('#pop-time-adjust-summary').closest('.glopop') ); 2333 GLO.Popup.closeIfExist( $('#wiz5-popupHours').closest('.glopop') ); 2334 2335 if (GLO.Calendar !== undefined) { 2336 GLO.Popup.Processing.open('Loading New Open / Close Time...', 'Day Adjusted'); 2337 2338 setTimeout(function() { 2339 location.reload(); 2340 }, 400); 2341 } else if ($('#wiz5-popupHours').length) { 2342 $.modal.close(); 2343 } 2344 }) 2345 .error(function(jqXHR, textStatus, errorThrown) { 2346 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2347 }); 2348 } 2349 _constructor.resetAdjustedTime = function(btn) { 2350 var jpop = $('#pop-edit-adjusted-day'); 2351 var staffId = jpop.attr('staff'); 2352 var day = jpop.attr('day'); 2353 2354 var url = GLO.Link.Object.AppointmentAjax + 'AdjustDaysNormalHoursReset?day=' + day + '&staff=' + staffId; 2355 jpop = jpop.closest('.glopop'); 2356 GLO.UI.Form.beginProcessing(jpop.find('.btnReset')); 2357 2358 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 2359 .success(function(data, textStatus, jqXHR) { 2360 GLO.UI.Form.resetProcessing(); 2361 2362 if ($(data).hasClass('warning') || $(data).hasClass('error')) { 2363 GLO.Popup.Warning.open(data, 'Unable to Change Open / Close'); 2364 return; 2365 } 2366 2367 GLO.Popup.closeIfExist(jpop); 2368 GLO.Popup.closeIfExist( $('#pop-time-adjust-summary').closest('.glopop') ); 2369 GLO.Popup.closeIfExist( $('#wiz5-popupHours').closest('.glopop') ); 2370 2371 if (GLO.Calendar !== undefined) { 2372 GLO.Popup.Processing.open('Open / Close Time Reset to Default, Loading Changes ...', 'Open / Close Time Reset'); 2373 2374 setTimeout(function() { 2375 location.reload(); 2376 }, 400); 2377 } else if ($('#wiz5-popupHours').length) { 2378 $.modal.close(); 2379 } 2380 }) 2381 .error(function(jqXHR, textStatus, errorThrown) { 2382 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2383 }); 2384 } 2385 2386 _constructor.isClosed = function(checkbox, isInit) { 2387 hourChangeInProgress = true; 2388 if (_constructor.loading) { isInit = true; } 2389 2390 var jClosed = $(checkbox); 2391 var jHide = jClosed.parent().parent().find('>td.HideOnCalendar'); 2392 var timeParent = jClosed.parent().parent().find('.wizHoursTime'); 2393 2394 var row = jClosed.attr('id'); 2395 row = row.substr(row.length-1); 2396 2397 if (jClosed.is(':checked')) { 2398 jHide.removeClass('hide'); 2399 if (!isInit) { jHide.find('>input').prop('checked', true); } 2400 timeParent.css('text-decoration', 'line-through'); 2401 timeParent.css('opacity', '.5'); 2402 timeParent.closest('tr').addClass('row-off'); 2403 2404 $('#Start_tm' + row).attr('title', '').blur(); 2405 //$('#Start_tm' + row + 'b').attr('title', '').blur(); 2406 $('#End_tm' + row).attr('title', '').blur(); 2407 //$('#End_tm' + row + 'b').attr('title', '').blur(); 2408 } else { 2409 jHide.addClass('hide'); 2410 jHide.find('>input').removeAttr('checked'); 2411 timeParent.css('text-decoration', ''); 2412 timeParent.css('opacity', ''); 2413 timeParent.closest('tr').removeClass('row-off'); 2414 2415 $('#Start_tm' + row).blur(); 2416 //$('#Start_tm' + row + 'b').blur(); 2417 $('#End_tm' + row).blur(); 2418 //$('#End_tm' + row + 'b').blur(); 2419 } 2420 2421 hourChangeInProgress = false; 2422 } 2423 2424 _constructor.init = function() { 2425 var tm, jContainer = $('#wizHours'); 2426 2427 $.each(jContainer.find("input.bizClosed"), function() { 2428 GLO.Hours.isClosed(this, true); 2429 }); 2430 2431 for (var i=1; i < 8; i++) { 2432 if ($('#Closed_fl' + i).is(':checked')) { 2433 _constructor.isClosed($('#Closed_fl' + i)[0]); 2434 } 2435 2436 UI.timeMask('#Start_tm' + i, '5:00 am'); 2437 UI.timeMask('#End_tm' + i, '11:59 am'); 2438 } 2439 2440 UI.timeMask('#CalendarMinTime', '4:00 am'); 2441 UI.timeMask('#CalendarMaxTime', '11:59 am'); 2442 2443 if ($.cookies.get('pstatus') == 2) { 2444 var jHolidayContainer = $('#wizHolidays'); 2445 jHolidayContainer.find('#New_Years_fl').prop('checked', true); 2446 jHolidayContainer.find('#Thanksgiving_fl').prop('checked', true); 2447 jHolidayContainer.find('#Christmas_fl').prop('checked', true); 2448 2449 var d = new Date(); 2450 var isDaylightSavings = false; 2451 var gmt = -d.getTimezoneOffset() / 60; 2452 if (isDaylightSavings) { gmt -= 1; } 2453 2454 var optList = $('#Time_Zone_cd option'); 2455 var optLen = optList.length; 2456 2457 for (var i=0; i < optLen; i++) { 2458 if (optList.eq(i).attr('offset') == gmt) { 2459 $('#Time_Zone_cd').val(optList.eq(i).attr('value')); 2460 } 2461 } 2462 2463 if (GLO.Info.isIPhone) { 2464 jContainer.find('.open-time:not(#Start_tm1)').val('09:00:00'); 2465 jContainer.find('.close-time:not(#End_tm1)').val('18:00:00'); 2466 } 2467 } 2468 } 2469 2470 _constructor.initAdjustedDays = function(staffId) { 2471 var jwiz = $('#wizNormalHours'); 2472 var cnt = UTIL.coalesceInt(jwiz.attr('startOrEndTimeAdjustCount'), 0); 2473 var firstDay = jwiz.attr('firstDayAdjusted'); 2474 2475 if (cnt > 0) { 2476 //var sid = UTIL.coalesceInt($('#wiz3-form').attr('edit_staff_id'), GLO.Info.StaffId); 2477 2478 //var url1 = 'provider/CalendarOne?sfilter=' + staffId + '#vw=agendaDay&dt=' + firstDay; 2479 //var a1 = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url1 + '\', this, event, true)"> ' + UTIL.pluralLabel(cnt, 'Day') + '</a>'; 2480 //var a2 = '<a id="wiz3-adjusted-days-faq" onclick="GLO.Uri.gotoUriWithSpinner(\'' + url2 + '\', this, event, true)">(different than listed below)</a>'; 2481 2482 var btn1 = '<span class="btnAdd">
2482<a onclick="GLO.Hours.openViewAdjustedTimes()">View ' + UTIL.pluralLabel(cnt, 'Day') + '</a></span>'; 2483 var note1 = '<span class="narrow-text" style="padding-left: 4px;"><i>with custom hours</i> different than listed below</span>' 2484 2485 var helpIcon = '<b class="question-icon" onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=calendar&id=calendar-change-days-work-time\', this, event, true)">?</b>'; 2486 var htm = '<p id="wiz3-adjusted-days">' + btn1 + note1 + helpIcon + '</p>'; 2487 jwiz.before(htm); 2488 } 2489 } 2490 2491 _constructor.hourChange = function(element) { 2492 if (hourChangeInProgress) { return; } //necessary to avoid infinite recursion. 2493 hourChangeInProgress = true; 2494 2495 var jElement = $(element); 2496 2497 if (!UTIL.isEmpty(jElement.val())) { 2498 jElement.parent().css('text-decoration', ''); 2499 var checkbox = jElement.parent().parent().find('input.bizClosed'); 2500 checkbox.removeAttr('checked'); 2501 _constructor.isClosed(checkbox[0], false); 2502 } 2503 2504 hourChangeInProgress = false; 2505 } 2506 2507 return _constructor; 2508})(); 2509 2510var ClientProfile = (function() { 2511 function _constructor(name) { } 2512 var _unlockPassword = null, _unlockTimeout = null; 2513 2514 _constructor.cancel = function() { history.back(1); } 2515 2516 _constructor.clearUnlockPassword = function() { 2517 clearTimeout(_unlockTimeout); 2518 _unlockPassword = null; 2519 //$('form#client-form').find('#Unlock_Password_vc').val(''); 2520 } 2521 _constructor.setUnlockPassword = function(pass, timeout) { 2522 _unlockPassword = pass; 2523 clearTimeout(_unlockTimeout); 2524 timeout = UTIL.coalesceInt(timeout, 5000); 2525 2526 _unlockTimeout = setTimeout(function() { 2527 _unlockPassword = null; 2528 }, timeout); 2529 } 2530 _constructor.getUnlockPassword = function() { 2531 return _unlockPassword; 2532 } 2533 2534 _constructor.changeBalance = function(el) { 2535 if (el.value != '') { 2536 //$('#trBalance_Change_Reason').removeClass('hide'); 2537 //$('#Balance_Change_Reason_vc').focus(); 2538 } 2539 } 2540 2541 _constructor.save = function() { 2542 WIZ.save(); 2543 } 2544 2545 _constructor.addBackToWailList = function() { 2546 if (innerWidth > 599) { 2547 var jmodal = $('#simplemodal-container'); 2548 jmodal.find('#client-purchased-products-link').remove(); 2549 2550 var htm = '<a id="linkbackToWaitList" class="back-to-appointment" onclick="GLO.WaitList.reopen()">< Back To Wait List</a>'; 2551 jmodal.find('h2#clientName').prepend(htm); 2552 } 2553 } 2554 2555 _constructor.goto = function(Client_id, IsPartial, clientName, fnAfterOpen) { 2556 var url = GLO.Link.Page.Provider.ClientProfile + '?cid=' + Client_id; 2557 2558 if (UTIL.isEmpty(clientName) && this && event) { 2559 clientName = event.target.innerText; 2560 } 2561 2562 if (GLO.Data.Staff.hideClientContact) { 2563 url = GLO.Link.Page.Provider.Home + 'NoteHistory?clientId=' + Client_id; 2564 } 2565 2566 if (IsPartial) { 2567 if ($('#simplemodal-container').is(':visible')) { 2568 _constructor.open(url, true, clientName, fnAfterOpen); 2569 } else { 2570 _constructor.open(url, false, clientName, fnAfterOpen); 2571 } 2572 } else { 2573 document.location = url; 2574 } 2575 } 2576 2577 _constructor.openAddCard = function() { 2578 var jpop = $('#pop-member-pay-summary').closest('.glopop'); 2579 GLO.Popup.close(jpop); 2580 $('#client-form #btnAddCardOnFile').find('a').click(); 2581 } 2582 2583 _constructor.switchPopup = function(cid, cparentid, cname) { 2584 //$.modal.close(); 2585 var loadPage = GLO.Link.Page.Provider.ClientProfile + '?cid=' + cid + '&cparentid=' + UTIL.cleanString(cparentid); 2586 _constructor.open(loadPage, true); 2587 } 2588 2589 _constructor.isFullPageProfile = function() { 2590 var currUrl = document.location.pathname.toLowerCase(); 2591 2592 var openAsFullPage1 = (currUrl.indexOf("/provider/clientprofile") !== -1 || currUrl.indexOf("/provider/profile") !== -1 || currUrl.indexOf("/provider/appointment/history/client/") !== -1); 2593 var openAsFullPage2 = ($('.shadow-content0 #sale-keyboard:visible').length > 0 || currUrl.indexOf("/provider/apptsummary") !== -1); 2594 2595 if (!openAsFullPage1) { 2596 openAsFullPage1 = (currUrl.indexOf("/schedule/recur") !== -1 || currUrl.indexOf("/provider/notehistory") !== -1); 2597 } 2598 2599 return (openAsFullPage1 || openAsFullPage2); 2600 } 2601 2602 _constructor.open = function(url, modalAlreadyOpen, clientName, fnAfterOpen) { //= ClientProfile.open() 2603 if (_constructor.isFullPageProfile()) { 2604 if (GLO.Info.isMobile(true)) { GLO.UI.animate(10); } 2605 document.location = url; 2606 } else { 2607 url += '&IsPartial=1&dt=' + UTIL.getDateString(); 2608 2609 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}); 2610 var pop = $('#pop-temp'); 2611 2612 if (modalAlreadyOpen) { 2613 $('#simplemodal-container .simplemodal-wrap #pop-temp').html(throbber); 2614 _addCloseIcon(); 2615 } 2616 2617 _constructor.openCompleted(url, modalAlreadyOpen, clientName, null, fnAfterOpen); 2618 } 2619 } 2620 2621 function _addCloseIcon() { //if open client profile from wait list popup + screen is < 990 -> no close button/icon 2622 var jmodal = $('#simplemodal-container'); 2623 2624 if (jmodal.find('.simplemodal-close').length === 0) { 2625 var icon = '<a class="modalCloseImg sa-sprite simplemodal-close" style="right: -2px;"></a>'; 2626 jmodal.prepend(icon); 2627 } 2628 } 2629 2630 _constructor.openCompleted = function(url, modalAlreadyOpen, clientName, smid, fnPostProcess) { 2631 if (UTIL.isEmpty(fnPostProcess)) { 2632 GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop')); 2633 } 2634 2635 var htm = '<div id="pop-processing-open-client-profile">' + SA.Resource.LookingUp + ' ' + UTIL.cleanString(clientName) + '...' + '</div>'; 2636 var ojProcessing = GLO.Popup.Processing.open(htm, 'Opening Client Profile'); 2637
2638 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 2639 .success(function(data, textStatus, jqXHR) { 2640 if (ojProcessing) { 2641 ojProcessing.close(); 2642 } else { 2643 var jpop = $('#pop-help-cell-summary').closest('.glopop'); 2644 GLO.Popup.closeIfExist(jpop); 2645 2646 $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove(); 2647 } 2648 2649 _loadClientProfile(modalAlreadyOpen, smid, data); 2650 2651 if (fnPostProcess) { fnPostProcess(smid); } 2652 }) 2653 .error(function(jqXHR, textStatus, errorThrown) { 2654 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2655 }); 2656 } 2657 2658 function _openDirections(modalAlreadyOpen, smid, clientId, clientName, url) { 2659 var h1 = '<h1 class="friendly-msg2">' + SA.Resource.Address + ' ' + SA.Resource.Lookup + '</h1>'; 2660 var msg = '<div>' + h1 + '<div class="friendly-msg2">' + SA.Resource.LookingUp + ' ' + UTIL.cleanString(clientName) + ' ' + SA.Resource.Address + '...</div> </div>'; 2661 var ojProcessing = new GLO.Popup.Processing(msg); 2662 2663 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 2664 .success(function(data, textStatus, jqXHR) { 2665 if (ojProcessing) { ojProcessing.close(); } 2666 2667 if (_lookupDirections(data)) { 2668 $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove(); 2669 } else { 2670 _loadClientProfile(modalAlreadyOpen, smid, data); 2671 ClientProfile.openProfileOnlyCompleted(smid); 2672 2673 var h1 = '<h1 class="friendly-msg2">Address Missing</h1>'; 2674 var msg = '<div>' + h1 + '<div class="friendly-msg2">' + clientName + ' has no Street Address<br/><br/>Please Enter a Street Address</div> </div>'; 2675 var fnOk = function() { $('#displayProfile-Client Street_vc').focus(); } 2676 new GLO.Popup.Warning(msg, fnOk); 2677 } 2678 }) 2679 .error(function(jqXHR, textStatus, errorThrown) { 2680 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 2681 }); 2682 } 2683 2684 function _lookupDirections(data) { 2685 var jd = $(data); 2686 var street = encodeURIComponent($.trim(jd.find('#Street_vc').val())); 2687 2688 if (UTIL.isEmpty(street)) { 2689 return false; 2690 } 2691 2692 var city = encodeURIComponent($.trim(UTIL.coalesce(jd.find('#City_vc').val(), GLO.Data.provider.city)).replace(' ', ' ').replace(' ', '+')); 2693 var state = encodeURIComponent($.trim(UTIL.coalesce(jd.find('#State_cc').val(), GLO.Data.provider.state))); 2694 var zip = encodeURIComponent($.trim(jd.find('#Zip_vc').val()).replace(' ', ' ').replace(' ', '+')); 2695 2696 street += '+' + city + ',' + state; 2697 if (UTIL.isEmpty(zip)) { street += '+' + zip; } 2698 2699 var url = 'https://maps.google.com?saddr=My+Location&daddr=' + street; //var url = 'https://maps.google.com/?q=' + addressLongLat; 2700 SA.App.openLinkInBrowser(url, true); //window.open(url, '_system'); 2701 2702 return true; 2703 } 2704 2705 function _loadClientProfile(modalAlreadyOpen, smid, data) { 2706 if (ClientProfile.isFullPageProfile()) { 2707 UI.closeAllPopups(); 2708 var jcontainer = $('.shadow-content0').html(data); 2709 } else if (modalAlreadyOpen) { 2710 var throbber = $('.loading-client-quick-view').remove(); 2711 var jcontainer = $('#simplemodal-container'); 2712 2713 if ($('.shadow-content0 .client-name-header').length > 0) { 2714 if (jcontainer.length > 0) { $.modal.close(); } 2715 2716 jcontainer = $('.shadow-content0').html(data); 2717 } else if (jcontainer.length === 1) { 2718 jcontainer.find('> .simplemodal-wrap').html(data); 2719 } else if (throbber.length === 1) { 2720 jcontainer = $('.shadow-content0').html(data); 2721 } 2722 } else { 2723 $(data).modal(); 2724 var jcontainer = $('#simplemodal-container'); 2725 } 2726
2727 if (jcontainer.find('#note-history').length > 0) { 2728 SA.Note.postOpen(smid); 2729 return; 2730 } else if (jcontainer.find('#displayProfile-Client.appt-summary-only').length > 0) { 2731 GLO.ClientProfile.initApptSummary(); 2732 return; 2733 } 2734 2735 if (!GLO.Info.isMobile()) { $.modal.update(620, 670); } 2736 2737 var pop = $('#simplemodal-container'); 2738 2739 if (pop.length === 1) { 2740 pop.css({ "padding": "0", "background-color": "" }); 2741 2742 pop.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 2743 pop.find('#displayProfile-Client').css({ "padding": 0 }); 2744 //_openCompleted(pop, smid); 2745 } 2746 2747 GLO.ClientProfile.init(); 2748 } 2749 2750 function _cleanClientName(cname) { 2751 if (cname && cname.length > 1 && cname.substring(0,2) === '* ') { 2752 cname = cname.substring(2); 2753 } 2754 2755 return cname; 2756 } 2757 2758 _constructor.getClientObject = function(isProfile) { 2759 var j = UserPortal.getEditAppt(); 2760 2761 if (j.length === 1) { 2762 var cname = _cleanClientName(j.find('h4 > a').text()); 2763 var json = { "id": UserPortal.Edit.clientId, "name": cname, "ismodal": true, "smid": UserPortal.Edit.scheduleMultiId, "bkg": UserPortal.Edit.booking_nr }; 2764 } else { 2765 j = $('#simplemodal-container'); 2766 2767 if (j.length === 1) { 2768 var isModal = true; 2769 } else { 2770 var isModal = false; 2771 2772 if (j.length === 0) { 2773 j = $('.shadow-content0'); 2774 j.addClass('loading-profile'); 2775 } 2776 2777 //if (j.length === 0) { j = $('body'); } 2778 } 2779 2780 var bkg = null, smid = null, clientId = null, cname = ''; 2781 var jclient = j.find('.client-name-header:visible'); //var jclient = j.find('#clientName'); 2782 2783 if (jclient.length === 0) { 2784 jclient = j.find('.client-name-header'); 2785 } 2786 2787 if (jclient.length) { 2788 cname = jclient.find('span').eq(0); 2789 2790 if (cname.length === 1) { 2791 cname = cname.text(); 2792 } else { 2793 cname = jclient.text(); 2794 } 2795 2796 if (jclient.closest('#note-history').length === 1) { 2797 cname = cname.replace(' Notes', ''); 2798 } 2799 2800 clientId = jclient.attr('client_id'); 2801 smid = UTIL.cleanString(jclient.find('.back-to-appointment').attr('smid')); 2802 } else if (GLO.isPOS) { 2803 jclient = $('#pos-ticket-client .client-lookup'); 2804 cname = jclient.val(); 2805 clientId = SA.Ticket.clientId; 2806 bkg = SA.Ticket.bookingNumber; 2807 smid = $('#pos-ticket').attr('schedule_multi_id'); 2808 } 2809 2810 cname = _cleanClientName(cname); 2811 var json = { "id": clientId, "name": cname, "ismodal": isModal, "smid": smid, "bkg": bkg }; 2812 } 2813 2814 if (UTIL.isEmpty(json.id) && UTIL.isEmpty(json.name)) { 2815 var json = GLO.ClientProfile.getClientFromProfile(); 2816 } 2817 2818 var jmenu = j.find('.sa-easy-menu'); 2819 2820 if (jmenu.hasClass('menu-is-open')) { 2821 jmenu.find('.drop-icon').click(); 2822 } 2823 2824 _displayThrobberOverlay(j); 2825 2826 if (isProfile) { 2827 json.url = GLO.Link.Page.Provider.ClientProfile + '?IsPartial=1&cid=' + json.id + '&dt=' + UTIL.getDateString(); //if (json.ismodal) { json.url += '&IsPartial=1'; } 2828 } 2829 2830 return json; 2831 } 2832 2833 function _displayThrobberOverlay(jContainer) { 2834 var throbber = $('.loadingDiv').clone().find('img').addClass('loading-client-quick-view'); 2835 var jsonCSS = { "position": "absolute", "top": "0", "height": "100px", "margin-top": "60px", "z-index": "9999" }; 2836 2837 if (jContainer.attr('id') === 'simplemodal-container' || jContainer.closest('#simplemodal-container').length === 1) { 2838 jsonCSS["margin-left"] = "-40px"; 2839 } else { 2840 jsonCSS["margin-left"] = (jContainer.width() - 100)/2 + 'px'; 2841 } 2842 2843 throbber.css(jsonCSS); 2844 jContainer.prepend(throbber); 2845 } 2846 2847 function _getProfileModal(hideSaveBtn) { 2848 var jmodal = $('#simplemodal-container').css({ "background-color": "" }); 2849 2850 if (jmodal.length === 0) { 2851 jmodal = $('.shadow-content0.loading-profile').removeClass('loading-profile'); 2852 //$('#doc3').css({ "width": "750px", "margin": "0px auto", "padding-top": "9px", "text-align": "left" }); 2853 $('#doc3').css({ "margin": "0px auto", "padding-top": "8px", "text-align": "left" }); 2854 } 2855 2856 jmodal.find('.client-name-header').css({ "padding-top": "6px", "padding-bottom": "2px", "letter-spacing": "1px" }).find('>a').remove(); 2857 2858 if (hideSaveBtn) { 2859 jmodal.find('#clientProfile-buttons .btnSave').addClass('hide'); 2860 jmodal.find('#basicUserInfo').addClass('hide'); 2861 jmodal.find('#client-staff').removeClass('hide').find('td').css({ "padding-top": "8px", "padding-bottom": "8px" }); 2862 } else { 2863 jmodal.find('#clientProfile-buttons .btnSave').removeClass('hide'); 2864 jmodal.find('#client-staff').addClass('hide'); 2865 jmodal.find('#basicUserInfo').removeClass('hide'); 2866 } 2867 2868 return jmodal; 2869 } 2870 2871 function _cleanupEditModal() { 2872 var jedit = $('#ba-EditAppointment').closest('#simplemodal-container'); 2873 2874 if (jedit.length === 1) { 2875 UserPortal.Edit.cleanupModal(jedit, false); 2876 } 2877 } 2878 2879 _constructor.getDirections = function() { 2880 var jsonClient = _constructor.getClientObject(true); 2881 _cleanupEditModal(); 2882 _openDirections(true, jsonClient.smid, jsonClient.id, jsonClient.name, jsonClient.url); 2883 } 2884 2885 _constructor.openApptSummary = function() { 2886 var jsonClient = _constructor.getClientObject(true); 2887 _cleanupEditModal(); 2888 _constructor.openCompleted(jsonClient.url, true, jsonClient.name, jsonClient.smid, ClientProfile.openApptSummaryCompleted); 2889 } 2890 2891 _constructor.openProductHistory = function() { 2892 var jsonClient = _constructor.getClientObject(true); 2893 _cleanupEditModal(); 2894 _constructor.openCompleted(jsonClient.url, true, jsonClient.name, jsonClient.smid, ClientProfile.openProductHistoryCompleted); 2895 } 2896 2897 _constructor.openProductHistoryByClient = function(btn, cid, cname, smid) { 2898 var jsonClient = { "id": cid, "name": cname, "ismodal": false }; 2899 2900 if (smid) { 2901 jsonClient.smid = smid; 2902 } 2903 2904 jsonClient.url = GLO.Link.Page.Provider.ClientProfile + '?IsPartial=1&cid=' + jsonClient.id + '&dt=' + UTIL.getDateString() + '#view=product-history'; 2905 2906 if (btn) { 2907 GLO.UI.Form.beginProcessing(btn); 2908 } 2909 2910 _constructor.openCompleted(jsonClient.url, false, jsonClient.name, jsonClient.smid, ClientProfile.openProductHistoryCompleted); 2911 } 2912 2913 _constructor.openApptHistoryByClient = function(btn, cid, smid, start, end) { 2914 if (btn) { 2915 GLO.UI.Form.beginProcessing(btn); 2916 } 2917 2918 GLO.ClientHistory.open(cid, true, smid, start, end); 2919 } 2920 2921 _constructor.openProfileVerifyPassword = function(cid, isSave) { 2922 if (!isSave && !UTIL.isEmpty(_unlockPassword)) { 2923 _constructor.verifyUnlockPassword(cid, _unlockPassword); 2924 return; 2925 } 2926 2927 if (isSave) { 2928 var msgLabel = 'Enter password to save client profile'; 2929 } else { 2930 var msgLabel = 'Enter password to unlock client profile'; 2931 } 2932 2933 var msg = '<label for="Unlock_Password_vc" style="font-weight: bold; color: white;">' + msgLabel + '</label>'; 2934 var input = '<input type="password" id="Unlock_Password_vc" style="width: 200px; letter-spacing: 2px;"/>';
2935 var htm = '<div id="pop-unlock-client-profile" style="margin-bottom: 16px;">' + msg + input + '</div>'; 2936 2937 if (isSave) { 2938 var fnYes = function() { 2939 var jpop = $('#pop-unlock-client-profile').closest('.glopop'); 2940 var pass = jpop.find('#Unlock_Password_vc').val(); 2941 2942 _constructor.setUnlockPassword(pass); 2943 GLO.Popup.close(jpop); 2944 2945 var jclient = $('#displayProfile-Client'); 2946 2947 if (jclient.find('#Unlock_Password_vc').length === 0) { 2948 jclient.find('#basicUserInfo').prepend('<input type="password" id="Unlock_Password_vc" name="Unlock_Password_vc" class="hideX" value="' + pass + '"/>'); 2949 } 2950 2951 jclient.find('#clientProfile-save > a').click(); 2952 }; 2953 } else { 2954 var fnYes = function() { 2955 var jpop = $('#pop-unlock-client-profile').closest('.glopop'); 2956 var pass = jpop.find('#Unlock_Password_vc').val(); 2957 GLO.UI.Form.beginProcessing(jpop.find('.btnYes')); 2958 _constructor.verifyUnlockPassword(cid, pass); 2959 }; 2960 } 2961 2962 //var fnNo = function() { $('#ba-EditAppointment').find('#imgThrobber').remove(); }; //= for some reason this was not being called. 2963 2964 var ojpop = GLO.Popup.Prompt.open(htm, 'Unlock Client Profile', fnYes); //, fnNo 2965 var jpop = ojpop.getPopup(); 2966 jpop.find('#val').remove(); 2967 2968 var jbtns = jpop.find('.pop-buttons'); 2969 //jbtns.prepend('<span class="btnNo btn"> <a onclick="ClientProfile.openNoteHistory">View Notes</a> </span>'); 2970 jbtns.find('.btnCancel').find('>a').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" }); 2971 jbtns.find('.btnYes').css({ "width": "160px", "margin-right": "16px" }).find('> a').css({ "font-size": "16px", "font-weight": "bold" }).text('Unlock + View'); 2972 2973 setTimeout(function() { 2974 $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove(); 2975 }, 800); 2976 2977 ojpop.saveOnEnter(); 2978 jpop.find('#Unlock_Password_vc').focus(); 2979 } 2980 2981 _constructor.verifyUnlockPassword = function(cid, pass) { 2982 var url = GLO.Link.Page.Provider.Home + 'ClientProfileWithPassword?cid=' + cid; 2983 var jd = { "unlockpassword": pass }; 2984 2985 if (ClientProfile.isFullPageProfile() || $('#simplemodal-container:visible').length) { url += '&IsPartial=1'; } 2986 2987 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 2988 .success(function(data, textStatus, jqXHR) { 2989 var jmodal = $('#simplemodal-container'); 2990 $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove(); 2991 2992 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 2993 _constructor.clearUnlockPassword(); 2994 GLO.UI.Form.resetProcessing(); 2995 GLO.Popup.Warning.open(data, 'Unlock Client Profile'); 2996 } else { 2997 GLO.Popup.close($('#pop-unlock-client-profile').closest('.glopop')); 2998 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 2999 3000 _constructor.setUnlockPassword(pass); 3001 3002 var modalAlreadyOpen = (jmodal.length > 0); 3003 var smid = UTIL.coalesceInt(jmodal.find('.back-to-appointment').attr('smid'), UserPortal.Edit.scheduleMultiId); 3004 3005 _loadClientProfile(modalAlreadyOpen, smid, data); 3006 $('form#client-form #Unlock_Password_vc').val(pass); 3007 } 3008 }) 3009 .error(function(jqXHR, textStatus, errorThrown) { 3010 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3011 }); 3012 } 3013 3014 _constructor.openProfileOnly = function(isViewTags) { 3015 if (GLO.Data.Staff.hideClientContact) { 3016 var jsonClient = _constructor.getClientObject(true); 3017 _constructor.openProfileVerifyPassword(jsonClient.id); 3018 return; 3019 } 3020 3021 _constructor.openProfileOnly2(isViewTags); 3022 } 3023 3024 _constructor.openProfileOnly2 = function(isViewTags) { 3025 var jsonClient = _constructor.getClientObject(true); 3026 var url = jsonClient.url; 3027 var fn = function() { 3028 ClientProfile.openProfileOnlyCompleted(null, isViewTags); 3029 } 3030 3031 _cleanupEditModal(); 3032 _constructor.openCompleted(url, true, jsonClient.name, jsonClient.smid, fn); 3033 } 3034 function _addDateRangeToUrl(url, fallbackStart, fallbackEnd) { 3035 var start = null, end = null; 3036 var jtbl = $('#client-appt-history').find('.appt-list-result tbody'); 3037 3038 if (jtbl.length) { 3039 var dt1 = new Date(jtbl.find('tr:first').attr('appt_dt')), dt2 = new Date(jtbl.find('tr:last').attr('appt_dt'));
3040 3041 if (!UTIL.isDate(start)) { 3042 if (dt1 < dt2) { 3043 start = dt1.toGloDate(true); 3044 } else { 3045 start = dt2.toGloDate(true); 3046 } 3047 } 3048 3049 if (!UTIL.isDate(end)) { 3050 if (dt1 > dt2) { 3051 end = dt1.toGloDate(true); 3052 } else { 3053 end = dt2.toGloDate(true); 3054 } 3055 } 3056 } else { 3057 var trs = $('#clientProfile-staff').find('tbody > tr'); 3058 3059 for (var i=0; i < trs.length; i++) { 3060 var dtRecent = trs.eq(i).find('.appt-summary-recent-date').attr('recent_dt'); 3061 var dtUpcoming = trs.eq(i).find('.appt-summary-upcoming-date').attr('upcoming_dt'); 3062 3063 if (UTIL.isDate(dtRecent) || UTIL.isDate(dtUpcoming)) { 3064 if (UTIL.isDate(dtRecent) && UTIL.isDate(dtUpcoming)) { 3065 if (new Date(dtRecent) > new Date(dtUpcoming)) { 3066 var dtEnd = dtRecent; 3067 } else { 3068 var dtEnd = dtUpcoming; 3069 } 3070 } else if (UTIL.isDate(dtRecent)) { 3071 var dtEnd = dtRecent; 3072 } else { 3073 var dtEnd = dtUpcoming; 3074 } 3075 3076 end = new Date(dtEnd).toGloDate(true); 3077 start = new Date(end).addDays(-365).toGloDate(true); 3078 break; 3079 } 3080 } 3081 } 3082 3083 if (UTIL.isDate(start) && UTIL.isDate(end)) { 3084 if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; } 3085 url += '&start=' + start + '&end=' + end; 3086 } else if (UTIL.isDate(fallbackStart) && UTIL.isDate(fallbackEnd)) { 3087 if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; } 3088 url += '&start=' + new Date(fallbackStart).toGloDate(true) + '&end=' + new Date(fallbackEnd).toGloDate(true); 3089 } 3090 3091 return url 3092 } 3093 _constructor.gotoClientTicketHistory = function() { 3094 var jsonClient = _constructor.getClientObject(true); 3095 var h1 = jsonClient.name + ' ' + SA.Resource.TicketHistory; 3096 var uri = 'reports/TicketHistory?client=' + jsonClient.id; 3097 uri = _addDateRangeToUrl(uri, new Date().addDays(-365), new Date()); 3098 3099 var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>'; 3100 var jpop = GLO.Popup.Custom.openSimple(throbber, h1); 3101 GLO.Popup.Custom.singleButton(jpop, 'Close'); 3102 GLO.Uri.gotoUri(uri); 3103 } 3104 3105 _constructor.openMessagesSent = function() { 3106 var jsonClient = _constructor.getClientObject(true); 3107 _constructor.openMessagesSentById(jsonClient.id, jsonClient.smid, jsonClient.bkg); 3108 } 3109 _constructor.openMessagesSentById = function(clientId, smid, bookingNumber) { 3110 var url = GLO.Link.WebsiteDomain + 'message/history?ispartial=1&client=' + clientId + '&smid=' + smid; 3111 3112 var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>'; 3113 var h1 = 'Loading Messages sent to Client...'; 3114 3115 if (!UTIL.isEmpty(bookingNumber)) { 3116 h1 += ' for appointment P' + bookingNumber; 3117 } 3118 3119 var ojpop = GLO.Popup.Custom.openSimple(throbber, h1, null, null, true); 3120 var jpop = ojpop.getPopup(); 3121 GLO.Popup.Custom.singleButton(jpop, 'Close'); 3122 3123 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 3124 .success(function(data, textStatus, jqXHR) { 3125 jpop.addClass('quick-report').find('.msg').html(data); //jpop.css({ "z-index": "501" }).addClass('quick-report').find('.msg').html(data); 3126 var jh = jpop.find('#report-message-sent-history-header'); 3127 var jrpt = jpop.find('table.tablesorter:visible'); 3128 3129 jpop.find('.pop-header h1').html(jh.html()); 3130 jh.remove(); 3131 3132 UI.initTableSorter(jrpt); 3133 GLO.Report.CellSummary.initReport(jrpt, false, false); 3134 3135 ojpop.realign(); 3136 ojpop.realign(); 3137 3138 $('#simplemodal-container').find('#imgThrobber').remove(); 3139 $('.loading-client-quick-view').remove(); 3140 $('.shadow-content0.loading-profile').removeClass('loading-profile').find('#imgThrobber').remove(); 3141 3142 setTimeout(function() { 3143 ojpop.realign(); 3144 ojpop.realign(); 3145 }, 500); 3146 }) 3147 .error(function(jqXHR, textStatus, errorThrown) { 3148 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3149 $('.shadow-content0.loading-profile').removeClass('loading-profile').find('#imgThrobber').remove(); 3150 3151 if (ojpop && ojpop.close) { 3152 ojpop.close(); 3153 } 3154 }); 3155 } 3156 3157 _constructor.openAppointmentActivity = function(event) { 3158 var jsonClient = _constructor.getClientObject(true); 3159 3160 if (UTIL.isNumber(UserPortal.Edit.apptId) && UserPortal.getEditAppt().find('tr.editServiceRow').length === 1) { 3161 GLO.MyAppts.openHistory2(UserPortal.Edit.apptId); 3162 return; 3163 } 3164 3165 _constructor.openAppointmentActivityById(jsonClient.id, jsonClient.smid); 3166 } 3167 _constructor.openAppointmentActivityById = function(clientId, smid, bookingNumber) { 3168 var url = GLO.Link.WebsiteDomain + 'reports/RecentActivity?client=' + clientId + '&smid='
3168+ smid; 3169 3170 var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>'; 3171 var bkg = UTIL.coalesceString(bookingNumber, UserPortal.Edit.booking_nr, ''); 3172 var h1 = SA.Resource.AppointmentEditHistory; //SA.Resource.RecentAppointmentUpdates; 3173 3174 if (!UTIL.isEmpty(bkg)) { 3175 h1 = 'P' + bkg + ': ' + h1; 3176 } 3177 3178 var ojpop = GLO.Popup.Custom.openSimple(throbber, h1, null, null, true); 3179 var jpop = ojpop.getPopup(); 3180 GLO.Popup.Custom.singleButton(jpop, 'Close'); 3181 3182 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 3183 .success(function(data, textStatus, jqXHR) { 3184 jpop.addClass('quick-report').find('.msg').html(data); //jpop.css({ "z-index": "501" }).addClass('quick-report').find('.msg').html(data); 3185 jpop.find('.appt-list-search, .appt-list-line').remove(); 3186 3187 UI.initTableSorter( jpop.find('table.tablesorter:visible') ); 3188 ojpop.realign(); 3189 3190 $('#simplemodal-container').find('#imgThrobber').remove(); 3191 $('.loading-client-quick-view').remove(); 3192 }) 3193 .error(function(jqXHR, textStatus, errorThrown) { 3194 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3195 }); 3196 } 3197 3198 _constructor.openPaymentHistory = function(event) { 3199 var jsonClient = _constructor.getClientObject(true); 3200 var start = new Date(new Date().setMonth(new Date().getMonth() - 6)).toGloDate(); 3201 var url = 'reports/saleshistory?isfullpage=1&paymethod=0&client=' + jsonClient.id + '&start=' + start; 3202 3203 GLO.Report.CellSummary.gotoReport(url, null, event); 3204 } 3205 _constructor.openSalesDetail = function(event) { 3206 var jsonClient = _constructor.getClientObject(true); 3207 var start = new Date(new Date().setMonth(new Date().getMonth() - 6)).toGloDate(); 3208 var url = 'reports/saleshistory?isfullpage=1&client=' + jsonClient.id + '&start=' + start; 3209 3210 GLO.Report.CellSummary.gotoReport(url, null, event); 3211 } 3212 3213 _constructor.openApptHistory = function() { 3214 var jsonClient = _constructor.getClientObject(); 3215 _cleanupEditModal(); 3216 GLO.ClientHistory.open(jsonClient.id, true, jsonClient.smid); 3217 } 3218 3219 _constructor.openNoteHistory = function() { 3220 var jsonClient = _constructor.getClientObject(); 3221 _cleanupEditModal(); 3222 SA.Note.open(jsonClient.id, true, jsonClient.smid); 3223 } 3224 3225 function _openCompleted(jmodal, smid) { 3226 var h2 = jmodal.find('.client-name-header'); 3227 3228 if (jmodal.attr('id') == 'simplemodal-container') { 3229 jmodal.find('.modalCloseImg').css({ "top": "4px", "right": "4px" }); 3230 } 3231 3232 if (jmodal.length && UTIL.isNumber(smid)) { _addBackToEditAppt(h2, smid); } 3233 3234 GLO.Mobile.simpleModalLoadComplete(); 3235 3236 if (GLO.Info.isMobile() && jmodal.hasClass('simplemodal-container')) { 3237 jmodal.find('#clientProfile-buttons').removeClass('hide'); 3238 var height = jmodal.find('.simplemodal-wrap > div').height(); 3239 $.modal.update(height, innerWidth - 4); 3240 } 3241 } 3242 3243 function _addBackToEditAppt(h2, smid) { 3244 if (innerWidth > 600) { var text = SA.Resource.BackToAppointment; } else { var text = SA.Resource.Back; } 3245 3246 h2.prepend('<a class="back-to-appointment" smid="' + smid + '" onclick="UserPortal.Edit.get(null, ' + smid + ', true, ' + UserPortal.Edit.isCalendar + ', null, null, event)">< ' + text + '</a>'); 3247 } 3248 3249 _constructor.openApptSummaryCompleted = function(smid) { 3250 var jmodal = _getProfileModal(true); 3251 _openCompleted(jmodal, smid); 3252 } 3253 3254 _constructor.openProductHistoryCompleted = function(smid) { 3255 GLO.ClientProfile.displayProductHistory(); 3256 3257 var jmodal = _getProfileModal(true); 3258 jmodal.find('#basicUserInfo').addClass('hide'); 3259 3260 _openCompleted(jmodal, smid); 3261 } 3262 3263 _constructor.openProfileOnlyCompleted = function(smid, isViewTags) { 3264 var jmodal = _getProfileModal(false); 3265 _openCompleted(jmodal, smid); 3266 _displayCreateDate(jmodal); 3267 3268 if (isViewTags) { 3269 GLO.Popup.closeIfExist($('#pop-edit-client-tag').closest('.glopop')); 3270 3271 var jScrollableDiv = $('#simplemodal-container #extraUserInfo'); 3272 var jt = jmodal.find('#row-client-tag-manager'); 3273 3274 if (jScrollableDiv.length) { 3275 jScrollableDiv[0].scrollTop += 350; //scroll within popup 3276 } 3277 3278 UI.highlight(jt); 3279 } 3280 } 3281 3282 function _displayCreateDate(jmodal) { 3283 var cdt = jmodal.find('#Create_dt').val(); 3284 3285 if (UTIL.isDate(cdt)) { 3286 var createByStaffId = jmodal.find('#Create_By_Staff_id').val(); 3287 var createCode = jmodal.find('#Client_Create_cd').val(); 3288 var createDescription = UTIL.coalesceString(jmodal.find('#Client_Create_vc').val(), 'Created'); 3289 var createByLabel = '', htmLastLogin = ''; 3290 var dtLastLogin = jmodal.find('#Last_Login_dt').val(); 3291
3292 if (!UTIL.isEmpty(createByStaffId)) { 3293 var createByStaffName = UTIL.cleanString(UserPortal.getStaffName(createByStaffId)); 3294 3295 if (UTIL.coalesceString(createByStaffName, 'Anyone') == 'Anyone') { 3296 createByLabel = 'Profile ' + createDescription.replace('Create ', 'Created ').replace('By Staff', 'By Staff using').replace(' Web ', ' Website from '); 3297 } else { 3298 createByLabel = '<span style="font-size: inherit;" title="' + createDescription + '">Profile Created by ' + createByStaffName + '</span>'; 3299 } 3300 } else if (createCode < 30 || createCode > 299) { 3301 createByLabel = 'Profile ' + createDescription.replace('Create ', 'Created ').replace('By Client', 'By Client using').replace(' Web ', ' Website from '); 3302 } 3303 3304 var htm = '<div id="client-profile-create-date-row"><i>' + createByLabel + ' on </i><b>' + new Date(cdt).toGloDateString(false, true) + '</b></div>'; 3305 3306 if (UTIL.isDate(dtLastLogin)) { 3307 htmLastLogin = '<div id="client-profile-last-login-row"><span>Last Login</span> <b>' + new Date(dtLastLogin).toGloDateString(false, true) + '</b></div>'; 3308 } 3309 3310 jmodal.find('#client-body').append(htm + htmLastLogin); 3311 } 3312 } 3313 3314 _constructor.openApptHistoryCompleted = function(smid) { 3315 var jmodal = $('#client-appt-history').closest('#simplemodal-container, .shadow-content0'); 3316 3317 setTimeout(function() { 3318 $('#ui-datepicker-div:visible').css('display', 'none'); 3319 }, 400); 3320 3321 _openCompleted(jmodal, smid); 3322 } 3323 3324 _constructor.openNoteHistoryCompleted = function(smid) { 3325 var jmodal = $('#note-history').closest('#simplemodal-container, .shadow-content0'); 3326 _openCompleted(jmodal, smid); 3327 } 3328 3329 _constructor.getDropIcon = function(isEditAppt) { 3330 if (GLO.Info.roleType === undefined) { GLO.Info.init(); } 3331 if (GLO.Info.roleType < 100) { return ''; } 3332 //if (GLO.Info.isMobile()) { return ''; } //= disabled TEMPORARILY!!! 3333 3334 var dropIcon = '<li style="display: inline; float: none;"> <i class="drop-icon" onclick="UserPortal.Edit.openClientMenu()">▼</i> </li>'; 3335 var menu = '<ul>'; 3336 3337 if (GLO.Info.roleType > 159) { menu += '<li><a class="no-animate" onclick="ClientProfile.openApptSummary()" title="' + SA.Resource.GroupServicesByStaff + '">' + SA.Resource.AppointmentSummary + '</a></li>'; } 3338 if (GLO.Info.roleType != 200) { menu += '<li><a class="no-animate" onclick="ClientProfile.openApptHistory()" title="' + SA.Resource.AppointmentsByDateRange + '">' + SA.Resource.AppointmentHistory + '</a></li>'; } 3339 if (GLO.Info.roleType > 159 && GLO.Info.providerPackage !== 1) { menu += '<li><a class="no-animate" onclick="ClientProfile.openProductHistory()" title="' + SA.Resource.ProductPurchases + '">' + SA.Resource.ProductHistory + '</a></li>'; } 3340 3341 if (GLO.Data.Staff.clientNoteAccess < 400) { 3342 menu += '<li><a class="no-animate" onclick="ClientProfile.openNoteHistory()" title="' + SA.Resource.DisplayAllClientNotes + '">' + SA.Resource.NoteHistory + '</a></li>'; 3343 } 3344 3345 if (GLO.Info.roleType > 159 && GLO.Info.roleType != 200) { 3346 menu += '<li><a class="no-animate" onclick="ClientProfile.openPaymentHistory()" title="">' + SA.Resource.PaymentHistory + '</a></li>'; 3347 menu += '<li><a class="no-animate" onclick="ClientProfile.openSalesDetail()" title="">' + SA.Resource.SalesDetail + '</a></li>'; 3348 menu += '<li><a class="no-animate" onclick="ClientProfile.gotoClientTicketHistory()" title="">' + SA.Resource.TicketHistory + '</a></li>'; 3349 menu += '<li><a class="no-animate" onclick="ClientProfile.openProfileOnly()" title="">' + SA.Resource.Client + ' ' + SA.Resource.Profile + '</a></li>'; 3350 3351 if (GLO.Info.roleType > 219 && !isEditAppt) { 3352 menu += '<li><a class="no-animate" onclick="GLO.ClientProfile.deleteClient()" title="">' + SA.Resource.DeleteOrMerge + ' ' + SA.Resource.Profile + '</a></li>'; 3353 } 3354 3355 if (GLO.Data && GLO.Data.Staff && !GLO.Data.Staff.hideClientContact && GLO.Data.Staff.clientNoteAccess < 10) { 3356 menu += '<li><a class="no-animate" onclick="ClientProfile.openMessagesSent()">' + SA.Resource.MessagesSent + '</a></li>'; 3357 } 3358 3359 menu += '<li><a class="no-animate" onclick="ClientProfile.openAppointmentActivity(true)" title="" style="color: deeppink;">' + SA.Resource.AppointmentUpdates + '</a></li>'; 3360 } 3361 3362 if (isEditAppt) { 3363 if (!GLO.Info.isMobile(true)) { 3364 menu += '<li><a class="no-animate" onclick="UserPortal.Edit.print()" style="color: rgba(255, 20, 140,.6);">' + SA.Resource.Print + ' ' + SA.Resource.Appointment + '</a></li>'; 3365 } 3366 3367 if (GLO.Info.roleType > 209 && !UTIL.isEmpty(UserPortal.Edit.clientId)) { 3368 menu += '<li><a class="no-animate" onclick="UserPortal.Edit.removeClient()" title="Remove client from this appointment" style="color: rgba(255, 20, 140,.6);">' + SA.Resource.Remove + ' ' + SA.Resource.Client + '</a></li>'; 3369 } 3370 3371 if (GLO.Provider.isValidNextBillDate() && GLO.Info.providerPackage != 4) { //GLO.Info.isMobile() && 3372 menu += '<li><a class="no-animate" onclick="UserPortal.StaffNote.open(false)" style="color: rgba(255, 20, 140,.6);">Add Note/Images</a></li>'; 3373 } 3374 } 3375 3376 if (GLO.Popup.Profile.isDisplayNewClientForm(GLO.Data.provider.new_client_address_cd) || GLO.Data.provider.outcall_type_cd > 0) { 3377 menu += '<li><a class="no-animate" onclick="ClientProfile.getDirections()">' + SA.Resource.GetDirections + '</a></li>'; 3378 } 3379 3380 return '<ul class="sa-easy-menu" style="display: inline;">' + dropIcon + menu + '</ul> </ul>'; 3381 } 3382 3383 return _constructor; 3384})(); 3385 3386GLO.ReputationReport = (function() { 3387 function _constructor(name) { } 3388 3389 _constructor.init = function() { 3390 GLO.Info.init(); 3391 3392 var j = $('#client-appt-history'); 3393 var jtbl = j.find('table.tablesorter'); 3394 // var sortOrder = _getSortOrder(jtbl); 3395 3396 // _setHeader(j); 3397 3398 // UI.initTableSorter(jtbl, sortOrder); 3399 // UI.setAccessKey('#client-appt-history', GLO.ClientHistory.search); 3400 3401 var jhead = j.find('.appt-list-search'); 3402 GLO.Report.Template.initDateRange(jhead, true); 3403
3404 const urlParams = new URLSearchParams(window.location.search); 3405 var staff_id = urlParams.get('staff'); 3406 var service_id = urlParams.get('service'); 3407 3408 if (staff_id != null) { 3409 $('#Staff_id').val(staff_id).attr('selected','selected'); 3410 } 3411 if (service_id != null) { 3412 $('.Service_Filter').val(service_id).attr('selected','selected'); 3413 } 3414 // GLO.Report.enableFullPageCheck(); 3415 // GLO.Report.CellSummary.initReport(jtbl, true); 3416 } 3417 3418 _constructor.search = function(thisBtn) { 3419 var j = $('#client-appt-history'); 3420 var begin = UTIL.fromSADate(j.find('#report-start').val(), true, true); 3421 var end = UTIL.fromSADate(j.find('#report-end').val(), true, true); 3422 3423 if (new Date(begin).getTime() > new Date(end).getTime() ) { 3424 new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>'); 3425 return; 3426 } 3427 3428 var svc = j.find('.Service_Filter').val(); 3429 var staff = j.find('#Staff_id').val(); 3430 3431 if (!UTIL.isDate(begin)) { begin = ''; } 3432 if (!UTIL.isDate(end)) { end = ''; } 3433 if (UTIL.isEmpty(svc)) { svc = ''; } 3434 if (UTIL.isEmpty(staff)) { staff = ''; } 3435 3436 var qs = 'id=' + '&begin=' + begin + '&end=' + end + '&service=' + svc + '&staff=' + staff; 3437 var url = GLO.Link.Page.Provider.Home + 'ReputationReviewReport?' + qs; 3438 thisBtn = $(thisBtn).parent().css({ "top":"1px" }); 3439 // GLO.UI.Form.beginProcessing(thisBtn); 3440 3441 setTimeout(function() { window.location.href = url; },50 ); 3442 3443 } 3444 3445 _constructor.setOverallRatings = function(positivePercentage) { 3446 // Clamp values between 0 and 100 3447 if (positivePercentage < 0) positivePercentage = 0; 3448 if (positivePercentage > 100) positivePercentage = 100; 3449 3450 const negativePercentage = 100 - positivePercentage; 3451 3452 const positiveDiv = document.getElementById('positive-div'); 3453 const negativeDiv = document.getElementById('negative-div'); 3454 3455 // Set Widths 3456 positiveDiv.style.width = positivePercentage + '%'; 3457 negativeDiv.style.width = negativePercentage + '%'; 3458 3459 // Function to generate the HTML content 3460 const getContent = (percent, label) => { 3461 // If the percentage is very small (e.g. < 15%), hide text to prevent ugliness 3462 if (percent < 15) return ''; 3463 return ` 3464 <span class="percent-text">${percent}%</span> 3465 <span class="label-text">${label}</span> 3466 `; 3467 }; 3468 3469 // Inject HTML using innerHTML 3470 positiveDiv.innerHTML = getContent(positivePercentage, "Positive"); 3471 negativeDiv.innerHTML = getContent(negativePercentage, "Negative"); 3472 } 3473 3474 return _constructor; 3475})(); 3476 3477GLO.ClientHistory = (function() { 3478 function _constructor(name) { } 3479 var _clientId; 3480 3481 _constructor.init = function() { 3482 GLO.Info.init(); 3483 3484 var j = $('#client-appt-history'); 3485 var jtbl = j.find('table.tablesorter'); 3486 var sortOrder = _getSortOrder(jtbl); 3487 3488 _setHeader(j); 3489 3490 UI.initTableSorter(jtbl, sortOrder); 3491 UI.setAccessKey('#client-appt-history', GLO.ClientHistory.search); 3492 3493 var jhead = j.find('.appt-list-search'); 3494 GLO.Report.Template.initDateRange(jhead, true); 3495 GLO.Report.enableFullPageCheck(); 3496 GLO.Report.CellSummary.initReport(jtbl, true); 3497 } 3498 3499 function _getSortOrder(jtbl) { 3500 var arr = [1,2]; 3501 3502 if (jtbl.find('.column-location:visible').length > 0) { 3503 ++arr[0]; 3504 ++arr[1]; 3505 } 3506 3507 if (jtbl.find('.column-staff:visible').length > 0) { 3508 ++arr[0]; 3509 ++arr[1]; 3510 } 3511 3512 return arr; 3513 } 3514 3515 function _setHeader(jClient) { 3516 var rows = jClient.find('table.tablesorter tbody tr'); 3517 3518 if (rows.length === 0) { 3519 var ctext = SA.Resource.NoAppointments; 3520 _clientId = jClient.find('h2#clientName').attr('client_id'); 3521 } else { 3522 var ctext = rows.eq(0).attr('client_vc'); 3523 _clientId = rows.eq(0).attr('client_id'); 3524 } 3525 3526 var clientHeader = '<span id="inner-client-name">' + ctext + '</span>'; 3527 var Total_Appt_nr = rows.length; 3528 3529 if (!UTIL.isEmpty(Total_Appt_nr)) { 3530 if (Total_Appt_nr == 1) { 3531 var appt_str = ' ' + SA.Resource.Appointment.toLowerCase(); 3532 } else { 3533 var appt_str = ' ' + SA.Resource.Appointments.toLowerCase(); 3534 } 3535 } 3536 3537 clientHeader += ClientProfile.getDropIcon(); 3538 //clientHeader += '<a href="/provider/clientProfile?cid=' + _clientId + '" class="quietest">' + SA.Resource.SeeProfile + '</a>'; 3539 clientHeader += '<a onclick="GLO.Uri.gotoUri(\'provider/clientProfile?cid=' + _clientId + '\', this, event, true)" class="quietest">' + SA.Resource.SeeProfile + '</a>'; 3540 3541 if (GLO.Info.roleType > 159 && GLO.Info.roleType != 200) { 3542 clientHeader += '<a onclick="GLO.ClientHistory.gotoClientTicketHistory(this, event)" class="quietest ticket-history-client-link">' + SA.Resource.TicketHistory + '</a>'; 3543 } 3544 3545 $('h2#clientName').html(clientHeader); 3546 _constructor.loadDataComplete(); 3547 } 3548 _constructor.gotoClientTicketHistory = function(element, event) { 3549 var jfilter = $('#client-appt-history').find('.appt-list-search'); 3550 var sid = UTIL.cleanString(jfilter.find('#Staff_id').val()), sgid = UTIL.cleanString(jfilter.find('.Service_Filter').val()); 3551 var start = UTIL.fromSADate(jfilter.find('#report-start').val(), true, true); 3552 var end = UTIL.fromSADate(jfilter.find('#report-end').val(), true, true); 3553 var uri = 'reports/TicketHistory?client=' + _clientId + '&sfilter=' + sid; 3554 3555 var jtbl = $('#client-appt-history').find('.appt-list-result tbody'); 3556 var dt1 = new Date(jtbl.find('tr:first').attr('appt_dt')), dt2 = new Date(jtbl.find('tr:last').attr('appt_dt'));
3557 3558 if (!UTIL.isDate(start)) { 3559 if (dt1 < dt2) { 3560 start = dt1.toGloDate(true); 3561 } else { 3562 start = dt2.toGloDate(true); 3563 } 3564 } 3565 3566 if (!UTIL.isDate(end)) { 3567 if (dt1 > dt2) { 3568 end = dt1.toGloDate(true); 3569 } else { 3570 end = dt2.toGloDate(true); 3571 } 3572 } 3573 3574 if (sgid.length > 2 && sgid.substring(0,2) == 'sg') { uri += '&service-group=' + sgid.substring(2); } 3575 if (UTIL.isDate(start)) { uri += '&start=' + start; } 3576 if (UTIL.isDate(end)) { uri += '&end=' + end; } 3577 3578 GLO.Uri.gotoUri(uri, element, event); 3579 } 3580 3581 _constructor.open = function(cid, useCurrentModal, openFromSmid, start, end) { 3582 var url = location.protocol + '//' + location.host + '/provider/appointment/history/client/' + cid; 3583 3584 if (useCurrentModal) { url = GLO.Uri.addQueryKeyAndValue(url, 'ispartial=1&isload=1'); } 3585 if (UTIL.isDate(start)) { url = GLO.Uri.addQueryKeyAndValue(url, 'start=' + start); } 3586 if (UTIL.isDate(end)) { url = GLO.Uri.addQueryKeyAndValue(url, 'end=' + end); } 3587 3588 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 3589 .success(function(data, textStatus, jqXHR) { 3590 var jpop = $('#pop-help-cell-summary, #member-period-report').closest('.glopop'); 3591 3592 if (jpop.length > 0) { 3593 GLO.Popup.close(jpop); 3594 } 3595 3596 if (useCurrentModal) { 3597 var throbber = $('.loading-client-quick-view').remove(); 3598 var jcontainer = $('#simplemodal-container'); 3599 3600 if ($('.shadow-content0 .client-name-header').length > 0) { 3601 if (jcontainer.length > 0) { $.modal.close(); } 3602 3603 jcontainer = $('.shadow-content0').html(data); 3604 useCurrentModal = false; 3605 } else if (jcontainer.length === 1) { 3606 jcontainer.find('> .simplemodal-wrap').html(data); 3607 } else if (throbber.length === 1) { 3608 jcontainer = $('.shadow-content0').html(data); 3609 useCurrentModal = false; 3610 } else if (jcontainer.length === 0) { 3611 $(data).modal(); 3612 $('#simplemodal-container').find('.simplemodal-data').css({ "padding": "0" }); 3613 } 3614 } 3615 3616 GLO.ClientHistory.init(); 3617 3618 if (useCurrentModal) { 3619 var jmodal = $('#simplemodal-container').css({ "padding": "0", "background": "" }); 3620 var height = jmodal.find('.simplemodal-wrap > div').height(); 3621 3622 if (innerWidth > 760) { //if (!GLO.Info.isMobile()) { $.modal.update(620, 760); } 3623 $.modal.update(height, 750); 3624 } else { 3625 jmodal.css({ "width": "inherit", "height": "inherit" }); 3626 $.modal.update(height, null); 3627 } 3628 3629 jmodal.find('.client-name-header').find('>a').remove(); 3630 jmodal.find('#client-appt-history #appt-history-footer').css({ "position": "absolute", "bottom": "0" }); 3631 jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 3632 3633 ClientProfile.openApptHistoryCompleted(openFromSmid); 3634 } 3635 3636 _constructor.loadDataComplete(); 3637 }) 3638 .error(function(jqXHR, textStatus, errorThrown) { 3639 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3640 }); 3641 } 3642 3643 _constructor.search = function(thisBtn) { 3644 var j = $('#client-appt-history'); 3645 var begin = UTIL.fromSADate(j.find('#report-start').val(), true, true); 3646 var end = UTIL.fromSADate(j.find('#report-end').val(), true, true); 3647 3648 if (new Date(begin).getTime() > new Date(end).getTime() ) { 3649 new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>'); 3650 return; 3651 } 3652 3653 var svc = j.find('.Service_Filter').val(); 3654 var staff = j.find('#Staff_id').val(); 3655 3656 if (!UTIL.isDate(begin)) { begin = ''; } 3657 if (!UTIL.isDate(end)) { end = ''; } 3658 if (UTIL.isEmpty(svc)) { svc = ''; } 3659 if (UTIL.isEmpty(staff)) { staff = ''; } 3660 3661 var qs = 'id=' + _clientId + '&begin=' + begin + '&end=' + end + '&service=' + svc + '&staff=' + staff; 3662 var url = GLO.Link.Page.Provider.Home + 'ClientHistory?ispartial=1&' + qs; 3663 thisBtn = $(thisBtn).parent().css({ "top":"1px" }); 3664 GLO.UI.Form.beginProcessing(thisBtn); 3665 3666 setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs, 'Client Appointment History'); }, 50); 3667
3668 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 3669 .success(function(data, textStatus, jqXHR) { 3670 GLO.UI.Form.resetProcessing(); 3671 thisBtn.css({ "top":"12px" }); 3672 3673 var jd = $(data); 3674 var jtbl = jd.find('.tablesorter'); 3675 var jf = jd.find('#appt-history-footer'); 3676 3677 var jrpt = $('.appt-list-result').html(jtbl); 3678 var sortOrder = _getSortOrder(jrpt); 3679 3680 UI.initTableSorter( $('#client-appt-history table.tablesorter'), sortOrder); 3681 3682 if (jf.length) { 3683 $('.appt-list-result').append(jf); 3684 } 3685 3686 _constructor.loadDataComplete(); 3687 }) 3688 .error(function(jqXHR, textStatus, errorThrown) { 3689 thisBtn.css({ "top":"12px" }); 3690 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3691 }); 3692 } 3693 3694 _constructor.loadDataComplete = function() { 3695 var j = $('#client-appt-history').find('.appt-list-result'); 3696 var jrows = j.find('table.apptList tbody tr'); 3697 3698 if (jrows.length === 100 && j) { 3699 if ($('#client-appointment-history-table-note').length > 0) { return; } 3700 3701 var htm = '<div id="client-appointment-history-table-note" style="">' 3702 + '<b>Latest 100 services displayed</b>' 3703 + '<span>use search filter above to see more services</span>' 3704 + '</div>'; 3705 3706 j.prepend(htm); 3707 } 3708 3709 GLO.Report.CellSummary.initReport(j, true); 3710 GLO.Report.initIcons(j); 3711 3712 GLO.Report.hideEmptyColumn(j, 'column-location'); 3713 GLO.Report.hideEmptyColumn(j, 'price-column'); 3714 } 3715 3716 return _constructor; 3717})(); 3718 3719GLO.Recur = (function() { 3720 function _conRecur() { } 3721 3722 _conRecur.init = function(isAll) { 3723 var j = $('#client-appt-history'); 3724 _loadData(j); 3725 3726 j.find('#item-row-box-all').click(GLO.Recur.selectAll); 3727 UI.setAccessKey('#client-appt-history', GLO.Recur.search); 3728 3729 j.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 }); 3730 j.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 3731 3732 GLO.Report.enableFullPageCheck(); 3733 3734 if (!UTIL.parseBool(isAll)) { 3735 var start = UTIL.coalesceDate(GLO.Uri.url('start'), new Date()).toGloDate(); 3736 var end = UTIL.coalesceDate(GLO.Uri.url('end')); 3737 3738 j.find('.Begin_dt').val(start); 3739 3740 if (UTIL.isDate(end)) { 3741 j.find('.End_dt').val( new Date(end).toGloDate() ); 3742 } 3743 } 3744 } 3745 3746 function _loadData(jClient) { 3747 var rows = jClient.find('table.tablesorter tbody tr'); 3748 var Total_Appt_nr = rows.length; 3749 3750 if (UTIL.coalesceInt(Total_Appt_nr, 0) > 0 || !rows.hasClass('noResults')) { 3751 if (Total_Appt_nr == 1) { 3752 var appt_str = ' ' + SA.Resource.Appointment.toLowerCase(); 3753 } else { 3754 var appt_str = ' ' + SA.Resource.Appointments.toLowerCase(); 3755 } 3756 3757 var msg = Total_Appt_nr + " <span style='font-size: 77%; color: #ccc;'>" + appt_str + "</span>"; 3758 $('#xxx-client-header-switch-view').html(msg); 3759 } 3760 3761 var jtbl = jClient.find('table.tablesorter'); 3762 //var sortOrder = _getSortOrder(jtbl); 3763 UI.initTableSorter(jtbl, null, true); 3764 } 3765 3766 function _getSortOrder(jtbl) { 3767 var arr = [2,3]; 3768 3769 if (jtbl.find('.recur-column-staff').length > 0) { 3770 ++arr[0]; 3771 ++arr[1]; 3772 } 3773 3774 return arr; 3775 } 3776 3777 _conRecur.selectAll = function() { 3778 var jcheckbox = $(this); 3779 var isChecked = jcheckbox.prop('checked'); 3780 var tbl = jcheckbox.closest('table').find('tbody'); 3781 3782 var boxes = tbl.find('.item-row-box:visible input:checkbox'); 3783 3784 for (var i=0; i < boxes.length; i++) { 3785 boxes.eq(i).prop('checked', isChecked); 3786 } 3787 3788 //setTimeout(function() { jcheckbox.prop('checked', isChecked); }, 200); //= for some reason the 'all' checkbox doesn't stay checked. 3789 } 3790 3791 _conRecur.addMore = function() { 3792 $('#client-appt-history').find('tr:last').find('.apptListDate a').click(); 3793 3794 setTimeout(function() { 3795 $('#simplemodal-container #ba-EditAppointment #ba-EditRecur').addClass('hide'); 3796 3797 UserPortal.Edit.displayRecur(); 3798 UserPortal.Edit.schedule_recur_id = $('#client-appt-history #clientName').attr('schedule_recur_id'); 3799 }, 900); 3800 } 3801 3802 _conRecur.massDelete = function() { 3803 var jbox = $('#client-appt-history').find('table.tablesorter tbody tr input:checked'); 3804 var apptCount = 0, xml = '<ul class="hide">'; 3805 3806 for (var i=0; i < jbox.length; i++) { 3807 ++apptCount; 3808 xml += '<dl schedule_id="' + jbox.eq(i).closest('tr').attr('id') + '"/>'; 3809 } 3810 3811 if (apptCount === 0) { 3812 new GLO.Popup.Warning(SA.Resource.PleaseClickBoxNextToAppt); 3813 return; 3814 } 3815 3816 xml += '</ul>'; 3817 3818 var htmPass = '', css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;'; 3819
3820 if (GLO.Info.isMobile()) { var pcss = 'margin-right: 9px; color: Red;'; } else { var pcss = 'color: Red;'; } 3821 3822 if (GLO.Data && GLO.Data.Staff && GLO.Data.Staff.require_password_appointment_edit_fl) { 3823 htmPass = '<div id="appointment-edit-password"><label for="Edit_Password_vc">Password</label><input id="Edit_Password_vc" type="password" class="required" autocomplete="new-password"></div>'; 3824 } 3825 3826 var htm = '<form><p style="' + pcss + '">' + SA.Resource.DeleteWarning + ' ' + apptCount + ' ' + SA.Resource.Appointment.toLowerCase() + '?</p>' 3827 + xml 3828 + '<textarea id="Delete_Reason_vc" name="Delete_Reason_vc" maxlength="2000" rows="2" placeholder="' + SA.Resource.DeleteReason + '" style="' + css + '"></textarea>' 3829 + htmPass 3830 + '</form>'; 3831 3832 GLO.Popup.Confirm(htm, _conRecur.massDeleteConfirmed); 3833 } 3834 3835 function _requirePasswordOnDelete(editPassword) { 3836 if (GLO.Data && GLO.Data.Staff && GLO.Data.Staff.require_password_appointment_edit_fl && UTIL.isEmpty(editPassword)) { 3837 var msg = 'Please Enter Your Password to Delete Appointments'; 3838 GLO.Popup.Warning.open(msg, 'Password Required'); 3839 return true; 3840 } 3841 3842 return false; 3843 } 3844 3845 _conRecur.massDeleteConfirmed = function(jform) { 3846 var editPassword = jform.find('#Edit_Password_vc').val(); 3847 var reason = UTIL.htmlEncode(jform.find('#Delete_Reason_vc').val()); 3848 var xml = UTIL.htmlEncode(jform.find('ul').outerHTML()); 3849 3850 if (_requirePasswordOnDelete(editPassword)) { return; } 3851 3852 var j = $('#client-appt-history'); 3853 var recurId = j.find('#clientName').attr('schedule_recur_id'); 3854 3855 var begin = j.find('.Begin_dt').val().replace(/\//g, '-'); 3856 var end = j.find('.End_dt').val().replace(/\//g, '-'); 3857 3858 if (new Date(begin).getTime() > new Date(end).getTime() ) { 3859 var oj = new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>'); 3860 oj.getPopup().find('.pop-buttons').css({ "width": "320px" }); 3861 return; 3862 } 3863 3864 var url = GLO.Link.WebsiteDomain + 'schedule/massDelete'; 3865 var jd = { "schedule_recur_id": recurId, "xml": xml, "delete_reason_vc": reason, "edit_password_vc": editPassword }; 3866 3867 var ojProcessing = new GLO.Popup.Processing(SA.Resource.DeletingAppointments + '...'); //var thisBtn = $('#btnMassDeleteAppt').parent().css({ "top":"1px" }); GLO.UI.Form.beginProcessing(thisBtn); 3868 3869 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 3870 .success(function(data, textStatus, jqXHR) { 3871 ojProcessing.close(); //GLO.UI.Form.resetProcessing(); thisBtn.css({ "top":"12px" }); 3872 3873 if (!UTIL.isEmpty($(data).attr('error_cd'))) { 3874 new GLO.Popup.Warning(data); 3875 } else { 3876 $('.appt-list-result').html(data); 3877 _loadData(j); 3878 } 3879 }) 3880 .error(function(jqXHR, textStatus, errorThrown) { 3881 thisBtn.css({ "top":"12px" }); 3882 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3883 }); 3884 } 3885 3886 _conRecur.search = function(thisBtn) { 3887 var j = $('#client-appt-history'); 3888 var begin = j.find('.Begin_dt').val().replace(/\//g, '-'); 3889 var end = j.find('.End_dt').val().replace(/\//g, '-'); 3890 3891 if (new Date(begin).getTime() > new Date(end).getTime()) { 3892 new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>'); 3893 return; 3894 //} else if (UTIL.isEmpty(begin) && UTIL.isEmpty(end)) { 3895 // new GLO.Popup.Warning('Please enter a begin and end date'); 3896 // return; 3897 } 3898 3899 if (UTIL.isEmpty(begin)) { begin = ''; } 3900 if (UTIL.isEmpty(end)) { end = ''; } 3901 3902 var schedule_recur_id = j.find('#clientName').attr('schedule_recur_id'); 3903 var url = GLO.Link.WebsiteDomain + 'schedule/recur?issearch=1&schedule_recur_id=' + schedule_recur_id + '&start=' + begin + '&end=' + end; 3904 3905 thisBtn = $(thisBtn).parent().css({ "margin-top":"1px" }); 3906 GLO.UI.Form.beginProcessing(thisBtn); 3907
3908 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 3909 .success(function(data, textStatus, jqXHR) { 3910 GLO.UI.Form.resetProcessing(); 3911 thisBtn.css({ "margin-top":"15px" }); 3912 3913 $('.appt-list-result').html(data); 3914 _loadData(j); 3915 }) 3916 .error(function(jqXHR, textStatus, errorThrown) { 3917 GLO.UI.Form.resetProcessing(); 3918 thisBtn.css({ "top":"12px" }); 3919 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 3920 }); 3921 } 3922 3923 return _conRecur; 3924})(); 3925 3926var Search = (function() { 3927 function _constructor(name) { } 3928 var debug = false; 3929 3930 _constructor.inProgress = false; 3931 3932 _constructor.init = function(el, src, searchFunction, hasElementStyling) { 3933 el = $(el); 3934 3935 if (el.length === 0) { return; } 3936 3937 el.autocomplete({ 3938 source: src, 3939 minLength: 2, 3940 select: function(event, ui) { 3941 _constructor.inProgress = true; 3942 el = _switchFromButtonBasedSearch(el); 3943 var val = ui.item.value; 3944 3945 if (!UTIL.isEmpty(ui.item.gift_number_vc)) { 3946 el.attr('giftId', ui.item.id); 3947 } else if (ui.item.id.substring(0, 1) === "I") { 3948 el.attr('inventoryId', ui.item.id); 3949 } else if (ui.item.id.substring(0, 1) === "P") { 3950 el.attr('bookingId', ui.item.id); 3951 } else if (ui.item.id.substring(0, 1) === "O") { 3952 el.attr('shipmentId', ui.item.id); 3953 } else if (val.substring && val.length > 1 && (val.substring(0, 1) === "P" && UTIL.isNumber(val.substring(1))) || (val.substring(0, 2) === "#P") && UTIL.isNumber(val.substring(2))) { 3954 _selectTicketNumber(ui.item); 3955 } else { 3956 el.attr('clientId', ui.item.id); 3957 } 3958 3959 //if (debug) { log(ui.item ? "Selected: " + ui.item.value + " ; ID: " + ui.item.id : "Nothing selected, input was " + this.value); } 3960 $('#search-overlay').remove(); 3961 3962 if (!UTIL.isEmpty(ui.item.gift_number_vc)) { 3963 if ($('#simplemodal-container:visible').length > 0) { return; } //~ modal popup is open so shouldn't be here. 3964 3965 UserPortal.Price.GiftCard.openEdit(ui.item.id, ui.item.gift_number_vc, ui.item.gift_balance_mn); 3966 3967 Search.resetSearchBox(); 3968 setTimeout(Search.wait, 500); 3969 } else if (UTIL.isEmpty(searchFunction)) { 3970 _constructor.run(ui.item.value, ui.item.id, ui.item); 3971 setTimeout(Search.wait, 500); 3972 } 3973 }, 3974 open: function(){ 3975 $(this).autocomplete('widget').css("z-index", "5900 !important"); 3976 3977 return false; 3978 }, 3979 }); 3980 3981 if (el.length) { //hasElementStyling 3982 el.data("ui-autocomplete")._renderItem = function(ul, item) { 3983 var cssClass = "", cssStyle = "", title = "", aStyle = ''; 3984 3985 if (!UTIL.isEmpty(item.gift_number_vc)) { 3986 cssClass = " class='item-gift'"; 3987 } else if (item.id.substring(0,1) === 'I') { 3988 cssClass = " class='item-inventory'"; 3989 } 3990 3991 if (item.location_name_vc && item.location_name_vc.length > 1) { title = " title='" + item.location_name_vc + "'"; } 3992 3993 if (item.background_rgb_vc && item.background_rgb_vc.length > 4) { 3994 cssStyle = " style='background-color: rgb(" + item.background_rgb_vc + ");'"; 3995 aStyle = " style='color: white;'"; 3996 } 3997 3998 return $("<li" + cssClass + cssStyle + title + "></li>") 3999 .data("ui-autocomplete-item", item) 4000 .append("<a" + aStyle + ">" + item.label + "</a>") 4001 .appendTo(ul); 4002 }; 4003 } 4004 4005 el.focus(function() { 4006 $(this).parent().addClass("quick-search"); 4007 }); 4008 4009 //el.blur(function() { /* $(this).parent().removeClass("quick-search"); */ }); 4010 4011 _constructor.wait = function() { //this function simply mimicks the time of an ajax call, so the enter access key works. 4012 _constructor.inProgress = false; 4013 } 4014 } 4015 4016 function _selectTicketNumber(uiItem) { 4017 var msg = "Looking up Ticket " + UTIL.coalesceString(uiItem.label, ui
4017Item.value) + "..."; 4018 var jsonPostOpen = { "processing_message_vc": msg, "processing_header_vc": "Opening Ticket" }; 4019 4020 if (uiItem.appt_count_sr > 0) { 4021 UserPortal.Edit.get(null, uiItem.id, null, null, null, jsonPostOpen); 4022 } else if (uiItem.inventory_count_sr > 0) { 4023 UserPortal.Price.get(uiItem.id, false, jsonPostOpen); 4024 } else { 4025 UserPortal.getTicket(uiItem.id, uiItem.value); 4026 } 4027 } 4028 4029 function _switchFromButtonBasedSearch(el) { 4030 if (el.hasClass('sa-main-search')) { 4031 var jpop = $('#pop-sa-keypad').closest('.glopop'); 4032 GLO.Popup.close(jpop); 4033 4034 el = $('#easySearch_text'); 4035 } 4036 4037 return el; 4038 } 4039 4040 _constructor.resetSearchBox = function(jsearch) { 4041 if (jsearch === undefined) { 4042 jsearch = _getSearchBox(); 4043 } 4044 4045 window.setTimeout( function() { jsearch.val('').blur(); }, 900); //s.val(''); 4046 jsearch.attr('clientId', '').attr('inventoryId', '').attr('shipmentId', '').attr('bookingId', ''); 4047 } 4048 4049 function _getSearchBox() { 4050 if (GLO.Info.isMobile()) { 4051 var s = $('#mp-pusher.mp-pushed').find('#mp-menu-search input'); 4052 4053 if (s.length === 0) { s = $('#easySearch_text'); } 4054 } else if ($('.glopop.sa-main-search').length) { 4055 var s = $('.glopop.sa-main-search #pop-sa-keypad').find('input.sa-main-search'); 4056 } else { 4057 var s = $('#easySearch_text'); 4058 } 4059 4060 return s; 4061 } 4062 4063 _constructor.run = function(text, id, uiItem) { 4064 $('#search-overlay').remove(); 4065 if ($('#simplemodal-container:visible').length > 0) { return; } //~ modal popup is open so shouldn't be here. 4066 4067 var s = _getSearchBox(); 4068 var sid = s.attr('clientId'); 4069 var inventoryId = s.attr('inventoryId'); 4070 var smid = UTIL.cleanString(s.attr('bookingId')).replace( 'P', ''); 4071 var shipmentId = UTIL.cleanString(s.attr('shipmentId')).replace('O', ''); 4072 4073 var openAsFullPage = ($('.shadow-content0 #sale-keyboard:visible').length > 0); 4074 UTIL.Validate.changeReset(); 4075 4076 if (!UTIL.isEmpty(inventoryId)) { 4077 GLO.Inventory.openSummary(inventoryId); 4078 } else if (!UTIL.isEmpty(shipmentId)) { 4079 if (uiItem.order_type_cd == 200) { 4080 //toDo: implement link to audit history report. 4081 } else { 4082 document.location = GLO.Link.Page.Provider.Home + 'Inventory/index?EditShipmentId=' + shipmentId; 4083 } 4084 } else if (!UTIL.isEmpty(smid)) { 4085 if (UTIL.coalesceInt(uiItem.appt_count_sr, 0) > 0) { 4086 UserPortal.Edit.get(null, smid); 4087 } else if (UTIL.coalesceInt(uiItem.inventory_count_sr, 0) > 0) { 4088 UserPortal.Price.get(smid); 4089 } 4090 } else if (!UTIL.isEmpty(sid) || openAsFullPage) { 4091 var loadPage = GLO.Link.Page.Provider.ClientProfile + '?cid=' + id; 4092 ClientProfile.open(loadPage, false, text); 4093 } else { 4094 var searchName = s.val().replace('(', '').replace('#', '').replace('$', '').replace('^', '').replace('<', '').replace('>', '').replace('&', '').replace('/', '').replace('\\', '').replace('"', ''); //toDo: make UTIL.replaceAll a function of JavaScript's String object (ie. ~ String.prototype.replaceAll = UTIL.replaceAll) and use replaceAll 4095 4096 var loadPage = GLO.Link.Object.Provider.UserSearchResult + '?term=' + encodeURIComponent(searchName) + '&dt=' + UTIL.getDateString(); 4097 var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"}); 4098 var jmodal = $('#pop-temp'); 4099 var htmProcessing = '<p style="letter-spacing: 1px; font-size: large; font-weight: bold;">Looking up <b style="color: #4F81BD">' + searchName + '</b>...</p>'; 4100 var ojProcessing = GLO.Popup.Processing.open('<div id="pop-running-search">
4100' + htmProcessing + '</div>', 'Searching'); 4101 4102 jmodal.html(throbber).load(loadPage, function() { 4103 _loadSearchResults(ojProcessing); 4104 }); 4105 4106 jmodal.modal(); 4107 jmodal.find('#imgThrobber').css({ "margin-top": "22px" }); 4108 $.modal.update(75, 75); 4109 } 4110 4111 window.setTimeout( function() { s.val('').blur(); }, 900); //s.val(''); 4112 s.attr('clientId', '').attr('inventoryId', '').attr('shipmentId', '').attr('bookingId', ''); 4113 } 4114 4115 function _loadSearchResults(ojProcessing) { 4116 if (innerWidth > 660) { 4117 var popWidth = 650; 4118 } else if (!GLO.Info.isMobile()) { 4119 var popWidth = innerWidth - 40; //$('#simplemodal-container').css({ "width": "inherit" }); 4120 if (popWidth < 480) { popWidth = 500; } 4121 } else { 4122 var popWidth = null; 4123 } 4124 4125 ojProcessing.close(); 4126 GLO.Popup.closeIfExist($('.glopop.sa-main-search')); 4127 $.modal.update(null, popWidth); 4128 4129 var jm = $('#simplemodal-container'); 4130 var jticket = jm.find('.ticket-search'); 4131 var jproduct = jm.find('#inventory-item-summary'); 4132 4133 if (jticket.length) { 4134 var smid = jticket.attr('schedule_multi_id'); 4135 4136 if (UTIL.parseBool(jticket.attr('is_appt_fl'))) { 4137 UserPortal.Edit.get(null, smid, true, UserPortal.Edit.isCalendar, true); 4138 return; 4139 } else if (UTIL.parseBool(jticket.attr('is_product_fl'))) { 4140 $.modal.close(); 4141 UserPortal.Price.get(smid); 4142 return; 4143 } 4144 } else if (jproduct.length) { 4145 GLO.Inventory.openSummaryAdjust(true); //GLO.Inventory.openSummary2(arguments[0], arguments[1], arguments[2]); 4146 return; 4147 } 4148 4149 if (jm.width() < 100 || jm.height() < 200) { //BUG (Chrome): fixes bug when on calendar popup's width & height are both < 50px. 4150 var rowCnt = jm.find('#searchResults-Client tr').length; 4151 var rowHeight = 36; 4152 var h = 120 + rowCnt * rowHeight; 4153 4154 if (h < 240 && GLO.Info.isMobile()) { 4155 h = 240; 4156 } else if (h < 200) { 4157 h = 200; 4158 } else if (h > 570) { 4159 h = 570; 4160 } 4161 4162 /* if (rowCnt === 0) { 4163 searchName = UTIL.htmlEncode2(searchName); 4164 $('#pop-temp').html("<div style='margin: auto; margin-top: 70px; color: Black;'>" + SA.Resource.NoResultsFoundWouldYouLikeToCreate + " <b style='font-style: italic; color: Purple;'>" + searchName + "</b> " + SA.Resource.as_text + " <a onclick='GLO.Popup.Profile(null, \"" + searchName + "\")'>" + SA.Resource.a_new_client + "</a>?</div>"); 4165 } */ 4166 4167 if (GLO.Info.isMobile()) { 4168 $.modal.update(h, null); 4169 4170 if (GLO.Info.isLandscape()) { 4171 //$.modal.update(h, 555); 4172 var isPortrait = false; 4173 } else { 4174 //$.modal.update(h, 310); 4175 //jm.find('.landscape-only').addClass('hidePhone'); 4176 var isPortrait = true; 4177 } 4178 4179 $('#simplemodal-container .modalCloseImg').attr('style', 'top: 3px !important'); 4180 GLO.ClientProfile.resizeClientProfilePopup(jm, isPortrait); 4181 } else { 4182 $.modal.update(h, null); 4183 } 4184 4185 jm.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 4186 } 4187 } 4188 4189 function log(message) { 4190 $("<div/>").text(message).prependTo("#log"); 4191 $("#searchDebug").attr("scrollTop", 0); 4192 } 4193 4194 _constructor.createAppt = function() { //opens the create appt popup from the search results popup 4195 var tblRow = $('#searchResults-Client tbody tr.selectedRow'); 4196 4197 if (tblRow.length === 0) { 4198 tblRow = $('#searchResults-Client tbody tr'); 4199 4200 if (tblRow.length !== 1) { 4201 GLO.Popup.Warning(SA.Resource.PleaseClickRow); 4202 return; 4203 } 4204 } 4205 4206 var c = tblRow.find('td[cid]') 4207 var clientId = c.attr('cid'), clientName = c.find('a').text(); 4208 var otherAttributes = GLO.ClientProfile.getClientAttributes(tblRow); 4209 var row = '<tr client_id="' + clientId + '" client_vc="' + clientName + '"' + otherAttributes + '/>'; 4210 4211 $.modal.close(); 4212 4213 if (tblRow.find('.location-icon').length > 0) { 4214 GLO.ClientProfile.importClient(clientId, clientName); 4215 } else { 4216 UserPortal.Create.get(row); 4217 } 4218 } 4219 4220 return _constructor; 4221})(); 4222 4223 4224GLO.Report = (function() { 4225 function _conRpt() { } 4226 _conRpt.staffFilter = ''; 4227 _conRpt.portalName = ''; 4228 _conRpt.isInit = false; 4229 4230 _conRpt.init = function() { 4231 _conRpt.isInit = GLO.Staff.Filter.isReportPortal = true; 4232 UI.initTableSorter( $('table.tablesorter:visible') ); 4233 4234 if (!(GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile())) { 4235 _conRpt.initBeginAndEndDate(-7); 4236 } 4237 4238 var j = $('.appt-list-search'); 4239 4240 var begin = GLO.Uri.query('start'); 4241 var end = GLO.Uri.query('end'); 4242 4243 var svcId = GLO.Uri.query('service'); 4244 var sfilter = GLO.Uri.query('sfilter'); 4245 4246 if (UTIL.isDate(begin)) { j.find('.Begin_dt').val(new Date(begin).toGloDate(
4246)); } 4247 if (UTIL.isDate(end)) { j.find('.End_dt').val(new Date(end).toGloDate()); } 4248 4249 if (!UTIL.isEmpty(svcId) && (j.find('.Service_Filter').length === 1)) { j.find('.Service_Filter').val(svcId); } 4250 4251 _conRpt.addSFilterHelloBar(sfilter); 4252 _conRpt.initShortcutKeys(); 4253 _conRpt.isInit = false; 4254 _conRpt.enableFullPageCheck(); 4255 _conRpt.initUrlAction(); 4256 } 4257 4258 _conRpt.initUrlAction = function() { 4259 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 4260 var step = UTIL.coalesceInt(GLO.Uri.url('step'), 0); 4261 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 4262 4263 if (!UTIL.isEmpty(open)) { 4264 if (open === 'commission-help') { 4265 GLO.Provider.Commission.openReportHelp(step); 4266 } 4267 } 4268 4269 if (!UTIL.isEmpty(highlight)) { 4270 var jhighlight = $('#' + highlight + ', .' + highlight); 4271 4272 if (jhighlight.length > 0) { 4273 UI.highlight(jhighlight, 800, 6400, true); 4274 } 4275 } 4276 } 4277 4278 _conRpt.initBeginAndEndDate = function(beginDays, endDays, jContainer) { 4279 if (jContainer === undefined || jContainer === null) { jContainer = $('.appt-list-search'); } 4280 4281 var Begin_dt = new Date(), End_dt = new Date(); 4282 var dtUI1 = jContainer.find('.Begin_dt').val(), dtUI2 = jContainer.find('.End_dt').val(); 4283 4284 if (UTIL.isDate(dtUI1)) { 4285 Begin_dt = new Date(dtUI1); 4286 } else if (!UTIL.isEmpty(beginDays)) { 4287 Begin_dt.setDate(Begin_dt.getDate() + beginDays); 4288 } 4289 4290 if (UTIL.isDate(dtUI2)) { 4291 End_dt = new Date(dtUI2); 4292 } else if (!UTIL.isEmpty(endDays)) { 4293 End_dt.setDate(End_dt.getDate() + endDays); 4294 } 4295 4296 jContainer.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 4297 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 4298 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }).val(Begin_dt.toGloDate()); 4299 4300 jContainer.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 4301 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 4302 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }).val(End_dt.toGloDate()); 4303 } 4304 4305 _conRpt.initShortcutKeys = function() { 4306 //toDo (low priority): implement so that on report portals w/ multiple tabs, ctrl + right/left arrow --> navigates b/ reports 4307 } 4308 4309 _conRpt.initStaffFilter = function(isAddHelloBar) { 4310 var sfilter = GLO.Uri.query('sfilter'); 4311 var sgid = GLO.Uri.query('id'); 4312 4313 if (UTIL.isEmpty(sfilter) && UTIL.isEmpty(sgid)) { return; } 4314 4315 var jfilter = $('#hd #staff-filter'); 4316 4317 if (UTIL.isNumber(sfilter) && sfilter.indexOf(',') === -1) { 4318 jfilter.val(sfilter); 4319 } else if (UTIL.isNumber(sgid) && GLO.Uri.query('type') === 'sg') { 4320 jfilter.val(sfilter); 4321 } else if (sfilter.indexOf('-9') !== -1) { 4322 jfilter.val('house'); 4323 } else { 4324 jfilter.find('#staff-filter-custom').prop('selected', true); 4325 4326 if (jfilter.find('option#staff-filter-change').length === 0) { 4327 jfilter.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>'); 4328 } 4329 } 4330 4331 jfilter.find('#staff-filter-today').remove(); 4332 4333 if (isAddHelloBar && UTIL.coalesce(sfilter, 'all').toLowerCase() != 'all') { 4334 if (sfilter == 'house') { 4335 sfilter = GLO.Staff.Filter.getHouseStaff(); 4336 } else if (UTIL.isNumber(sgid) && GLO.Uri.query('type') === 'sg') { 4337 sfilter = $('#ServiceGroupOptionsClone option[value="' + jOption.attr('value') + '"]').attr('staff_ids'); 4338 } 4339 4340 _conRpt.setStaffFilter(sfilter); 4341 } 4342 } 4343 4344 _conRpt.initIcons = function(jtbl) { 4345 if (!jtbl || jtbl.length === 0) { 4346 jtbl = $('#bd table.tablesorter'); 4347 } 4348 4349 var searchQuery = '.location-icon, .appt-edit-contains-products, .staff-only-note-icon, .special-request-icon, .mult-service-icon, .cal-event-icon-multi-ticket'; 4350 searchQuery += ', .multi-service-icon, .multi-ticket-icon-container, .staff-only-note-icon, .special-request-icon, .camera-icon, .client-rating-icon'; 4351 4352 jtbl.find(searchQuery).css({ "cursor": "pointer" }).click(GLO.Report.openIconSummary); 4353 } 4354 4355 _conRpt.initEnterPasswordPage = function() { 4356 _hideReportInfo(); 4357 var jinput = $('#report-password-container #Report_Password_vc'); 4358 4359 if (jinput.length) { 4360 jinput.focus(); 4361 jinput[0].addEventListener("keydown", function (e) { 4362 if (e.code === "Enter") { //checks whether the pressed key is "Enter" 4363 $('#report-password-container .btnSearchWithReportPassword').find('> a').click(); 4364 } 4365 }); 4366 } 4367 } 4368 function _hideReportInfo() { 4369 $('.report-chart-container').remove(); 4370 } 4371 4372 _conRpt.openTag = function(event) { 4373 var jtag = $(this); 4374 var tr = jtag.closest('tr'); 4375 var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.reminder-client-name').find('a').text(); 4376 4377 if (UTIL.isEmpty(thisClientName)) { 4378 thisClientName = tr.find('.member-client-name').text(); 4379 } 4380 4381 GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName); 4382 } 4383 4384 _conRpt.openIconSummary = function(event) { 4385 var jicon = $(this); 4386 var id = jicon.attr('id'); 4387 title = UTIL.cleanString(jicon.attr('title'));
4388 if (!title && title != '') { 4389 title = UTIL.cleanString(jicon.find('>img').attr('title')); 4390 } 4391 4392 if (jicon.hasClass('location-icon')) { 4393 var h1 = 'Different Location', msg = title; 4394 } else if (jicon.hasClass('appt-edit-contains-products')) { 4395 var h1 = 'Has Product', msg = title; 4396 } else if (jicon.hasClass('staff-only-note-icon')) { 4397 var h1 = 'Staff Only Note', msg = '<label>Staff Only Note:</label> ' + title; 4398 } else if (jicon.hasClass('special-request-icon')) { 4399 var h1 = 'Special Request', msg = '<label>Special Request:</label> ' + title; 4400 } else if (jicon.hasClass('mult-service-icon')) { 4401 var h1 = 'Multiple Services', msg = title; 4402 } else if (jicon.hasClass('recur-icon')) { 4403 var h1 = 'Recurring Appointment', msg = UTIL.coalesce(title, 'is recurring appointment'); 4404 } else if (jicon.hasClass('cal-event-icon-multi-ticket')) { 4405 var h1 = 'Multiple Tickets', msg = 'Ticket linked to other tickets'; 4406 } else if (jicon.hasClass('camera-icon')) { 4407 var h1 = 'Appointment has Images', msg = UTIL.pluralLabel(jicon.attr('image_count_sr'), 'Image') + ' attached to appointment'; 4408 } else if (jicon.hasClass('client-rating-icon')) { 4409 var msg =''; 4410 var responseData = _getRatingDetails(title); 4411 if (responseData && responseData!='') { 4412 var arrResponse = UTIL.cleanString(responseData).split('|'); 4413 for (var i=0; i < arrResponse.length; i++) { 4414 if (!UTIL.isEmpty(arrResponse[i])) { 4415 msg += '<p>' + (arrResponse[i]) + '</p>'; 4416 } else { 4417 msg += '<br/>'; 4418 } 4419 } 4420 } 4421 4422 var h1 = 'Client Rating', msg = '<label>Rating Details:</label> ' + msg; 4423 } else { 4424 return; 4425 } 4426 4427 GLO.Popup.close($('#pop-help-icon-summary').closest('.glopop')); 4428 4429 var htm = '<div id="pop-help-icon-summary">' + msg + '</div>'; 4430 GLO.Popup.Info.open(htm, h1); 4431 } 4432 4433 _conRpt.enableFullPageCheck = function(isDefaultToDisplayAll) { 4434 var rptDefault = $.cookies.get("reports"); 4435 4436 if (rptDefault === "display-all" || (isDefaultToDisplayAll && UTIL.isEmpty(rptDefault))) { 4437 _conRpt.enableFullPage(true, true); 4438 } else { 4439 _conRpt.enableFullPage(false, true); 4440 } 4441 } 4442 4443 _conRpt.enableFullPage = function(isYes, isIgnoreCookie) { 4444 if (isYes) { 4445 $('body').removeClass('report-custom-page').addClass('report-full-page'); 4446 $('.btnReportAll').addClass('hideX'); 4447 $('.btnReportFit').removeClass('hideX'); 4448 4449 //var expireDate = new Date(); 4450 //expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1)); 4451 4452 if (!isIgnoreCookie) { 4453 UTIL.setCookie("reports", "display-all"); //$.cookies.set("reports", "display-all", { "expiresAt": expireDate }); 4454 } 4455 } else { 4456 if (GLO.Report.portalName === 'payroll') { 4457 if ($('body.report-custom-page').length === 1) { 4458 $('body').removeClass('report-custom-page'); 4459 } else if (_payrollUseCustomPage()) { 4460 $('body').removeClass('report-full-page').addClass('report-custom-page'); 4461 } 4462 } 4463 4464 $('body').removeClass('report-full-page'); 4465 $('.btnReportAll').removeClass('hideX'); 4466 $('.btnReportFit').addClass('hideX'); 4467 4468 if (!isIgnoreCookie) { 4469 UTIL.setCookie("reports", "fit-screen"); //UTIL.setCookieWithExpire("reports", null); 4470 } 4471 } 4472 } 4473 4474 function _getRatingDetails(title) { 4475 4476 var msg = '', arr = UTIL.cleanString(title).split('|'); 4477 var pid = arr[0]; 4478 var smid = arr[1]; 4479 var url = GLO.Link.WebsiteDomain + 'repman/getRatingDetailsForClientHistory?providerId='+pid+'&bookingId='+smid; 4480 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false,"async":false }) 4481 .success(function(data, textStatus, jqXHR) { 4482 }) 4483 .error(function(jqXHR, textStatus, errorThrown) { 4484 }).responseText; 4485 4486 return jqxhr; 4487 } 4488 4489 function _payrollUseCustomPage() { 4490 var cnt = 0, tds = $('#report-payroll-summary #report-payroll-header2 td'); 4491 4492 for (var i=0; i < tds.length; i++) { 4493 var td = tds.eq(i); 4494 4495 if (!td.hasClass('staff-column') && !td.hasClass('staff-type-column') && !td.hasClass('narrow-column') && !td.hasClass('hideX')) { 4496 ++cnt; 4497 } 4498 } 4499 4500 if (GLO.Info.isGold()) { var groupWidth = 300; } else { var groupWidth = 200; } 4501 4502 if (cnt * groupWidth < innerWidth) { 4503 return true; 4504 } else { 4505 return false; 4506 } 4507 } 4508 4509 _conRpt.addSFilterHelloBar = function(sfilter) { 4510 if (UTIL.isEmpty(sfilter) || String(sfilter).toLowerCase() === 'all') { 4511 $('#staff-filter').val('all'); 4512 } else if (String(sfilter).indexOf(',') !== -1) { 4513 $('#staff-filter').val('staff-filter-custom'); 4514 _conRpt.setStaffHelloBar(sfilter); 4515 } else if (UTIL.isNumber(sfilter)) { 4516 $('#staff-filter').val(sfilter); 4517 _conRpt.setStaffHelloBar(sfilter); 4518 } 4519 } 4520 4521 _conRpt.datePickerBeforeShow = function(input, inst) { 4522 $("#ui-datepicker-div").removeClass('is-week-picker').removeClass('is-month-picker'); 4523 4524 if ($(input).hasClass('week-picker')) { 4525 $("#ui-datepicker-div").addClass('is-week-picker'); 4526 } else if ($(input).hasClass('month-picker')) { 4527 $("#ui-datepicker-div").addClass('is-month-picker'); 4528 } 4529 } 4530 4531 _conRpt.datePickerOnChange = function(year, month, inst) { 4532 var jInput = $(inst.input); 4533 4534 if (jInput.hasClass('month-picker')) { 4535 if (jInput.hasClass('Begin_dt')) { 4536 var dt = new Date(year, month - 1, 1); 4537 } else { 4538 var dt = new Date(year, month, 0); 4539 } 4540
4541 jInput.val(dt.toGloDate()); 4542 } 4543 } 4544 4545 _conRpt.firstDayOfWeek = function(dt, firstDayOfWeek) { 4546 var selectedDayOfWeek = dt.getDay(); 4547 4548 if (selectedDayOfWeek >= firstDayOfWeek) { 4549 var diff = selectedDayOfWeek - firstDayOfWeek; 4550 } else { 4551 var diff = 7 + selectedDayOfWeek - firstDayOfWeek; 4552 } 4553 4554 return new Date(dt).addDays(-diff); 4555 } 4556 4557 _conRpt.datePickerOnSelect = function(dateText, inst) { 4558 var jInput = $(inst.input); 4559 4560 if (jInput.hasClass('week-picker')) { 4561 var dt = new Date(dateText); 4562 var firstDayOfWeek = jInput.datepicker('option', 'firstDay'); //= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1) 4563 var dtStart = _conRpt.firstDayOfWeek(dt, firstDayOfWeek); 4564 4565 if (!jInput.hasClass('Begin_dt')) { 4566 dtStart.addDays(6); 4567 } 4568 4569 jInput.val(dtStart.toGloDate()); 4570 } 4571 } 4572 4573 _conRpt.setBeginDate = function(dt, view, jInput) { 4574 dt = new Date(dt); 4575 4576 if (view === 'week') { 4577 dt.setDate(dt.getDate() - dt.getDay()); 4578 } else if (view === 'month') { 4579 dt = new Date(dt.getFullYear(), dt.getMonth(), 1); 4580 } 4581 4582 jInput.val(dt.toGloDate()); 4583 } 4584 _conRpt.setEndDate = function(dt, view, jInput) { 4585 dt = new Date(dt); 4586 4587 if (view === 'week') { 4588 dt.setDate(dt.getDate() - dt.getDay() + 6); 4589 } else if (view === 'month') { 4590 var dt = new Date(dt.getFullYear(), dt.getMonth() + 1, 0); 4591 } 4592 4593 jInput.val(dt.toGloDate()); 4594 } 4595 4596 _conRpt.movePrev = function() { 4597 _moveDates(-1); 4598 } 4599 _conRpt.moveNext = function() { 4600 _moveDates(1); 4601 } 4602 function _moveDates(up) { 4603 var j = $('.appt-list-search'); 4604 if (j.length === 0) { j = $('.report-search-header'); } 4605 4606 var jBegin = j.find('.Begin_dt'); 4607 var jEnd = j.find('.End_dt'); 4608 4609 var dt1 = jBegin.val(); 4610 var dt2 = jEnd.val(); 4611 var monthCount = null, isWeekRange = false; 4612 4613 if (!UTIL.isEmpty(dt1)) { 4614 if (GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile()) { 4615 var arr = dt1.split('-'); 4616 dt1 = new Date(arr[1] + '/' + arr[2] + '/' + arr[0]); 4617 } else { 4618 dt1 = new Date(dt1); 4619 } 4620 } else { 4621 dt1 = new Date(); 4622 } 4623 4624 if (!UTIL.isEmpty(dt2)) { 4625 if (GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile()) { 4626 var arr = dt2.split('-'); 4627 dt2 = new Date(arr[1] + '/' + arr[2] + '/' + arr[0]); 4628 } else { 4629 dt2 = new Date(dt2); 4630 } 4631 } else { 4632 dt2 = new Date(); 4633 } 4634 4635 if (jBegin.hasClass('month-picker')) { 4636 dt1.setMonth(dt1.getMonth() + (1 * up) ); 4637 dt2.setMonth(dt2.getMonth() + (1 * up) ); 4638 } else { 4639 if (jBegin.hasClass('week-picker')) { 4640 var moveBy = 7; 4641 } else if (!jBegin.is(':visible') && j.find('#Week_dt').length === 1) { 4642 var moveBy = 7; 4643 isWeekRange = true; 4644 } else if (GLO.Report.Template.isMonthRange(dt1, dt2)) { 4645 var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1); 4646 dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount)); 4647 dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount); 4648 } else { 4649 var oneDay = 24*60*60*1000; //hours * minutes * seconds * milliseconds. 4650 var moveBy = Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + 1; 4651 } 4652 4653 if (monthCount === null) { 4654 dt1.setDate(dt1.getDate() + (moveBy * up)); 4655 dt2.setDate(dt2.getDate() + (moveBy * up)); 4656 } 4657 } 4658 4659 if ((GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile())) { 4660 jBegin.val(dt1.toGloDate(true)); 4661 jEnd.val(dt2.toGloDate(true)); 4662 } else {
4663 jBegin.val(dt1.toGloDate()); 4664 jEnd.val(dt2.toGloDate()); 4665 } 4666 4667 var dtRange = GLO.Report.Timesheet.getWeekDateRange(dt1, dt2); 4668 4669 if (isWeekRange) { 4670 j.find('#week-date-range').text(dtRange); 4671 4672 GLO.UI.Form.beginProcessing( j.find('.btnAction1') ); 4673 GLO.Report.Timesheet.search(); 4674 } else if ($('#report-header-search').length > 0) { 4675 $('#report-header-search').click(); 4676 } else { 4677 $('#report-ticket-history').find('.report-search-header .btnSearch:visible a').click(); 4678 } 4679 } 4680 4681 _conRpt.hideEmptyColumn = function(jtbl, columnClass) { 4682 var tds = jtbl.find('tbody').find('.' + columnClass); 4683 4684 for (var i=0; i < tds.length; i++) { 4685 if (!UTIL.isEmpty(tds.eq(i).text())) { 4686 return false; 4687 } 4688 } 4689 4690 tds.addClass('hideX'); 4691 jtbl.find('thead').find('.' + columnClass).addClass('hideX'); 4692 4693 var tf = jtbl.find('tfoot').find('.' + columnClass); 4694 var colspan = UTIL.coalesceInt(tf.attr('colspan'), 0); 4695 4696 if (colspan > 1) { 4697 tf.attr('colspan', colspan - 1); 4698 return false; 4699 } else { 4700 tf.addClass('hideX'); 4701 return true; 4702 } 4703 } 4704 4705 _conRpt.changeStaffFilter = function(jOption) { 4706 if (jOption === undefined || jOption.attr('value') == 'all') { 4707 _conRpt.setStaffFilter(''); 4708 } else if (jOption.attr('value') == '' || jOption.attr('value') == '-99') { 4709 GLO.Staff.Filter.open(true); 4710 return; 4711 } else if (jOption.attr('value') == 'house') { 4712 var sfilter = GLO.Staff.Filter.getHouseStaff(); 4713 _conRpt.setStaffFilter(sfilter); 4714 } else if (jOption.attr('value') == 'not-house') { 4715 var sfilter = GLO.Staff.Filter.getNotHouseStaff(); 4716 _conRpt.setStaffFilter(sfilter); 4717 } else if (jOption.parent().attr('id') == 'staff-filter-sg') { 4718 _conRpt.setStaffFilter( $('#ServiceGroupOptionsClone option[value="' + jOption.attr('value') + '"]').attr('staff_ids') ); 4719 } else { //if (jOption.parent().attr('id') == 'staff-filter-s') 4720 _conRpt.setStaffFilter(jOption.attr('value')); 4721 } 4722 4723 if (GLO.Report.portalName === 'sales' || GLO.Report.portalName === 'popular') { //re-run all reports 4724 var jrpt, jrpts = $('.inventory-report, .entire-report'); 4725 4726 for (var i=0; i < jrpts.length; i++) { 4727 jrpt = jrpts.eq(i); 4728 GLO.Report.Template.search(null, jrpt); 4729 } 4730 } else if (GLO.Report.portalName === 'timesheet') {
4731 $('#timesheet-header #report-header-search').click(); 4732 } else if (GLO.Report.portalName === 'ticket') { 4733 GLO.Report.TicketHistory.search(); 4734 } else if (GLO.Report.portalName === 'incorrect-payment') { 4735 var btnRefresh = $('#bd h1 .fa-refresh')[0]; 4736 GLO.Report.Other.search(btnRefresh); 4737 } else if (GLO.Report.portalName === 'payroll-days') { 4738 _searchDailyPayrollReport(); 4739 } else { 4740 $('.report-search-header').find('.btnSearch > a').click(); 4741 } 4742 } 4743 4744 function _searchDailyPayrollReport() { 4745 var btnSearch = $('.report-search-header').find('.btnSearch:visible'); 4746 4747 if (btnSearch.length) { 4748 GLO.Report.Payroll.search(); 4749 } else { 4750 var btn = $('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected'); 4751 4752 if (btn.hasClass('btnProcessing4')) { 4753 setTimeout(function() { 4754 location.reload(); 4755 }, 1500); 4756 4757 GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Multiple Report Requests'); 4758 } else { 4759 btn.find('>a').click(); 4760 } 4761 } 4762 } 4763 4764 _conRpt.setStaffFilter = function(staffIds) { 4765 staffIds = UTIL.cleanString(staffIds); 4766 4767 var queryString = GLO.Uri.getQueryString('sfilter', staffIds); 4768 var uri = document.location.origin + document.location.pathname + '?' + queryString + document.location.hash; 4769 //var uri = document.location.origin + document.location.pathname + '?sfilter=' + staffIds + GLO.Uri.urlToArray() + document.location.hash; 4770 4771 try { 4772 window.history.pushState("", "Report", uri); 4773 } catch (e) { 4774 document.location = uri; 4775 return; 4776 } 4777 4778 _conRpt.setStaffHelloBar(staffIds); 4779 4780 /* 4781 if (GLO.Report.portalName !== 'sales') { 4782 if ($('#report-header-search:visible').length === 1) { 4783 $('#report-header-search').click(); 4784 } else { 4785 $('.report-search-header:visible').find('.btnSearch a').click(); 4786 } 4787 } 4788 */ 4789 } 4790 4791 _conRpt.getStaffHelloLabel = function(staffIds) { 4792 if (staffIds.substring(staffIds.length - 1) === ',') { staffIds = staffIds.substring(0, staffIds.length - 1); } 4793 4794 if (!UTIL.isEmpty(staffIds)) { 4795 var sname, slabel = '', arr = staffIds.split(','); 4796 var jddStaff = $('#ba-CreateAppointment').find('#Staff_id'); 4797 4798 for (var s=0; s < arr.length; s++) { 4799 sname = jddStaff.find('option[value="' + arr[s] + '"]').text(); 4800 4801 if (!UTIL.isEmpty(sname)) { 4802 if (slabel !== '') { slabel += ', '; } 4803 4804 slabel += '<span>' + sname + '</span>'; 4805 } 4806 } 4807 4808 return slabel; 4809 } else { 4810 return ''; 4811 } 4812 } 4813 4814 _conRpt.setStaffHelloBar = function(staffIds) { 4815 if (GLO.Info.isMobile()) { return; } 4816 4817 $('#staffFilter').remove(); 4818 4819 if (!UTIL.isEmpty(staffIds)) { 4820 var slabel = _conRpt.getStaffHelloLabel(staffIds); 4821 4822 if (!UTIL.isEmpty(slabel)) { 4823 var htm = '<div id="staffFilter"> <p>' 4824 +'<span class="filter-by">' + SA.Resource.FilterBy + ':</span> <span class="hello-bar-label">' + slabel + '</span>' 4825 + '<span class="ui-icon ui-icon-circle-close" style="position: fixed; right: 7px; top: 3px; cursor: pointer;" onclick="GLO.Staff.Filter.removeFilter()" title="' + SA.Resource.RemoveFilter + '"></span>' 4826 + '</p> </div>'; 4827 4828 $('#hd-parent').after(htm); 4829 $('#doc3').css({ "margin-top": "25px" }); 4830 } else { 4831 $('#doc3').css({ "margin-top": "" }); 4832 } 4833 } else { 4834 $('#doc3').css({ "margin-top": "" }); 4835 } 4836 } 4837 4838 _conRpt.setViewType = function() { 4839 var jContainer = $('.appt-list-search'); 4840 var jdt1 = jContainer.find('.Begin_dt'); 4841 var jdt2 = jContainer.find('.End_dt'); 4842 4843 if (this.value === 'week') { 4844 jContainer.find('#Week_dt').addClass('week-picker'); 4845 jContainer.find('.timesheet-search-day').addClass('hide'); 4846 jContainer.find('.timesheet-search-week').removeClass('hide'); 4847 4848 GLO.Report.Timesheet.datePickerOnSelect2(new Date(jdt1.val())); 4849 } else if (this.value === 'month') { 4850 pickers.addClass('month-picker'); 4851 pickers.datepicker("option", "changeMonth", true) 4852 pickers.datepicker("option", "changeYear", true); 4853 4854 var jdt1 = jContainer.find('.Begin_dt'); 4855 var jdt2 = jContainer.find('.End_dt'); 4856 4857 GLO.Report.setBeginDate(jdt1.val(), 'month', jdt1); 4858 GLO.Report.setEndDate(jdt1.val(), 'month', jdt2); 4859 4860 jContainer.find('.timesheet-search-week').addClass('hide'); 4861 jContainer.find('.timesheet-search-day').removeClass('hide'); 4862 } else { 4863 jContainer.find('.timesheet-search-week').addClass('hide'); 4864 jContainer.find('.timesheet-search-day').removeClass('hide'); 4865 } 4866
4867 $('#timesheet-view-options .view-selected').removeClass('view-selected'); 4868 $(this).parent().addClass('view-selected'); 4869 4870 if (!GLO.Report.isInit && GLO.Report.portalName === 'timesheet' && this.value !== 'week') { //= if is timesheet report (+ not initializing page, + not wk vw) --> run search. 4871 jContainer.find('#report-header-search').click(); 4872 } 4873 } 4874 4875 _conRpt.setupFastClick = function() { 4876 if (GLO.Info.isMobile(true)) { 4877 var jhead = $('.report-search-header'); 4878 4879 for (var i=0; i < jhead.length; i++) { 4880 GLO.Info.setupFastClick(jhead[i]); 4881 } 4882 } 4883 } 4884 4885 _conRpt.initReportPassword = function(jrpt) { 4886 if (GLO.Info.roleType < 220) { 4887 if (UTIL.isEmptyObject(jrpt)) { 4888 jrpt = $('#report-main'); 4889 } 4890 4891 jrpt.find('.tablesorter').find('input').prop('disabled', 'disabled').click(GLO.Report.allowReportChange); 4892 4893 if ($('#bd #commission-by-staff-service').length) { 4894 //UI.setAccessKey('#bd #commission-by-staff-service', null, GLO.Report.searchWithReportPassword); 4895 //jrpt.find('.commission-column-wage > a, .commission-column-product > a, .svc-price > a, .commission-column-tax-withheld').click(GLO.Report.allowReportChange); 4896 $('#bd #commission-by-staff-service-more').find('input').prop('readonly', 'readonly').click(GLO.Report.allowReportChange); 4897 } 4898 } 4899 } 4900 _conRpt.allowReportChange = function() { 4901 if (GLO.Info.roleType < 220) { 4902 if ($('#pop-warn-role-report').closest('.glopop').length === 0) { 4903 var htm = '<div id="pop-warn-role-report">Please login as manager or admin to change this setting</div>'; 4904 GLO.Popup.Warning.open(htm, 'Manager or Admin Required'); 4905 } 4906 4907 return false; 4908 } 4909 4910 return true; 4911 } 4912 _conRpt.hasReportPasswordWarning = function(data) { 4913 GLO.Popup.closeIfExist($('#pop-warn-missing-pin-session').closest('.glopop')); 4914 4915 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 4916 GLO.UI.Form.resetProcessing(); 4917
4918 var jpopPIN = GLO.Popup.Custom.openSimple('<div id="pop-warn-missing-pin-session">' + data + '</div>', 'Enter PIN / Password'); 4919 jpopPIN.find('.pop-buttons-parent').remove(); 4920 4921 jpopPIN[0].addEventListener("keydown", function(e) { 4922 if (e.code === "Enter") { //checks whether the pressed key is "Enter" 4923 jpopPIN.find('.btnSearchWithReportPassword').find('> a').click(); 4924 } 4925 }); 4926 4927 return true; 4928 } else { 4929 return false; 4930 } 4931 } 4932 _conRpt.openReportPassword = function() { 4933 GLO.UI.Form.resetProcessing(); 4934 4935 var htm = '<div id="pop-report-role-password" style="padding: 12px;">' 4936 + '<label for="Report_Password_vc">Enter Password to Access Report</label>' 4937 + '<input type="password" id="Report_Password_vc"/>' 4938 + '</div>'; 4939 4940 var jpop = GLO.Popup.Custom.openSimple(htm, 'Report Password', GLO.Report.searchWithReportPassword); 4941 4942 jpop.find('.pop-buttons').css({ "max-width": "320px" }); 4943 jpop.find('.btnSave').addClass('btnSearchWithReportPassword').addClass('btnAdd').removeClass('btnSave').css({ "position": "absolute", "right": "6px" }).find('a').text('Lookup'); 4944 4945 jpop[0].addEventListener("keydown", function(e) { 4946 if (e.code === "Enter") { //checks whether the pressed key is "Enter" 4947 jpop.find('.btnSearchWithReportPassword').find('> a').click(); 4948 } 4949 }); 4950 } 4951 _conRpt.searchWithReportPassword = function() { 4952 if ($('#enter-report-password-page').length) { 4953 var url = document.location.href; 4954 var element = $('#enter-report-password-page').find('.btnSearchWithReportPassword'); 4955 4956 SA.Menu.verifyPIN(url, false, element); 4957 } else if ($('#pop-edit-wage').closest('.glopop').length) { 4958 var jpop = $('#pop-edit-wage').closest('.glopop'); 4959 var password = jpop.find('#Report_Password_vc').val(); 4960 4961 if (jpop.find('#edit-employee-service').length) { 4962 GLO.Provider.Commission.saveEditWage(); 4963 } else { 4964 var sid = jpop.find('#Edit_Staff_id').val(); 4965 var sname = jpop.find('label[for="Edit_Hourly_Wage_mn"]').text(); 4966 var wage = ''; 4967 //var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>'; 4968 4969 GLO.Popup.close(jpop); // jpop.find('.no-results-report-role').replaceWith(throbber); 4970 GLO.Provider.Commission.openEditWage2(sid, sname, wage, password); 4971 } 4972 } else if ($('#bd #commission-by-staff-service').length) { 4973 GLO.Provider.Commission.loadCommissionReport(); 4974 } else if ($('#pop-confirm-save-goals').closest('.glopop').length) { 4975 var jpop = $('#pop-confirm-save-goals').closest('.glopop'); 4976 jpop.find('.btnSave > a').click(); 4977 } else if ($('#cash-event-popup').closest('.glopop').length) { 4978 var jpop = $('#cash-event-popup').closest('.glopop'); 4979 jpop.find('.btnSave > a').click(); 4980 //} else if ($('.glopop').length > 0 && $('#Report_Password_vc').closest('.glopop').length === 0) { 4981 // _conRpt.openReportPassword(); 4982 } else if ($('#client-list-search-button').find('#btnFilter > a').length) { 4983 $('#client-list-search-button').find('#btnFilter > a').click(); 4984 } else if ($('#timesheet-view-options #timesheet-weekly').prop('checked')) { 4985 GLO.Report.Timesheet.search(); 4986 } else { 4987 var jbtn = $('#report-main, .report-search-header, #doc3 #timesheet-report').find('.btnSearch > a:visible'); 4988 4989 if (jbtn.length) { 4990 jbtn.eq(0).click(); 4991 } else if (GLO.Report.portalName == 'payroll-days') { 4992 $('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected > a').click(); 4993 } else { 4994 $('#bd').find('h1, h2').find('.fa-refresh').click(); 4995 } 4996 } 4997 } 4998 _conRpt.isReport = function(urlPath) { 4999 if (GLO.Staff && GLO.Staff.Filter && GLO.Staff.Filter.isReportPortal) { 5000 return true; 5001 } 5002 5003 urlPath = $.trim(urlPath); 5004 5005 if (urlPath.startsWith(document.location.origin)) { 5006 urlPath = urlPath.substring(document.location.origin.length); 5007 } 5008 5009 var arr = urlPath.toLowerCase().split('?'); 5010 var urlPath2 = arr[0]; 5011 5012 if (urlPath2.length && urlPath2.substring(0, 1) === '/') { 5013 urlPath2 = urlPath2.substring(1); 5014 } 5015 5016 if (urlPath2.length && urlPath2.substring(urlPath2.length - 1) === '/') { 5017 urlPath2 = urlPath2.substring(0, urlPath2.length - 1); 5018 } 5019 5020 if (UTIL.startsWith(urlPath2, 'report/') || UTIL.startsWith(urlPath2, 'reports/')) { 5021 return true; 5022 } else if (urlPath2 == 'provider/inventory' || urlPath2 == 'inventory' || urlPath2 == 'message/clientlist' 5023 || urlPath2 == 'membership/report' || urlPath2 == 'membership/servicereport' || urlPath2 == 'payment/reportdaterange' || urlPath2 == 'payment/reportbatch' 5024 || urlPath2 == 'provider/manage/discount' || urlPath2 == 'provider/manage/addon' || urlPath2 == 'provider/manage/referral' || urlPath2 == 'provider/manage/commissionbystaffservice') { 5025 return true; 5026 } 5027 5028 return false; 5029 } 5030 _conRpt.autoSearch = function(element) { 5031 $('#report-main, .appt-list-search').find('.btnSearch > a:visible').click(); 5032 } 5033 _conRpt.hasTimesheetAccess = function(jd) { 5034 var rr = UTIL.coalesceInt(GLO.Data.Staff.role_report_cd, 0); 5035 5036 if (rr === 30 || rr === 36) { 5037 return true; 5038 } else { 5039 return _conRpt.hasReportPassword(jd); 5040 } 5041 } 5042 _conRpt.hasReportPassword = function(jd, isPayroll) { 5043 var rr = UTIL.coalesceInt(GLO.Data.Staff.role_report_cd, 0); 5044 5045 if (rr === 0 || rr === 99 || rr === 199) { 5046 return true; 5047 } else if (!isPayroll && rr < 99) { 5048 return true; 5049 } 5050 5051 var j = $('#report-password-container'); 5052 var pass = j.find('#Report_Password_vc').val(); 5053 5054 if (UTIL.isEmpty(pass)) { 5055 var jpop = $('#pop-report-role-password').closest('.glopop'); 5056 5057 if (jpop.length) { 5058 pass = jpop.find('#Report_Password_vc').val(); 5059 5060 if (UTIL.isEmpty(pass)) { 5061 var fnFocus = function() { jpop.find('#Report_Password_vc').focus(); } 5062 GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus); 5063 return false; 5064 } else { 5065 GLO.Popup.close(jpop); 5066 jd.report_password_vc = UTIL.htmlEncode(pass); 5067 return true; 5068 } 5069 } else if (j.length) { 5070 var fnFocus = function() { j.find('#Report_Password_vc').focus(); } 5071 GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus); 5072 return false; 5073 }
5073 else if (!UTIL.isEmpty($.cookies.get('pinsession'))) { 5074 return true; 5075 } else { 5076 _conRpt.openReportPassword(); 5077 return false; 5078 } 5079 } else { 5080 GLO.UI.Form.beginProcessing(j.find('.btnSearchWithReportPassword')); 5081 jd.report_password_vc = UTIL.htmlEncode(pass); 5082 return true; 5083 } 5084 } 5085 5086 _conRpt.exportAsSpreadsheet = function(trs, fileName, btnId) { 5087 var htm = '<table border="2px">'; 5088 var textRange, j=0, rowCount = 0; 5089 5090 for (a=0 ; a < trs.length ; a++) { 5091 var tr = trs.eq(a); 5092 5093 if (!tr.hasClass('ignore-export')) { 5094 if (tr.parent().is('thead')) { 5095 var css = 'text-align: center; font-weight: bold; background-color: rgb(180,200,255);'; 5096 } else if (tr.parent().is('tfoot')) { 5097 var css = 'background-color: rgb(200,200,200);'; 5098 } else { 5099 if (rowCount % 2 === 1) { 5100 var css = 'background-color: rgb(250,250,250);'; 5101 } else { 5102 var css = ''; 5103 } 5104 5105 ++rowCount; 5106 } 5107 5108 htm += '<tr style="' + css + '">'; 5109 var tds = trs.eq(a).find('th,td'); 5110 5111 for (var b=0; b < tds.length; b++) { 5112 var td = tds.eq(b); 5113 5114 if (!td.hasClass('ignore-export')) { 5115 td = td.clone(); 5116 td.find('.btnAdd, .btnSave').remove(); 5117 5118 if (td.find('input').length) { 5119 var jinput = td.find('input'); 5120 td.append(jinput.val()); 5121 jinput.remove(); 5122 } 5123 5124 htm += td.outerHTML(); 5125 } 5126 } 5127 5128 htm += '</tr>'; 5129 } 5130 } 5131 5132 htm += '</table>'; 5133 htm = htm.replace(/<A[^>]*>|<\/A>/g, ''); //remove if u want links in your table 5134 htm = htm.replace(/<img[^>]*>/gi, ''); //remove if u want images in your table 5135 //htm = htm.replace(/<input[^>]*>|<\/input>/gi, ''); //removes input params 5136 5137 var ua = window.navigator.userAgent; 5138 var msie = ua.indexOf("MSIE "); 5139 5140 if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) { // If Internet Explorer 5141 txtArea1.document.open("txt/html","replace"); 5142 txtArea1.document.write(htm); 5143 txtArea1.document.close(); 5144 txtArea1.focus(); 5145 sa = txtArea1.document.execCommand('SaveAs', true, fileName); 5146 } else { 5147 //sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(htm)); 5148 5149 var btnId = UTIL.coalesceString(btnId, 'btnExportLink'); 5150 var downloadLink = $('#' + btnId)[0]; 5151 downloadLink.href = 'data:application/vnd.ms-excel,' + encodeURIComponent(htm); 5152 downloadLink.download = fileName; 5153 downloadLink.click(); 5154 } 5155 5156 //return (sa); 5157 } 5158 5159 return _conRpt; 5160})(); 5161 5162 5163GLO.Report.Template = (function() { 5164 function _conRptTemplate() { } 5165 5166 _conRptTemplate.init = function() { 5167 GLO.Staff.Filter.isReportPortal = true; 5168 var jhead = $('.report-search-header'); 5169 5170 for (var i=0; i < jhead.length; i++) { 5171 var includeYearRange = _isIncludeYearRange(jhead); 5172 var yearRange = GLO.UI.getYearRange(true); //'2012:' + (new Date().getFullYear() + 2); 5173 5174 jhead.eq(i).find('input[type=text].Report_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true 5175 , calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 5176 , beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange }); 5177 jhead.eq(i).find('input[type=text].Report_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true 5178 , calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths()
5179 , beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange }); 5180 } 5181 5182 var jtbls = $('.tablesorter'); 5183 5184 for (var i=0; i < jtbls.length; i++) { 5185 UI.initTableSorter2( jtbls.eq(i) ); 5186 } 5187 5188 $('#report-portal-header').removeClass('hide'); 5189 5190 if (!GLO.Report.Sales.initStaffFilter()) { 5191 _conRptTemplate.initStaffFilter(); 5192 } 5193 5194 GLO.Report.setupFastClick(); 5195 return GLO.Uri.url('tab'); 5196 } 5197 5198 function _isIncludeYearRange(jhead) { 5199 var jrpt = jhead.closest('.inventory-report'); 5200 var rptid = jrpt.attr('id'); 5201 5202 if (rptid === 'report-sales-summary' || rptid === 'report-popular-services' || rptid === 'report-popular-products' || rptid === 'report-product-activity' 5203 || rptid === 'report-product-history' || rptid === 'report-shipment-history' || rptid === 'report-audit-history' || rptid === 'report-returns-exchanges') { 5204 return true; 5205 } else { 5206 return false; 5207 } 5208 } 5209 5210 _conRptTemplate.initDateRange = function(jhead, includeYearRange, isBlockFutureDays) { 5211 if (jhead.find('#report-start').length === 0) { return; } 5212 5213 var yearRange = GLO.UI.getYearRange(true); //'2012:' + (new Date().getFullYear() + 2); 5214 var monthsToShow = 1; 5215 5216 if (innerWidth > 970) { 5217 monthsToShow = 2; 5218 } 5219 5220 var startOptions = { showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 5221 , dateFormat: "M d, yy", numberOfMonths: monthsToShow, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange }; 5222 5223 var endOptions = { showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 5224 , dateFormat: "M d, yy", numberOfMonths: monthsToShow, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange }; 5225 5226 if (isBlockFutureDays) { 5227 startOptions.maxDate = 0; 5228 endOptions.maxDate = 0; 5229 } else { 5230 startOptions.showCurrentAtPos = 1; 5231 } 5232 5233 //number of months must be '1' (cannot use UI.getDatepickerMonths() ) because if show more than 1 month then datepicker on start overlaps left side of screen on client history report 5234 var jstart = jhead.find('#report-start').datepicker(startOptions); 5235 var jend = jhead.find('#report-end').datepicker(endOptions); 5236 5237 var dtStart = jhead.find('label[for="report-start"]').attr('inital_date'); 5238 var dtEnd = jhead.find('label[for="report-end"]').attr('inital_date'); 5239 5240 if (UTIL.isDate(dtStart)) { 5241 dtStart = new Date(dtStart).toSADate(true); 5242 jstart.val(dtStart); 5243 } 5244 5245 if (UTIL.isDate(dtEnd)) { 5246 dtEnd = new Date(dtEnd).toSADate(true); 5247 jend.val(dtEnd) 5248 } 5249 } 5250 5251 _conRptTemplate.initStaffFilter = function(isAddHelloBar) { 5252 GLO.Report.initStaffFilter(isAddHelloBar); 5253 return; 5254 /* if (!UTIL.isEmpty(GLO.Uri.query('sfilter'))) { 5255 var sfilter = GLO.Uri.query('sfilter'); 5256 var jdd = $('#header-navigation-links #staff-filter'); 5257 5258 if (jdd.length === 0) { jdd = $('#hd-parent #staff-filter'); } 5259 5260 var option = jdd.find('option[value="' + sfilter + '"]'); 5261 5262 if (option.length > 0) { 5263 //jdd.val(sfilter).change(); //Apr 2016: was throwing invalid begin date warning message. 5264 } else { 5265 jdd.find('option#staff-filter-custom').prop('selected', true); 5266 } 5267 } */ 5268 } 5269 5270 _conRptTemplate.movePrev = function() { 5271 _conRptTemplate.moveDates(-1); 5272 _moveSearch(); 5273 } 5274 _conRptTemplate.moveNext = function() { 5275 _conRptTemplate.moveDates(1); 5276 _moveSearch(); 5277 } 5278 function _moveSearch() { 5279 var jsearch = $('.report-search-header:visible').find('.btnSearch > a'); 5280 5281 if (jsearch.length === 1) { 5282 jsearch.click(); 5283 } else { 5284 _conRptTemplate.search(); 5285 } 5286 } 5287 5288 function _getSearchDate(jdt) { 5289 if (jdt.hasClass('is-sa-date')) { 5290 var dt = UTIL.fromSADate(jdt.val()); 5291 } else { 5292 var dt = UTIL.replaceAll(jdt.val(), '-', '/'); //= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone). 5293 } 5294 5295 if (UTIL.isDate(dt)) { 5296 return new Date(dt); 5297 } else { 5298 if (jdt.hasClass('Report_Begin_dt') || jdt.hasClass('Begin_dt')) { 5299 var msg = 'start'; 5300 } else { 5301 var msg = 'end'; 5302 } 5303 5304 msg = '<div> <h1 class="friendly-msg2">' + SA.Resource.DateMissing + '</h1> <div class="friendly-msg2">' + SA.Resource.Please_enter_a + ' ' + msg + ' ' + SA.Resource.Date.toLowerCase() + '</div> </div>'; 5305 new GLO.Popup.Warning(msg, function() { jdt.focus(); }); 5306 5307 return null; 5308 } 5309 } 5310 5311 _conRptTemplate.addMonthsToEndDate = function(dt, monthCount) { 5312 return new Date(dt.getFullYear(), dt.getMonth() + monthCount + 1, 0) 5313 } 5314 5315 _conRptTemplate.isMonthRange = function(dt1, dt2) { 5316 var dtNextDay = new Date(dt2); 5317 dtNextDay = new Date(dtNextDay.setDate(dtNextDay.getDate() + 1)); 5318 5319 if (dt1.getDate() === 1 && dtNextDay.getDate() === 1) { 5320 return true; 5321 } else { 5322 return false; 5323 } 5324 } 5325 5326 _conRptTemplate.focusDate = function(selector) { 5327 if ($('.pop-warning:visible').length === 0 || $('.pop-warning:visible').length === 0) { 5328 $(selector).focus() 5329 } 5330 } 5331 5332 _conRptTemplate.moveDates = function(up) { 5333 var oneDay = 24 * 60 * 60 * 1000; //hours * minutes * seconds * milliseconds. 5334 var j = $('.report-search-header:visible'); 5335 var jBegin = j.find('.Report_Begin_dt'); 5336 var jEnd = j.find('.Report_End_dt'); 5337 5338 if (jBegin.length === 0) { jBegin = j.find('.Begin_dt'); } 5339 if (jEnd.length === 0) { jEnd = j.find('.End_dt'); } 5340 5341 if (jBegin.length === 0) { jBegin = j.find('#report-start'); } 5342 if (jEnd.length === 0) { jEnd = j.find('#report-end'); } 5343 5344 var dt1 = _getSearchDate(jBegin); 5345 if (dt1 === null) { return; } 5346 var dt2 = _getSearchDate(jEnd); 5347 if (dt2 === null) { return; } 5348 5349 if (_conRptTemplate.isMonthRange(dt1, dt2)) { 5350 var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1); 5351 dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount)); 5352 dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount); 5353 } else if (dt1.getTime() == dt2.getTime()) { 5354 dt1 = new Date(dt1.setDate(dt1.getDate() + up)); 5355 dt2 = new Date(dt2.setDate(dt2.getDate() + up)); 5356 } else { 5357 var dayCount = up * Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + up * 1; 5358 5359 dt1 = new Date(dt1.setDate(dt1.getDate() + dayCount)); 5360 dt2 = new Date(dt2.setDate(dt2.getDate() + dayCount)); 5361 } 5362 5363 UI.setDateInput(jBegin, dt1); 5364 UI.setDateInput(jEnd, dt2); 5365 } 5366 5367 _conRptTemplate.validateDates = function(start, end, isBackgroun
5367dSearch) { 5368 if (!UTIL.isDate(start)) { 5369 if (!isBackgroundSearch) { 5370 GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('.Report_Begin_dt:visible'); }); 5371 } 5372 5373 return false; 5374 } else if (!UTIL.isDate(end)) { 5375 if (!isBackgroundSearch) { 5376 GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('.Report_End_dt:visible'); }); 5377 } 5378 5379 return false; 5380 } else if (new Date(start) > new Date(end)) { 5381 if (!isBackgroundSearch) { 5382 GLO.Popup.Warning(SA.Resource.BeginDateWarning2); 5383 } 5384 5385 return false; 5386 } 5387 5388 return true; 5389 } 5390 5391 function _getHash(jhead, jrpt, isBackgroundSearch, report, start, end) { 5392 var sfilter = GLO.Uri.query('sfilter'); //if (GLO.Info.isMobile() && UTIL.isEmpty(sfilter)) { sfilter = jrpt.find('#staff-filter').val(); } 5393 5394 if (report == 'sales-summary' && sfilter == -1) { 5395 GLO.Staff.Filter.removeFilter(); 5396 return null; 5397 } 5398 5399 /* 5400 if (GLO.Report.staffFilter !== null) { 5401 var sfilter = GLO.Report.staffFilter; 5402 GLO.Report.staffFilter = null; 5403 } else { 5404 var sfilter = GLO.Uri.query('sfilter'); 5405 } 5406 */ 5407 5408 var uhash = 'sfilter=' + sfilter + '&report=' + report + '&start=' + start + '&end=' + end; 5409 5410 var svcFilter = jhead.find('.Service_Filter').val(); 5411 if (!UTIL.isEmpty(svcFilter)) { uhash += '&servicefilter=' + svcFilter; } 5412 5413 var jInventoryFilter = jhead.find('.Inventory_Filter:visible'); 5414 5415 if (jInventoryFilter.length === 0) { jInventoryFilter = $('#report-product-history:visible .Inventory_Filter'); } 5416 5417 var inventoryFilter = jInventoryFilter.val(); 5418 5419 if (!UTIL.isEmpty(inventoryFilter)) { 5420 uhash += '&inventoryfilter=' + inventoryFilter; 5421 } else if (jhead.find('.Inventory_Filter:visible').hasClass('required')) { 5422 if (!isBackgroundSearch) { 5423 new GLO.Popup.Warning(SA.Resource.PleaseSelectAProduct, function() { jhead.find('.Inventory_Filter:visible').focus(); }); 5424 } 5425 5426 return null; 5427 } 5428 5429 var paymeth = jhead.find('.Payment_Method_cd:visible, .Payment_Method_cd.use').val(); 5430 if (!UTIL.isEmpty(paymeth)) { uhash += '&paymethod=' + paymeth; } 5431 5432 var jpopular = jrpt.parent().find('.popular-input:visible'); 5433 if (jpopular.length > 0) { 5434 if (jpopular.find('#radio-popular-most-services, #radio-popular-most-products').prop('checked')) { 5435 uhash += '&most_popular_nr=' + jpopular.find('.number-popular-most').val(); 5436 } else if (jpopular.find('#radio-popular-least-services, #radio-popular-least-products').prop('checked')) { 5437 uhash += '&least_popular_nr=' + jpopular.find('.number-popular-least').val(); 5438 } 5439 } 5440 5441 if (report === 'sales-history') { 5442 if ($('#hello-bar-gift-card').length > 0) { 5443 var gcid = GLO.Uri.query('giftcard'); 5444 5445 if (!UTIL.isEmpty(gcid)) { 5446 uhash += '&giftcard=' + gcid; 5447 } 5448 } 5449 5450 if (jhead.parent().find('#Include_Unpaid_Tickets_fl').prop('checked')) { 5451 uhash += '&include-unpaid=1'; 5452 } 5453 } 5454 5455 var jforecast = jhead.parent().find('.report-search-forecast #Include_Forecast_fl'); 5456 5457 if (jforecast.length === 1 && jforecast.prop('checked')) { 5458 uhash += '&forecast=1'; 5459 } 5460 5461 var processedBy = jhead.find('#Payment_Processed_By_id:visible').val(); 5462 5463 if (!UTIL.isEmpty(processedBy)) { 5464 uhash += '&processedby=' + processedBy; 5465 } 5466 5467 uhash += _getClientFilter(jhead); 5468 return uhash 5469 } 5470 5471 function _getClientFilter(jhead) { 5472 var jclient = jhead.find('#Client_Filter_id'); 5473 5474 if (jclient.length > 0 && !UTIL.isEmpty(jclient.val())) { 5475 var cid = jclient.attr('autoId'); 5476 5477 if (!UTIL.isEmpty(cid)) { 5478 return '&client=' + cid; 5479 } 5480 } 5481 5482 return ''; 5483 } 5484 5485 function _getReportUrl(start, end) { 5486 5487 } 5488 5489 _conRptTemplate.search = function(exportToExcel, jrpt) { 5490 if (jrpt !== undefined) {
5491 var isBackgroundSearch = true; 5492 } else { 5493 jrpt = $('.inventory-report:visible, .entire-report:visible'); 5494 var isBackgroundSearch = false; 5495 } 5496 5497 var jhead = jrpt.find('.report-search-header'); // var jhead = $('.report-search-header:visible'); 5498 var start = jhead.find('.Report_Begin_dt').val(); 5499 var end = jhead.find('.Report_End_dt').val(); 5500 5501 if (start === undefined) { 5502 var start = jhead.find('.Begin_dt').val(); 5503 var end = jhead.find('.End_dt').val(); 5504 } 5505 5506 if (!_conRptTemplate.validateDates(start, end, isBackgroundSearch)) { return; } 5507 5508 var report = jrpt.attr('id').replace('report-', ''); 5509 jrpt = jrpt.find('.inventory-report-container, .report-container'); 5510 5511 var uhash = _getHash(jhead, jrpt, isBackgroundSearch, report, start, end); 5512 if (UTIL.isEmpty(uhash)) { return; } 5513 5514 if (jhead.find('#Date_Range_Type_Pay_fl').prop('checked')) { 5515 uhash += '&ispaydate=1'; 5516 } 5517 5518 var url = GLO.Link.Page.Provider.Home + 'report/search?' + uhash; 5519 var pageUrl = document.location.origin + document.location.pathname + '?isfullpage=1&' + uhash.replace('report=sales-history&', ''); 5520 var searchBtn = null; 5521 var isIncludeDetail = (jrpt.find('#sales-summary-ticket-info:visible').length > 0); 5522 var reportPassword = $.trim($('#report-password-container #Report_Password_vc').val()); 5523 var jdPost = { "report_password_vc": reportPassword }; 5524 5525 if (exportToExcel) { 5526 var btnExport = jhead.parent().find('.btnExportToExcel'); 5527 GLO.UI.Form.beginProcessing(btnExport); 5528 5529 window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 2500); 5530 5531 url += '&ExportToExcel=1'; 5532 var childWindow = UI.openChildWindow(url, '', true); 5533 5534 return; 5535 } else { 5536 searchBtn = jhead.parent().find('.btnSearch'); 5537 GLO.UI.Form.beginProcessing(searchBtn); 5538 } 5539 5540 if (_isRefreshReportScreen(report, start, end, isIncludeDetail)) { 5541 return; 5542 } else if (isIncludeDetail) { 5543 url += '&include_detail_fl=1'; 5544 } 5545 5546 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdPost }) 5547 .success(function(data, textStatus, jqXHR) { 5548 if (searchBtn !== null) { GLO.UI.Form.resetProcessing(searchBtn); } 5549 5550 if (jrpt.find('#sales-summary-container').length > 0) { //#report-table-sales-summary 5551 var jdata = $('<div>' + data + '</div>'); 5552 data = GLO.Report.Sales.preInitSalesSummary(jdata, true); 5553 } 5554 5555 if ($(data).find('.no-results-report-role #Report_Password_vc').length) { 5556 jrpt.html(data); 5557 } else if (!UTIL.isEmpty(data)) { 5558 if (report === 'sales-summary') { 5559 data = GLO.Report.Sales.initSummaryChart(data); 5560 $('#ssh-payment-column').remove(); //cash drawer + incorrect payments are not re-freshed on search (+ issue because report loaded incorrect payments report container as well). 5561 } 5562 5563 jrpt.html(data); 5564 UI.initTableSorter( jrpt.find('table.tablesorter') ); 5565 GLO.Report.Sales.hideCommissionColumn(jrpt); 5566 _conRptTemplate.hideEmptyColumn(jrpt, 'column-profit'); 5567 GLO.Report.enableFullPageCheck(); 5568 5569 if (report == 'product-history') { 5570 GLO.Report.CellSummary.initReport(jrpt, true, true); 5571 } else if (report == 'payment-history') { 5572 GLO.Report.CreditCard.postSearch(jrpt, report); 5573 } else if (report == 'returns-exchanges') { 5574 GLO.Inventory.Reports.loadReturnReport(jrpt); 5575 } else if (report === 'sales-summary') { 5576 var jcontainer = jrpt.closest('#report-sales-summary'); 5577 5578 if (GLO.Report.Sales.postInitSalesSummary(jcontainer, true)) { 5579 var jbtns = $('#sales-summary-ticket-buttons'); 5580 5581 if (jbtns.find('#sales-average-ticket-on').hasClass('selected')) { 5582 GLO.Report.Sales.switchToTicketAverage(true); 5583 } 5584 5585 GLO.Report.Sales.createSummaryChart(); 5586 } 5587 } else if (report === 'popular-products' || report === 'popular-services' || report === 'sales-history') { 5588 GLO.Report.CellSummary.initReport(jrpt, true, true); 5589 GLO.Report.Sales.loadHistory(); 5590 5591 if (report === 'sales-history') { 5592 GLO.Report.Sales.initPaymentDetailReport(); 5593 } 5594 } 5595 5596 GLO.Report.initIcons(jrpt); 5597 } else { 5598 GLO.Popup.Info(SA.Resource.NoResultsFound); 5599 } 5600 5601 if (document.location.pathname.toLowerCase() === "/reports/saleshistory") { 5602 window.history.pushState('', 'Sales History', pageUrl); 5603 document.title = _getPageTitle(jhead, start, end); 5604 GLO.Report.Sales.loadPaymentDetailReport(); 5605 } 5606 5607 if (GLO.Info.isMobile(true) || GLO.Mobile.isTablet) { 5608 var jlinks = $('#sales-summary-ticket-info').find('a'); 5609 GLO.UI.initAnimateLink(jlinks, 4, GLO.UI.pinkify); 5610 } 5611 }) 5612 .error(function(jqXHR, textStatus, errorThrown) { 5613 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 5614 GLO.UI.Form.resetProcessing(searchBtn); 5615 }); 5616 } 5617 5618 function _isRefreshReportScreen(report, start, end, isIncludeDetail) { //= if just refreshing current day then refresh report page so report is in dashboard mode (looks up incorrect payments, cash drawer, + payment summary) 5619 if (report === 'sales-summary') {
5620 if (new Date(start).toGloDate() === new Date().toGloDate() && new Date(end).toGloDate() === new Date().toGloDate()) { 5621 var url = location.origin + location.pathname; 5622 var sfilter = GLO.Uri.url('sfilter'); 5623 var isIncludeForecast = $('#report-sales-summary #Include_Forecast_fl').prop('checked'); 5624 5625 if (isIncludeDetail) { 5626 url = GLO.Uri.addQueryKeyAndValue(url, 'include_detail_fl=1'); 5627 } 5628 5629 if (!isIncludeForecast) { 5630 url = GLO.Uri.addQueryKeyAndValue(url, 'forecast=0'); 5631 } 5632 5633 if (!UTIL.isEmpty(sfilter)) { 5634 url = GLO.Uri.addQueryKeyAndValue(url, 'sfilter=' + sfilter); 5635 } 5636 5637 setTimeout(function() { 5638 document.location = url; 5639 }, 100); 5640 5641 return true; 5642 } 5643 } 5644 5645 return false; 5646 } 5647 5648 _conRptTemplate.hideEmptyColumn = function(jcontainer, className, isInputText, hideClass, isNoteField) { 5649 var tds = jcontainer.find('tbody').find('.' + className); 5650 hideClass = UTIL.coalesceString(hideClass, 'hideX'); 5651 5652 if (_columnIsEmpty(tds, isInputText, isNoteField)) { 5653 jcontainer.find('.' + className).addClass(hideClass); 5654 return true; 5655 } else { 5656 return false; 5657 } 5658 } 5659 5660 function _columnIsEmpty(jcolumn, isInputText, isNoteField) { 5661 var total = 0; 5662 5663 for (var i=0; i < jcolumn.length; i++) { 5664 if (isInputText) { 5665 var text = jcolumn.eq(i).find(':text').val(); 5666 } else { 5667 var text = jcolumn.eq(i).text(); 5668 } 5669 5670 if (isNoteField) { 5671 if (!UTIL.isEmpty(text)) { 5672 return false; 5673 } 5674 } else { 5675 total += UTIL.coalesceMoney($.trim(text).replace('$', '').replace(' ', '')); 5676 } 5677 } 5678 5679 if (total == 0) { 5680 return true; 5681 } else { 5682 return false; 5683 } 5684 } 5685 5686 function _getPageTitle(jhead, start, end) { 5687 var jpaymeth = jhead.find('.Payment_Method_cd:visible, .Payment_Method_cd.use'); 5688 var title = 'Sales Detail: '; 5689 5690 if (!UTIL.isEmpty(jpaymeth.val())) { 5691 title = jpaymeth.find(':selected').text().replace(' Payments', '') + ' Payment Detail: '; 5692 } 5693 5694 if (UTIL.isDate(start) && UTIL.isDate(end)) { 5695 title += start + ' - ' + end; 5696 } 5697 5698 return title; 5699 } 5700 5701 _conRptTemplate.goToReport = function(event, url, sfilter, element) { 5702 if (event && event.target && element === undefined) { 5703 element = event.target; 5704 } 5705 5706 GLO.Uri.gotoReport(url, element, sfilter, null, null, event); 5707 return; 5708 5709 if (sfilter === 'h') { sfilter = GLO.Staff.Filter.getHouseStaff(); } 5710 if (!UTIL.isEmpty(sfilter)) { url = url + '&sfilter=' + sfilter; } 5711 5712 if (SA.Menu.isRequirePIN(url, null, event)) { 5713 return false; 5714 } 5715 5716 if (event.ctrlKey || event.altKey) { 5717 window.open(url); 5718 } else { 5719 document.location = url; 5720 } 5721 } 5722 5723 return _conRptTemplate; 5724})(); 5725 5726 5727GLO.Report.Template2 = (function() { 5728 function _conRptTemplate2() { } 5729 5730 _conRptTemplate2.init = function(reportName, start, end) { 5731 GLO.Staff.Filter.isReportPortal = true; 5732 5733 if (!GLO.Report.Sales.initStaffFilter()) { 5734 GLO.Report.Template.initStaffFilter(true); 5735 } 5736 5737 $('#header-icon-container').remove(); 5738 5739 var j = $('#report-main'); 5740 UI.initTableSorter2( j.find('table.tablesorter') ); 5741 5742 var jhead = $('.report-search-header'); 5743 GLO.Report.Template.initDateRange(jhead, true); 5744 5745 if (start) { jhead.find('#report-start').val(start); } 5746 if (end) { jhead.find('#report-end').val(end); } 5747 if (reportName) { GLO.Report.portalName = reportName; } 5748 5749 GLO.Report.setupFastClick(); 5750 } 5751 5752 _conRptTemplate2.getBlueThrobber = function(css) { 5753 var blueThrobber = '<img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="' + UTIL.cleanString(css) + '"/>'; 5754 return '<div id="imgThrobberContainer" style="height: 100%; width: 100%; text-align: center;">' + blueThrobber + '</div>'; 5755 } 5756 5757 function _displayBlueThrobber(appendTo) { 5758 $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove(); 5759 5760 var htmThrobber = _conRptTemplate2.getBlueThrobber('height: 60px; margin: auto; margin-top: 24px; margin-bottom: 12px;'); 5761 5762 if (appendTo) { 5763 appendTo.append(htmThrobber); 5764 } else { 5765 var j = $('.report-container'); 5766 var jNoResults = j.find('.no-results'); 5767 5768 if (jNoResults.length > 0) { 5769 jNoResults.replaceWith(htmThrobber); 5770 } else { 5771 j.append(htmThrobber); 5772 } 5773 } 5774 } 5775 5776 _conRptTemplate2.search = function(reportUrlName, isDisplayThrobber, fnOnSearchComplete) { 5777 var jrpt = $('#report-main'); 5778 var btnSearch = jrpt.find('.btnSearch'); 5779 var pageTitle = UTIL.directTagOnly($('#report-header-text'));
5780 var qstring = '', sids = GLO.Uri.url('sfilter'); 5781 var jGiftFilter = $('#gift-card-filter'); 5782 5783 if (UTIL.isEmpty(pageTitle)) { 5784 pageTitle = UTIL.directTagOnly($('#bd h1')); 5785 5786 if (UTIL.isEmpty(pageTitle)) { 5787 pageTitle = UTIL.directTagOnly($('#bd h1 > b')); 5788 } 5789 } 5790 5791 if (!UTIL.isEmpty(sids)) { 5792 qstring += '&sfilter=' + sids; 5793 var sfilter = $('#staff-filter').find('option:selected').text(); 5794 5795 if (UTIL.coalesce(sfilter, 'all').toLowerCase() != 'all') { 5796 pageTitle += ' ' + sfilter; 5797 } 5798 } 5799 5800 if (jGiftFilter.length === 1) { 5801 var ifilter = $.trim($('#gift-report-header-product-list #Gift_Product_List').val()); 5802 5803 if (jGiftFilter.find('#gift-option-all-with-balance').prop('checked')) { 5804 pageTitle = 'All Gift Cards with a Balance' 5805 qstring += '&allWithBalance=1&ifilter=' + ifilter; 5806 } else if (jGiftFilter.find('#gift-option-number').prop('checked')) { 5807 var gcnr = UTIL.replaceAll(jGiftFilter.find('#Gift_Number_vc').val(), '#', ''); 5808 5809 if (UTIL.isEmpty(gcnr)) { 5810 var msg = '<p>Please Enter Gift Card Number</p><p>or select <i>date range</i> or <i>all cards with a balance</i></p>'; 5811 GLO.Popup.Warning.open(msg, 'Enter Gift Card Number', function() { jGiftFilter.find('#Gift_Number_vc').focus(); }); 5812 return; 5813 } 5814 5815 pageTitle = 'Sale & Reloads for Gift Card: ' + gcnr; 5816 qstring += '&gcnr=' + gcnr; 5817 } else if (jGiftFilter.find('#gift-option-client-name').prop('checked')) { 5818 var jclient = jGiftFilter.find('#Gift_Client_Name_vc'); 5819 var cid = jclient.attr('autoId'); 5820 5821 if (!UTIL.isEmpty(cid)) { 5822 pageTitle = 'Gift Card: ' + jclient.val(); 5823 qstring += '&client=' + cid; 5824 } else { 5825 var htm = 'Please enter client name or select a different search filter option'; 5826 var fn = function() { $('#doc3 #Gift_Client_Name_vc').focus(); }; 5827 GLO.Popup.Warning.open(htm, 'Enter Client Name', fn); 5828 return; 5829 } 5830 } else { 5831 var start = jGiftFilter.find('#report-start:visible').val(); 5832 var end = jGiftFilter.find('#report-end:visible').val(); 5833 pageTitle += ': ' + start + ' - ' + end; 5834 qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&ifilter=' + ifilter; 5835 } 5836 } else { 5837 var start = jrpt.find('#report-start:visible').val(); 5838 var end = jrpt.find('#report-end:visible').val(); 5839 pageTitle = $.trim(pageTitle) + ': ' + start + ' - ' + end; 5840 qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true); 5841 } 5842 5843 if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); } 5844 5845 GLO.UI.Form.beginProcessing(btnSearch); 5846 5847 var url = GLO.Link.WebsiteDomain + 'report/' + reportUrlName + '?' + qstring; 5848 var jRptData = jrpt.find('.report-container'); 5849 var jd = {}; 5850 5851 if (!GLO.Report.hasReportPassword(jd)) { 5852 return; 5853 } else if (isDisplayThrobber) { 5854 _displayBlueThrobber(); 5855 } 5856 5857 $.ajax({ type: "POST", url: (url + '&ispartial=1'), "cache": false, "data": jd }) 5858 .success(function(data, textStatus, jqXHR) { 5859 GLO.UI.Form.resetProcessing(); 5860 5861 if (fnOnSearchComplete) { 5862 fnOnSearchComplete(jRptData, data); 5863 } else { 5864 jRptData.html(data); 5865 } 5866 5867 UI.initTableSorter2(jRptData.find('table.tablesorter')); 5868 5869 window.history.pushState("", pageTitle, url); 5870 5871 if (reportUrlName === 'GiftCardSales') { 5872 var isLookupDates = !$('#gift-option-all-with-balance').prop('checked'); 5873 GLO.Report.CellSummary.initReport(jRptData, isLookupDates, true); 5874 GLO.Report.initIcons(jRptData); 5875 UserPortal.Price.GiftCard.loadAfterSearch(); 5876 } 5877 }) 5878 .error(function(jqXHR, textStatus, errorThrown) { 5879 GLO.UI.Form.resetProcessing(); 5880 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 5881 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 5882 }); 5883 } 5884 5885 _conRptTemplate2.hideHeaderHelp = function(element) { 5886 var jhelp = $('#report-header-help');
5887 jhelp.find('.emphasize-only').slideUp(1400, function() { }); 5888 5889 setTimeout(function(){ 5890 $('#report-header-help').removeClass('emphasize'); 5891 jhelp.find('.de-emphasize-only').slideDown(600); 5892 }, 800); 5893 } 5894 5895 _conRptTemplate2.displayHeaderHelp = function(element) { 5896 var jhelp = $('#report-header-help'); 5897 5898 jhelp.find('.de-emphasize-only').slideUp(400, function() { 5899 5900 }); 5901 5902 jhelp.find('.emphasize-only').slideDown(1800, function() { 5903 jhelp.addClass('emphasize'); 5904 }); 5905 } 5906 5907 _conRptTemplate2.searchCompleteFade = function(jrpt, data) { 5908 jrpt.css({ "display": "none" }).html(data).slideDown(2400); 5909 var jhelp = $('#report-header-help'); 5910 5911 jhelp.find('.emphasize-only').slideUp(2400, function() { 5912 $('#report-header-help').find('.close-icon').removeClass('hide'); 5913 }); 5914 5915 setTimeout(function(){ 5916 $('#report-header-help').find('.de-emphasize-only').css({ "display": "none" }).slideDown(600); 5917 $('#report-header-help').removeClass('emphasize'); 5918 }, 1800); 5919 } 5920 5921 _conRptTemplate2.goToReport2 = function(url, event, isLookupDate, sfilter, element) { 5922 var reportName2 = '', reportName = 'Report'; 5923 var jheader = $('#simplemodal-container .report-header, .glopop .report-header'); 5924 5925 if (jheader.length === 0) { 5926 jheader = $('#bd .report-header'); 5927 } 5928 5929 var jheaderText = jheader.find('.report-header-text'); 5930 5931 if (jheaderText.length) { 5932 var reportName2 = UTIL.directTagOnly(jheaderText); 5933 } else { 5934 var reportName2 = UTIL.directTagOnly(jheader); 5935 } 5936 5937 if (reportName2.length) { 5938 reportName = reportName2.replace('Report').replace('report') + ' Report'; 5939 } 5940 5941 return _conRptTemplate2.goToReport(reportName, url, event, isLookupDate, sfilter, element); 5942 } 5943 _conRptTemplate2.goToReport = function(reportName, url, event, isLookupDate, sfilter, element) { 5944 if (event && event.target && element === undefined) { 5945 element = event.target; 5946 } 5947 5948 GLO.Uri.gotoReport(url, element, sfilter, isLookupDate, reportName, event); 5949 return; 5950 5951 if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; } 5952 if (sfilter === 'h') { sfilter = GLO.Staff.Filter.getHouseStaff(); } 5953 if (!UTIL.isEmpty(sfilter)) { url += '&sfilter=' + sfilter; } 5954 5955 if (isLookupDate) { 5956 var jhead = $('.report-search-header:visible'); 5957 5958 if (jhead.length) { 5959 var start = jhead.find('.Report_Begin_dt').val(); 5960 var end = jhead.find('.Report_End_dt').val(); 5961 5962 if (UTIL.isDate(start)) { url += '&start=' + new Date(start).toGloDate(); } 5963 if (UTIL.isDate(end)) { url += '&end=' + new Date(end).toGloDate(); } 5964 } 5965 } 5966 5967 if (SA.Menu.isRequirePIN(url, null, event)) { 5968 return false; 5969 } 5970 5971 GLO.Popup.Processing.open('Loading ' + UTIL.cleanString(reportName) + '...', reportName); 5972 url = GLO.Link.WebsiteDomain + url; 5973 5974 setTimeout(function() { 5975 if (event && (event.ctrlKey || event.altKey)) { 5976 window.open(url); 5977 } else { 5978 document.location = url; 5979 } 5980 }, 100) 5981 } 5982 5983 return _conRptTemplate2; 5984})(); 5985 5986 5987GLO.Report.ProductActivity = (function() { 5988 function _conProductActivity() { } 5989 _conProductActivity.isProductSummaryReport = false; 5990 5991 _conProductActivity.init = function() { 5992 var jfilter = $('#report-product-activity-filter'); 5993 var jco = jfilter.find('#report-product-activity-company'); 5994 var jhead = $('.report-search-header .report-search-header-table'); 5995 5996 jfilter.find('.Report_Begin_dt').attr('id', 'Begin_dt'); 5997 jfilter.find('.Report_End_dt').attr('id', 'End_dt'); 5998 5999 var filter = UTIL.coalesce(GLO.Uri.query('inventoryfilter'), GLO.Uri.query('inventory-filter')); 6000 jco.find('#Filter_Company').val(filter); 6001 6002 jhead.find('#rpt-filter-pay-method, .report-list-line').remove(); 6003 jhead.find('td:first').append(jco); 6004 6005 $('.report-inventory-header-search').attr('onclick', 'GLO.Report.ProductActivity.search()'); 6006
6007 GLO.Report.Template.init(); 6008 _initData(filter); 6009 6010 jfilter.css({ "visibility": "" }); 6011 GLO.Report.enableFullPageCheck(); 6012 6013 _conProductActivity.isProductSummaryReport = true; 6014 UserPortal.Lookup.initMonitorQRScan(); 6015 } 6016 6017 function _initData(inventoryFilter) { 6018 var tbl = $('#report-product-activity'); 6019 6020 tbl.find('td.column-brand-name').click(GLO.Report.ProductActivity.searchRow); 6021 tbl.find('td.column-product-line-name').click(GLO.Report.ProductActivity.searchRow); 6022 //tbl.find('td.column-product-name').click(GLO.Report.ProductActivity.gotoProductHistory); 6023 6024 var jh2 = $('#report-inventory-h2'); 6025 6026 _addNoBrandOption(tbl); 6027 6028 if (UTIL.isEmpty(inventoryFilter)) { 6029 jh2.find('.h2text').text('Product Activity Summary'); 6030 jh2.find('#report-activity-h2-arrow').addClass('hide'); 6031 6032 tbl.find('#product-activity-detail-help').addClass('hide'); 6033 tbl.find('#product-activity-summary-help').removeClass('hide'); 6034 } else { 6035 jh2.find('.h2text').text('Product Activity Detail'); 6036 jh2.find('#report-activity-h2-arrow').removeClass('hide'); 6037 6038 var filter = '<i style="color: rgb(80, 180, 200);">' + $.trim(tbl.find('#Filter_Company option:selected').text()) + '</i>'; 6039 6040 tbl.find('#product-activity-detail-help').removeClass('hide').find('b').html('for each ' + filter + ' product'); 6041 tbl.find('#product-activity-summary-help').addClass('hide'); 6042 } 6043 6044 GLO.Report.CellSummary.initReport(tbl, true, true); 6045 GLO.Report.initIcons(tbl); 6046 } 6047 6048 function _addNoBrandOption(tbl) { 6049 if (tbl.find('tr[vendor_id=1]').length > 0) { 6050 var jco = $('#report-product-activity-company #Filter_Company'); 6051 6052 if (jco.find('option[value="v1"]').length === 0) { 6053 jco.append('<option class="v-option" value="v1">( No Brand )</option>'); 6054 } 6055 } 6056 } 6057 6058 _conProductActivity.gotoProductHistory = function() { 6059 var td = $(this); 6060 var tr = td.closest('tr'); 6061 var iid = td.attr('inventory_id'); 6062 var name = UTIL.coalesce(td.attr('title'), td.find('a').text()); 6063 6064 var jrpt = $('#report-product-activity'); 6065 6066 var start = new Date(jrpt.find('.Report_Begin_dt').val()).toGloDate(true); 6067 var end = new Date(jrpt.find('.Report_End_dt').val()).toGloDate(true); 6068 6069 var htm = 'Loading ' + name + ' Product History...'; 6070 new GLO.Popup.Processing(htm); 6071 6072 setTimeout(function() { 6073 document.location = document.location.protocol + '//' + document.location.host + '/reports/inventory#tab=product-history&id=' + iid + '&start=' + start + '&end=' + end; 6074 }, 100); 6075 } 6076 6077 function _getHash(jhead, start, end, co) { 6078 var uhash = 'start=' + start + '&end=' + end + '&inventoryfilter=' + UTIL.cleanString(co); 6079 6080 /* 6081 var ifilter = jhead.find('.Inventory_Filter:visible').val(); 6082 6083 if (!UTIL.isEmpty(ifilter)) { 6084 uhash += '&inventoryfilter=' + ifilter; 6085 } 6086 */ 6087 6088 return uhash; 6089 } 6090 6091 _conProductActivity.gotoTopLevel = function() { 6092 var j = $('#report-product-activity'); 6093 var start = j.find('.Report_Begin_dt').val(); 6094 var end = j.find('.Report_End_dt').val(); 6095 6096 var jparent = j.parent(); 6097 UI.displayProcessingLayer(jparent); 6098 6099 setTimeout(function() { 6100 document.location = document.location.protocol + '//' + document.location.host + '/reports/ProductActivity?start=' + start + '&end=' + end; 6101 }, 100); 6102 } 6103 6104 _conProductActivity.searchRow = function() { 6105 var jrpt = $('#report-product-activity'); 6106 var jfilter = jrpt.find('.report-search-header-table #Filter_Company'); 6107 var td = $(this); 6108 var tr = td.closest('tr'); 6109 6110 if (UTIL.isEmpty(td.find('a').text())) { return; } 6111 6112 if (td.hasClass('column-brand-name')) { 6113 jfilter.val('v' + tr.attr('vendor_id')); 6114 } else if (td.hasClass('column-product-line-name')) { 6115 jfilter.val('p' + tr.attr('product_line_id')); 6116 } 6117 6118 jrpt.find('.btnSearch:visible > a').click(); 6119 } 6120 6121 _conProductActivity.search = function() { 6122 var jrpt = $('.inventory-report'); 6123 var jhead = jrpt.find('.report-search-header'); // var jhead = $('.report-search-header:visible'); 6124 var start = jhead.find('.Report_Begin_dt').val(); 6125 var end = jhead.find('.Report_End_dt').val(); 6126 var co = jhead.find('#Filter_Company').val();
6127 var isBackgroundSearch = false, jd = {}; 6128 6129 if (!GLO.Report.Template.validateDates(start, end, isBackgroundSearch)) { 6130 return; 6131 } else if (!GLO.Report.hasReportPassword(jd)) { 6132 return; 6133 } 6134 6135 var uhash = _getHash(jhead, start, end, co); 6136 var jrpt = jrpt.find('.inventory-report-container'); 6137 6138 var url = GLO.Link.Page.Provider.Home + 'report/ProductActivity?ispartial=1&' + uhash; 6139 var pageUrl = document.location.origin + document.location.pathname + '?' + uhash; 6140 6141 var searchBtn = searchBtn = jhead.parent().find('.btnSearch'); 6142 GLO.UI.Form.beginProcessing(searchBtn); 6143 6144 var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd }) 6145 .success(function(data, textStatus, jqXHR) { 6146 if (searchBtn !== null) { GLO.UI.Form.resetProcessing(searchBtn); } 6147 6148 if (!UTIL.isEmpty(data)) { 6149 jrpt.html(data); 6150 UI.initTableSorter( jrpt.find('table.tablesorter') ); 6151 _initData(co); 6152 } else { 6153 GLO.Popup.Info(SA.Resource.NoResultsFound); 6154 } 6155 6156 var htitle = 'Product Activity ' + new Date(start).toSADate(true) + ' - ' + new Date(end).toSADate(true); 6157 window.history.pushState('', htitle, pageUrl); 6158 }) 6159 .error(function(jqXHR, textStatus, errorThrown) { 6160 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 6161 GLO.UI.Form.resetProcessing(searchBtn); 6162 }); 6163 } 6164 6165 _conProductActivity.openReportHelp = function() { 6166 var msg0 = '<p>Dashboard of activity for each product, product line, and brand as well as offers insight into your product sales profitability</p>'; 6167 var h = '<h3 style="margin-top: 24px; margin-bottom: 0; line-height: 1.8; border-radius: 28px; font-size: 131%; background-color: rgba(80, 200, 240,1);">'; 6168 6169 var h1 = h + 'Product Activity Summary</h3>'; 6170 var msg1 = '<p>The first report when the screen loads is the <i>Product Activity Summary report</i> which is a summary of activity for each brand / product line</p>'; 6171 6172 var h2 = h + 'Product Activity Detail</h3>'; 6173 var msg2 = '<p>Click a brand or product line <small>(any underlined value in the report)</small> or select a brand or product line <small>(from the drop down in the report filter)</small> to go to the <i>Product Activity Detail report</i> which displays the activity for each product in that brand / product line over the selected date range</p>'; 6174 6175 var h3 = h + 'Staff Access</h3>'; 6176 var msg3a = '<p>Managers and Admins have full access to this report</p>'; 6177 var msg3b = '<p>Receptionists can only see sales information <small>(not cost or profitability information)</small> specifically receptionists cannot see the last five columns (Order Cost, Total Cost, Profit, Gross Margin, and Profit Margin)</p>'; 6178 var msg3c = '<p>Other staff roles do not have access to this report</p>'; 6179 6180 var htm = '<div>' + msg0 + h1 + msg1 + h2 + msg2 + h3 + msg3a + msg3b + msg3c + '</div>'; 6181 var jpop = GLO.Popup.Info.open(htm, 'Inventory Activity Report').getPopup(); 6182 6183 jpop.attr('id', 'pop-help-inventory-activity-report').css({ "background-color": "rgb(240, 255, 255)" }); 6184 } 6185 6186 return _conProductActivity; 6187})(); 6188 6189GLO.Report.Sales = (function() { 6190 function _conRptSales() { } 6191 6192 _conRptSales.currentTab = 1; 6193 _conRptSales.MAX_TAB = 2; 6194 6195 _conRptSales.init = function() { 6196 var jsummary = $('#report-sales-summary'); 6197 if (jsummary.find('#report-table-sales-summary').length === 0) { $('#sales-summary-ticket-buttons').addClass('hide'); } 6198 6199 _conRptSales.preInitSalesSummary(jsummary); 6200 _conRptSales.postInitSalesSummary(jsummary); 6201 6202 var initTab = GLO.Report.Template.init(); //GLO.Report.setupFastClick(); 6203 6204 if (!UTIL.isEmpty(initTab)) { 6205 initTab = initTab.toLowerCase(); 6206 6207 if (initTab === 'sales-summary' || initTab == '1') { 6208 initTab = 1; 6209 } else if (initTab === 'sales-history' || initTab == '2') { 6210 initTab = 2; 6211 } 6212 } else { 6213 initTab = _conRptSales.currentTab; 6214 } 6215 6216 _conRptSales.goToTab(1); //must display summary to create chart. 6217 //_conRptSales.goToTab(initTab); 6218 _preInitSalesHistory(initTab); 6219 _initProductFilter(); 6220 6221 _initSalesSummary(); 6222 _initSalesHistory(true); 6223 //_initMostPopular(true); 6224 //_initMostPopular(false); 6225 GLO.Report.Sales.createSummaryChart(); 6226 6227 $('#report-sales-trends').find('#rpt-filter-pay-method').remove(); 6228 $('#report-shipment-history').find('#rpt-filter-pay-method').remove(); 6229 $('#report-audit-history').find('#rpt-filter-pay-method').remove(); 6230 6231 GLO.Report.portalName = 'sales'; 6232 _loadIncorrectPayments(); 6233 _conRptSales.loadHistory(); 6234 } 6235 6236 _conRptSales.loadPaymentDetailReport = function() { 6237 if (innerWidth < 500) { return; } 6238 6239 var jtbl = $('#report-payment-history'); 6240 var trs = jtbl.find('tbody tr'); 6241 var hasGiftCard = false; 6242 6243 for (var i=0; i < trs.length; i++) { 6244 if (!UTIL.isEmpty(trs.find('.report-gift-card').text())) { 6245 hasGiftCard = true; 6246 break; 6247 } 6248 } 6249 6250 if (hasGiftCard) { 6251 jtbl.find('.report-gift-card').removeClass('hide'); 6252 } 6253 } 6254 6255 function _loadIncorrectPayments(days) { 6256 if ($('#ssh-payment-incorrect').length === 0) { return; } 6257
6258 days = UTIL.coalesceInt(days, 7); 6259 var uri = GLO.Link.WebsiteDomain + 'reports/IncorrectPayment?ispartial=1&rows=5&days=' + days; 6260 var sfilter = GLO.Uri.query('sfilter'); 6261 6262 if (!UTIL.isEmpty(sfilter)) { 6263 uri += '&sfilter=' + sfilter; 6264 } 6265 6266 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false }) 6267 .success(function(data, textStatus, jqXHR) { 6268 var j = $('#ssh-payment-incorrect'); 6269 6270 if ($(data).find('tbody > tr').length) { 6271 j.removeClass('hideX'); 6272 } else { 6273 j.addClass('hideX'); 6274 return; 6275 } 6276 6277 j.find('img').remove(); 6278 j.append( $(data).html() ); 6279 6280 var tbl = j.find('.tablesorter'); 6281 if (tbl.length > 0) { UI.initTableSorter(tbl); } 6282 }) 6283 .error(function(jqXHR, textStatus, errorThrown) { 6284 $('#ssh-payment-incorrect').addClass('hideX'); 6285 }); 6286 } 6287 6288 _conRptSales.initHistory = function(giftCardId, giftCardNumber, giftCardBalance) { 6289 GLO.Report.Template.init(); 6290 6291 _preInitSalesHistory(2); 6292 _initProductFilter(); 6293 _conRptSales.goToTab(2); 6294 _initSalesHistory(false); 6295 6296 GLO.Report.portalName = 'sales'; 6297 GLO.Report.setupFastClick(); 6298 GLO.Report.Sales.initStaffFilter(); 6299 6300 _initSetHistoryHeader(); 6301 _initGiftCard(giftCardId, giftCardNumber, giftCardBalance); 6302 _initSalesHistoryUrl(); 6303 _conRptSales.loadHistory(); 6304 6305 _initPaymentProcessedBy(); 6306 _conRptSales.initPaymentDetailReport(); 6307 } 6308 _conRptSales.initPaymentDetailReport = function() { 6309 if ($('#doc3').hasClass('is-payment-report')) { 6310 var jheadDT = $('#report-search-header-date-range'); 6311 6312 /* if (innerWidth > 800) { 6313 jheadDT.find('label[for="Begin_dt"]').text('Payment Date Range'); 6314 jheadDT.find('label[for="End_dt"]').text('-'); 6315 } */ 6316 6317 /* if (innerWidth > 420) { 6318 var title = 'Filter the payments by the payment date', small = 'To filter by appointment date use a Sales Report'; 6319 var icon = '<b class="question-icon" onclick="GLO.UI.openHelp(this)" header="Filter by Payment Date" title="' + title + '" htm_small="' + small + '" alt="" alt_html="">?</b>'; 6320 jheadDT.find('td:last-child').append(icon); 6321 } */ 6322 6323 var jrpt = $('#report-payment-history'); 6324 GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-service', null, null, true); 6325 GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-product', null, null, true); 6326 GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-note', null, null, true); 6327 GLO.Report.Template.hideEmptyColumn(jrpt, 'report-gift-card', null, null, true); 6328 GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-process-by', null, null, true); 6329 } 6330 } 6331 function _initPaymentProcessedBy() { 6332 if (GLO.Info.roleType > 209) { 6333 var htmOptions = $('#staff-filter #staff-filter-s').html(); 6334 var label = '<label for="Payment_Processed_By_id">Payment Processed By</label>'; 6335 var select = '<select id="Payment_Processed_By_id"> <option value="">All</option>' + htmOptions + '</select>'; 6336 var cssHide = ''; 6337 var jFilterPayMeth = $('#rpt-filter-pay-method'); 6338 6339 if (UTIL.isEmpty(jFilterPayMeth.find('.Payment_Method_cd').val())) { 6340 cssHide = 'hide'; 6341 } 6342 6343 if ($('#report-sales-history .is-pay-history-report').length > 0) { 6344 jFilterPayMeth.append('<span id="filter-pay-processed-by" class="' + cssHide + '">' + label + select + '</span>'); 6345 } 6346 } 6347 } 6348 function _initSalesHistoryUrl() { 6349 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 6350 var staffId = GLO.Uri.url('staff'); 6351 6352 if (open === 'print') { 6353 GLO.Report.Sales.printScreenInit(); 6354 } else if (open === 'print-staff') {
6355 if (!UTIL.isEmpty(staffId)) { 6356 GLO.Report.Sales.printByStaff2(staffId); 6357 } else { 6358 GLO.Report.Sales.printByStaff(); 6359 } 6360 } 6361 } 6362 function _initProductFilter() { 6363 var jp = $('#report-sales-history .Inventory_Filter'); 6364 var jno = jp.find('option[value="-1"]'); 6365 var isIncludeUnpaid = $.cookies.get('sales-detail-is-include-unpaid'); 6366 6367 if (GLO.Provider.isValidGoldPackage()) { 6368 if (GLO.Data.provider.MembershipList && GLO.Data.provider.MembershipList.length > 0) { 6369 jno.after('<option value="m" title="Sales of memberships">Memberships</option>'); 6370 } 6371 6372 jno.after('<option value="g" title="Sales of gift cards">Gift Card</option>'); 6373 jno.after('<option value="b" title="Only products available for internal users (like backbar products)">Internal Only (backbar)</option>'); 6374 jno.after('<option value="r" title="Only products available for retail sale">Retail Only</option>'); 6375 } 6376 6377 if (UTIL.parseBool(isIncludeUnpaid) || UTIL.isEmpty(isIncludeUnpaid)) { 6378 $('#report-sales-history #Include_Unpaid_Tickets_fl').prop('checked', true); 6379 } 6380 } 6381 6382 function _initGiftCard(giftCardId, giftCardNumber, giftCardBalance) { 6383 var pmeth = $('#report-sales-history .report-search-header .Payment_Method_cd').val(); 6384 6385 if (pmeth == 0 || pmeth == 20) { 6386 _initGiftCardHelloBar(giftCardId, giftCardNumber, giftCardBalance); 6387 _conRptSales.loadPaymentDetailReport(); 6388 } 6389 } 6390 6391 function _initGiftCardHelloBar(giftCardId, giftCardNumber, giftCardBalance) { 6392 if (UTIL.isEmpty(giftCardId)) { return; } 6393 //var gcnr = GLO.Uri.query('giftcard'); 6394 if (UTIL.isEmpty(giftCardNumber)) { return; } 6395 6396 var onclick = 'UserPortal.Price.GiftCard.openEdit(' + giftCardId + ', \'' + giftCardNumber + '\', ' + UTIL.coalesceMoney(giftCardBalance) + ')'; 6397 var label = '<b style="white-space: nowrap; padding-right: 2px;">Payments with Gift Card #' + giftCardNumber + '</b>'; 6398 6399 if (giftCardBalance > 0) { 6400 label += '<b class="hell-bar-gift-balance"> Balance: ' + UTIL.displayMoney(giftCardBalance) + '</b>'; 6401 } 6402 6403 var helloBar = '<div id="hello-bar-gift-card" class="hello-bar-container" style="display:none;"> <p style="padding-top: 2px;">' 6404 + '<span class="hello-bar-label" onclick="' + onclick + '" style="position: relative; top: inherit; left: inherit;">' + label + '</span>' 6405 + '<span class="hello-bar-close"> <a onclick="GLO.Report.Sales.removeGiftCardHelloBar(this, event)"> ✖</a> </span>' 6406 + '</p> </div>'; 6407 6408 GLO.Info.displayGiftCardHelloBar(helloBar); 6409 } 6410 6411 _conRptSales.removeGiftCardHelloBar = function(xbutton, event) { 6412 GLO.Uri.removeQueryKey('giftcard'); 6413 $('#hello-bar-generic, #hello-bar-gift-card').remove(); 6414 $('#report-sales-history .report-search-header .btnSearch > a').click(); 6415 $('body').removeClass('phone-has-hello-bar'); 6416 } 6417 6418 function _getSalesReportLink(url, label, isLeft, sfilter, elementClass) { 6419 var onclick = 'GLO.Uri.gotoReport(\'' + url + '\', this, ' + sfilter + ', true)'; //(uri, element, sfilter, isLookupDate, reportName, event2, isSpinButton) 6420 var cssClass = 'quietest ' + $.trim(elementClass); 6421 6422 if (isLeft) { 6423 cssClass += ' quietest-left'; 6424 } else { 6425 cssClass += ' quietest-right'; 6426 } 6427 6428 return '<a class="' + cssClass + '" onclick="' + onclick + '">' + label + '</a>'; 6429 } 6430 6431 function _initSetHistoryHeader() { 6432 var jPayMeth = $('#rpt-filter-pay-method .Payment_Method_cd').change(GLO.Report.Sales.changePaymentMethod); 6433 var jlanguage = $('#language-icon-container, #language-icons').remove(); 6434 6435 if (GLO.Info.roleType > 200) { 6436 var aPayDetail = _getSalesReportLink('reports/saleshistory?isfullpage=1&paymethod=0', 'Payment Detail', true, true, 'display-on-sales-detail'); 6437 var aSalesSummary = _getSalesReportLink('reports/sales#tab=sales-summary', 'Sales Summary', false, true, 'display-on-sales-detail');
6438 var aSalesDetail = _getSalesReportLink('reports/saleshistory?isfullpage=1', 'Sales Detail', true, true, 'display-on-pay-detail'); 6439 var aPaySummary = _getSalesReportLink('reports/PaymentSummary', 'Payment Summary', false, false, 'display-on-pay-detail'); 6440 } else { 6441 var aPayDetail = '', aSalesSummary = '', aSalesDetail = '', aPaySummary = ''; 6442 } 6443 6444 var htext = '<b id="detail-report-header-text"></b>'; 6445 var h2 = '<h2 id="detail-report-header" class="report-header">' + aPayDetail + aSalesDetail + htext + aSalesSummary + aPaySummary + jlanguage.html() + '</h2>'; 6446 6447 $('.shadow0').css({ "padding-top": 0, "border-radius": "20px" }); 6448 var j = $('.shadow-content0').css({ "padding-top": 0, "border-radius": "20px" }); 6449 j.prepend(h2); 6450 6451 if (jPayMeth.length) { 6452 jPayMeth.change(); 6453 } else { 6454 _conRptSales.changePaymentMethod(); 6455 } 6456 6457 if (UTIL.isEmpty(jPayMeth.val())) { //= hide on 'Sales Detail' full page report 6458 jPayMeth.addClass('hide'); 6459 } 6460 } 6461 6462 _conRptSales.loadHistory = function() { 6463 var jrpt = $('#report-sales-history .tablesorter'); 6464 var totalFees = UTIL.coalesceMoney($.trim(jrpt.find('tfoot .column-staff-fee').text()).replace('$', '')); 6465 var totalCommission = UTIL.coalesceMoney($.trim(jrpt.find('tfoot .commission-cell').text()).replace('$', '')); 6466 6467 if (totalFees > 0) { 6468 jrpt.find('.column-staff-fee').removeClass('hide'); 6469 } 6470 6471 if (totalCommission > 0) { 6472 jrpt.find('.commission-cell').removeClass('hide'); 6473 } 6474 6475 GLO.Report.hideEmptyColumn(jrpt, 'column-due-date'); 6476 var isHideDiscount = GLO.Report.hideEmptyColumn(jrpt, 'column-discount'); 6477 var isHideAddOnFee = GLO.Report.hideEmptyColumn(jrpt, 'column-add-on'); 6478 GLO.Report.hideEmptyColumn(jrpt, 'column-staff-fee'); 6479 6480 if (isHideDiscount && isHideAddOnFee) { 6481 _hideTotalColumn(jrpt); 6482 } else if (GLO.Info.roleType > 219) { 6483 _displayCommissionSplitNotExpected(jrpt); 6484 } 6485 } 6486 6487 function _displayCommissionSplitNotExpected(jrpt) { 6488 var trs = jrpt.find('tbody tr'); 6489 6490 for (var i=0; i < trs.length; i++) { 6491 var tr = trs.eq(i); 6492 var splitCode = tr.attr('commission_split_cd'), splitAmount = tr.attr('commission_split_mn'), splitAdjust = tr.attr('commission_adjust_mn'), splitPercent = tr.attr('commission_split_pct'); 6493 var discountCount = UTIL.coalesceInt(tr.attr('discount_count_sr'), 0), feeCount = UTIL.coalesceInt(tr.attr('add_on_fee_count_sr'), 0); 6494 var hasCustomDiscountSplit = UserPortal.Price.Discount.hasCommissionSplitByDiscountType; 6495 var hasCustomFeeSplit = UserPortal.Price.Discount.hasCommissionSplitByFeeType; 6496 6497 var isDiffDiscountSplit = (splitCode != GLO.Data.provider.commission_split_discount_cd); 6498 var isDiffAddOnFeeSplit = (splitCode != GLO.Data.provider.commission_split_fee_cd); 6499 6500 if (discountCount + feeCount > 0) { 6501 if (discountCount > 0 && feeCount > 0) { 6502 if (!hasCustomFeeSplit && splitCode == 2) { 6503 _displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent); 6504 } else if (!hasCustomDiscountSplit && !hasCustomFeeSplit) { 6505 //for now only process discounts 6506 } 6507 } else if (isDiffDiscountSplit && (discountCount == 1 || !hasCustomDiscountSplit)) { 6508 _displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent); 6509 } else if (isDiffAddOnFeeSplit && (feeCount == 1 || !hasCustomFeeSplit)) { 6510 //for now only process discounts 6511 } 6512 } 6513 } 6514 } 6515 function _displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent) { 6516 if (UserPortal.Price.Discount.hasCommissionSplitByDiscountType) { return; } 6517 6518 var price = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.column-price-only').text())); 6519 var discount = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.column-discount').text())); 6520 var fee = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.add-on-discount').text())); 6521 var isExpected = false, title = null; 6522 var hasCustomDiscountSplit = UserPortal.Price.Discount.hasCommissionSplitByDiscountType; 6523 6524 if (splitCode == 0) { //Proportional 6525 if (!UTIL.isDollarDiff( UTIL.coalesceMoney(splitAmount), UTIL.coalesceMoney(fee) ) && UTIL.coalesceMoney(splitAdjust, splitPercent) == 0) { 6526 isExpected = true; 6527 } else { 6528 title = 'Discount commission split expected to be proportional, but is calculated differently'; 6529 } 6530 } else if (splitCode == 1) { //Staff 6531 if ( !UTIL.isDollarDiff(splitAdjust, discount - fee) && UTIL.coalesceMoney(splitAmount) == 0) { 6532 isExpected = true; 6533 } else { 6534 title = 'Discount commission split expected to be take from staff commission, but is calculated differently'; 6535 } 6536 } else if (splitCode == 2) { //Business 6537 if (UTIL.coalesceMoney(splitAdjust) == 0 && !UTIL.isDollarDiff(splitAmount, discount)) { 6538 isExpected = true; 6539 } else if (!hasCustomDiscountSplit && GLO.Data.provider.commission_split_discount_cd == 2 && UTIL.isEmpty(splitAdjust) && UTIL.isEmpty(splitAmount) 6540 && (fee == 0 || GLO.Data.provider.commission_split_fee_cd == 2)) { 6541 isExpected = true; 6542 } else { 6543 title = 'Discount commission split expected to be taken out of the business, but is calculated differently'; 6544 } 6545 } else if (splitCode == 3) { //Custom 6546 if (!UTIL.isDollarDiff(splitAdjust, UTIL.coalesceMoney(splitPercent) * UTIL.coalesceMoney(discount + fee))) { 6547 isExpected = true; 6548 } else { 6549 title = 'Discount commission split expected to be ' + splitPercent + '% of the discount, but is calculated differently'; 6550 } 6551 } 6552 6553 if (title) {
6554 var tdDiscount = tr.find('td.column-discount'); 6555 var currentTitle = tdDiscount.attr('title'); 6556 6557 tdDiscount.attr('title', currentTitle + ' | ' + title); 6558 tr.addClass('discount-commission-split-unexpected'); 6559 } 6560 } 6561 6562 function _hideTotalColumn(jrpt) { //= hide Total column if always the same as the Price column 6563 var tdTotal = jrpt.find('tbody td.column-price-only'); 6564 var tdPrice = jrpt.find('tbody td.column-price'); 6565 6566 for (var i=0; i < tdTotal.length; i++) { 6567 if (tdTotal.eq(i).text() != tdPrice.eq(i).text()) { 6568 return false; 6569 } 6570 } 6571 6572 jrpt.find('.column-price-only').addClass('hideX'); 6573 return true; 6574 } 6575 6576 function _removeCommissionStaff() { //= on Payment Detail report remove individual commission staff members, because payments go to the house account not each house staff 6577 var jf = $('#hd #staff-filter'); 6578 var jfilter = jf.find('#staff-filter-s').find('option'); 6579 var jstaff = UserPortal.getStaffDropDown(); 6580 var hasHouseStaff = false; 6581 6582 for (var i=0; i < jfilter.length; i++) { 6583 var sid = jfilter.eq(i).val(); 6584 var mtype = UTIL.coalesceInt(jstaff.find('option[value="' + sid + '"]').attr('merchant_type_cd'), 99); 6585 6586 if (mtype < 20) { 6587 jfilter.eq(i).remove(); 6588 hasHouseStaff = true; 6589 } 6590 } 6591 6592 if (hasHouseStaff || GLO.Data.provider.merchant_type_cd < 10) { 6593 jf.find('#staff-filter-custom').remove(); 6594 jf.find('#staff-filter-sg').remove(); 6595 } 6596 } 6597 6598 _conRptSales.initPopular = function() { 6599 _conRptSales.MAX_TAB = 2; 6600 var initTab = GLO.Report.Template.init(); //GLO.Report.setupFastClick(); 6601 6602 if (!UTIL.isEmpty(initTab)) { 6603 initTab = initTab.toLowerCase(); 6604 6605 if (initTab === 'popular-services' || initTab == '1') { 6606 initTab = 1; 6607 } else if (initTab === 'popular-products' || initTab == '2') { 6608 initTab = 2; 6609 } 6610 } else { 6611 initTab = _conRptSales.currentTab; 6612 } 6613 6614 _conRptSales.goToPopularTab(initTab); 6615 _conRptSales.hideCommissionColumn(); 6616 6617 _initMostPopular(true); 6618 _initMostPopular(false); 6619 6620 GLO.Report.portalName = 'popular'; 6621 $('#header-navigation-links').find('#report-popular-service > a, #report-popular-product > a').addClass('ignore-animate'); 6622 GLO.Report.enableFullPageCheck(); 6623 } 6624 6625 function _preInitSalesHistory(initTab) { 6626 var pmeth = GLO.Uri.hash('pay-method'); 6627 var jrpt = $('#report-sales-history'); 6628 6629 if (UTIL.isEmpty(pmeth)) { 6630 pmeth = UTIL.coalesce(GLO.Uri.query('pay-method'), GLO.Uri.query('paymethod')); 6631 } 6632 6633 if (!UTIL.isEmpty(pmeth)) { 6634 jrpt.find('.Payment_Method_cd').val(pmeth); 6635 //if (jrpt.find('.payment-history').length === 0) { setTimeout(function() { $('#report-sales-history .report-inventory-header-search').click(); }, 1500); } 6636 } 6637 } 6638 6639 function _initSalesHistory(isSalesSummary) { 6640 var jrpt = $('#report-sales-history'); 6641 jrpt.find('.report-inventory-search-prev, .report-inventory-search-next').css({ "margin-top": "10px" }); 6642 jrpt.find('.report-inventory-search-prev img, .report-inventory-search-next img').css({ "height": "70px" }); 6643 6644 var svc = GLO.Uri.query('servicefilter'); 6645 var product = GLO.Uri.query('inventoryfilter'); 6646 var sfilter = GLO.Uri.query('sfilter'); 6647 6648 if (!UTIL.isEmpty(svc)) { 6649 jrpt.find('.Service_Filter').val(svc); 6650 } else if (UTIL.coalesceInt(GLO.Info.getStaffRole(), 0) > 200 && GLO.Report.Sales.isCommissionBusiness == 0) { 6651 jrpt.find('.Service_Filter').val(-1); 6652 } 6653 6654 if (!UTIL.isEmpty(product)) { 6655 jrpt.find('.Inventory_Filter').val(product); 6656 } 6657 6658 //if (!UTIL.isEmpty(sfilter)) { $('#staff-filter').val(sfilter); } 6659 GLO.Report.enableFullPageCheck(isSalesSummary); 6660 GLO.Report.CellSummary.initReport(jrpt, true, true); 6661 GLO.Report.initIcons(jrpt); 6662 6663 _initClientFilter(jrpt); 6664 _conRptSales.hideCommissionColumn(); //GLO.Report.Template.hideEmptyColumn(jrpt, 'commission-cell'); 6665 GLO.Report.Template.hideEmptyColumn(jrpt, 'column-profit'); 6666 } 6667 6668 function _initClientFilter(jrpt) { 6669 var jclient = jrpt.find('#report-client-filter').find('#Client_Filter_id'); 6670 6671 if (jclient.length > 0) { 6672 UI.initAutoComplete(jclient, GLO.Link.Object.Provider.ClientSearch); 6673 6674 if (UTIL.isEmpty(jclient.val())) { 6675 var jtd = jrpt.find('table.tablesorter').find('tbody').find('.column-buyer:first, .report-pay-buyer:first'); 6676 6677 jclient.val(UTIL.coalesce(jtd.find('a').text(), jtd.text())); 6678 } 6679 } 6680 } 6681 6682 _conRptSales.preInitSalesSummary = function(jcontainer, isSearch) { 6683 //var cashDIV = jcontainer.find('#cash-drawer-info').removeClass('hide'); 6684 //jcontainer.find('#report-table-sales-summary').before(cashDIV); 6685 6686 var jrpts = jcontainer.find('.report-sales-summary-by-booking'); 6687 var javg = jcontainer.find('.report-sales-average-by-booking'); 6688 var htm = '', tbl = '<table class="hide tablesorter tblSlim report-sales-average-by-booking" style="margin: auto; margin-top: 60px;">'; 6689 6690 for (var i=0; i < jrpts.length; i++) { 6691 var avgRPT = tbl + jrpts.eq(i).find('thead').outerHTML(); 6692 var trs = jrpts.eq(i).find('tbody tr.average-total'); 6693 6694 for (var r=0; r < trs.length; r++) { 6695 avgRPT += trs.eq(r).removeClass('hide').outerHTML(); 6696 trs.eq(r).remove(); 6697 } 6698 6699 /* removed footer 6700 var trfoot = jrpts.eq(i).find('tfoot tr.average-total'); 6701 avgRPT += '<tfoot style="border-top: 1px solid #333;">' + trfoot.removeClass('hide').outerHTML() + '</tfoot> </table>'; 6702 trfoot.remove(); 6703 */ 6704 6705 javg.eq(i).html(avgRPT); 6706 } 6707 6708 _conRptSales.loadSalesSummary(jcontainer); 6709 6710 if (isSearch) { 6711 htm = $('<div>' + jcontainer.outerHTML() + htm + '</div>'); 6712 htm = _formatSalesSummaryByBkg(htm); 6713 return htm.html(); 6714 } else { 6715 _formatSalesSummaryByBkg(jcontainer); 6716 var checkedAttribute = ''; 6717 var isForecast = UTIL.parseBool(UTIL.coalesceString(GLO.Uri.query('Include_Forecast_fl'), GLO.Uri.query('forecast'), $.cookies.get('is-forecasted-sales'), 1)); 6718 6719 if (isForecast) { 6720 checkedAttribute = ' checked="checked"'; 6721 } 6722 6723 var chk = '<input type="checkbox" id="Include_Forecast_fl" onchange="GLO.Report.Sales.changeForecastedSales()"' + checkedAttribute + '/>'; 6724 var lblMessage = 'Include Forecasted Sales <small>(appointments scheduled in the future)'; 6725 6726 if (innerWidth < 500) { lblMessage = 'Include Sales Forecast <small>(future appointments)'; } 6727 6728 var lbl = '<label for="Include_Forecast_fl">' + lblMessage + '</small><label>'; 6729 var htm = '<div class="report-search-forecast">' + chk + lbl + '</div>'; 6730 jcontainer.find('.report-search-header').after(htm); 6731 } 6732 6733 _conRptSales.initSummaryChart(); 6734 } 6735 _conRptSales.changeForecastedSales = function() { 6736 var isForecastedSales = $('.report-search-forecast #Include_Forecast_fl').prop('checked'); 6737 6738 UTIL.setCookie('is-forecasted-sales', isForecastedSales); 6739 } 6740 _conRptSales.initStaffFilter = function() { 6741 GLO.Info.init(); 6742 6743 if (GLO.Info.roleType > 199 && !GLO.Info.isIndependentPackage() && GLO.Info.isMobile()) { 6744 var sfilter = UTIL.coalesceString(GLO.Uri.query('sfilter'), 'all'); 6745 var jstaff = $('#staff-filter'); 6746 6747 if (jstaff.find('option[value = "all"]').length === 0) { 6748 jstaff.prepend('<option value="all">ALL</option>'); 6749 } 6750 6751 jstaff.val(sfilter); 6752 return true; 6753 } 6754 6755 return false; 6756 } 6757 _conRptSales.postInitSalesSummary = function(jcontainer, isSearch) { 6758 _displayPriceOnlyColumn(jcontainer); 6759 var jh = jcontainer.find('#ss-header'); 6760 6761 if (jcontainer.find('#ss-no-results').length > 0) { 6762 jh.addClass('hide'); 6763 return false; 6764 } 6765 6766 var jTicketData = jcontainer.find('#sales-summary-ticket-data'); 6767 $('#sales-summary-ticket-container-left').html(jTicketData.find('#sales-summary-ticket-data-left')); 6768 $('#sales-summary-ticket-container-right').html(jTicketData.find('#sales-summary-ticket-data-right')); 6769 6770 if (jTicketData.length > 0) { 6771 $('#sales-summary-ticket-buttons').removeClass('hide'); 6772 } else { 6773 $('#sales-summary-ticket-buttons').addClass('hide'); 6774 } 6775 6776 _initPaySummary(jcontainer, jh, isSearch); 6777 _postSearchHideEmptyColumns(jcontainer); 6778 6779 jh.removeClass('hide'); 6780 GLO.Report.CellSummary.initReport(jcontainer, true, true); 6781 return true; 6782 } 6783 function _displayPriceOnlyColumn(jcontainer) { 6784 var trs = jcontainer.find('#report-table-sales-summary tbody tr'); 6785 var hasPriceDiff = false; 6786 6787 for (var i=0; i < trs.length; i++) { 6788 var sales = UTIL.coalesceMoney(trs.eq(i).find('td.summary-column-service-sale').text().replace('$', '')); 6789 var price = UTIL.coalesceMoney(trs.eq(i).find('td.summary-column-service-price').text().replace('$', '')); 6790 6791 if (sales != price) { 6792 hasPriceDiff = true; 6793 break; 6794 } 6795 } 6796 6797 if (hasPriceDiff) { 6798 jcontainer.find('#report-table-sales-summary .summary-column-service-price').removeClass('hideX'); 6799 } 6800 } 6801 function _postSearchHideEmptyColumns(jrpt) { 6802 if (!jrpt.hasClass('tablesorter')) { 6803 jrpt = jrpt.find('table.tablesorter'); 6804 } 6805 6806 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-count'); 6807 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-sale'); 6808 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-discount'); 6809 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-tax'); 6810 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-return'); 6811 6812 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-commission'); 6813 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-cost'); 6814 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-profit'); 6815 6816 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-fee'); 6817 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-commission'); 6818 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-profit'); 6819 6820 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-discount'); 6821 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-addon'); 6822 GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-tip'); 6823 6824 var jrpts = $('table.report-sales-summary-by-booking'); 6825 6826 for (var i=0; i < jrpts.length; i++) { 6827 var report = jrpts.eq(i); 6828 6829 GLO.Report.hideEmptyColumn(report, 'column-product-count'); 6830 GLO.Report.hideEmptyColumn(report, 'column-product-sale'); 6831 GLO.Report.hideEmptyColumn(report, 'column-product-discount'); 6832 6833 GLO.Report.hideEmptyColumn(report, 'column-product-tax'); 6834 GLO.Report.hideEmptyColumn(report, 'column-product-total'); 6835 GLO.Report.hideEmptyColumn(report, 'column-product-return'); 6836 6837 GLO.Report.hideEmptyColumn(report, 'column-product-commission'); 6838 GLO.Report.hideEmptyColumn(report, 'column-product-cost'); 6839 GLO.Report.hideEmptyColumn(report, 'column-product-profit'); 6840 } 6841 } 6842 6843 function _initPaySummary(jcontainer, jh, isSearch) { 6844 jh.find('#sales-summary-payment-summary').remove(); 6845 6846 var jPaySummary = jcontainer.find('#sales-summary-payment-summary'); 6847 var tds = jPaySummary.find('tfoot tr td'); 6848 var paymentTypeCount = 0; 6849 6850 if (tds.length === 0) { 6851 tds = jPaySummary.find('tbody tr td'); 6852 } 6853 6854 if (isSearch) { 6855 jh.removeClass('is-initial-page-load').addClass('is-search'); 6856 } else { 6857 jh.addClass('is-initial-page-load'); 6858 } 6859 6860 for (var i=0; i < tds.length; i++) { 6861 var td = tds.eq(i); 6862 6863 if (td.hasClass('ps-merchant-column')) { 6864 ++paymentTypeCount; 6865 } else { 6866 var amt = UTIL.coalesceMoney($.trim(td.find('a').text()).replace('$', '')); 6867 6868 if (amt > 0) { 6869 ++paymentTypeCount; 6870 } else { 6871 var cssClass = td.attr('class'); 6872 jPaySummary.find('.' + cssClass).remove(); 6873 } 6874 } 6875 } 6876 6877 jh.find('#ssh-payment-column').append(jPaySummary); 6878 /* if (paymentTypeCount < 4 && !isSearch) { 6879 jh.find('#ssh-data').append(jPaySummary); 6880 } else { 6881 jh.append(jPaySummary); 6882 } */ 6883 } 6884 6885 function _formatSalesSummaryByBkg(jcontainer) { 6886 var jrpts = jcontainer.find('.report-sales-summary-by-booking, .report-sales-average-by-booking'); 6887 6888 for (var i=0; i < jrpts.length; i++) { 6889 var pcommission = 0, pdiscount = 0, sdiscount = 0; 6890 var trs = jrpts.eq(i).find('tbody > tr'); 6891 6892 for (var r=0; r < trs.length; r++) { 6893 var tr = trs.eq(r);
6894 pcommission += UTIL.coalesceMoney($.trim(tr.find('td.commission-column').text()).replace('$', '')); 6895 pdiscount += UTIL.coalesceMoney($.trim(tr.find('td.product-discount-column').text()).replace('$', '')); 6896 sdiscount += UTIL.coalesceMoney($.trim(tr.find('td.service-discount-column').text()).replace('$', '')); 6897 } 6898 6899 //Remove Columns (if empty) 6900 if (pcommission === 0) { 6901 jrpts.eq(i).find('tr .commission-column').remove(); 6902 } 6903 6904 if (pdiscount === 0) { 6905 jrpts.eq(i).find('tr .product-discount-column').remove(); 6906 } 6907 6908 if (sdiscount === 0) { 6909 jrpts.eq(i).find('tr .service-discount-column').remove(); 6910 } 6911 6912 //If have all columns make text smaller 6913 if (pcommission > 0 && pdiscount > 0 && sdiscount > 0) { 6914 jrpts.eq(i).addClass('report-smaller'); 6915 } 6916 } 6917 6918 return jcontainer; 6919 } 6920 6921 function _initSalesSummary() { 6922 var jrpt = $('#report-sales-summary'); 6923 jrpt.find('.Payment_Method_cd, #report-search-header-line2').remove(); 6924 6925 /* 6926 var jsearch = jrpt.find('.btnSearch'); 6927 var btnSearch = jsearch.css({ "position": "absolute", "left": "5px" }).outerHTML(); 6928 var btoday = '<span class="btnAdd" style="position: absolute; right: 5px; height: 20px; padding-top: 0;"><a onclick="GLO.Report.Sales.searchToday()"> Today </a></span>'; 6929 var td = jsearch.parent().css({ "width": "260px" }); 6930 td.html('<span style="position: relative; display: block; width: 240px; margin-top: -6px;">' + btnSearch + btoday + '</span>'); 6931 */ 6932 6933 jrpt.find('#sales-summary-ticket-container').removeClass('hide'); 6934 6935 if (jrpt.find('.report-sales-summary-by-booking').length < 2) { 6936 jrpt.find('#sales-summary-ticket-info').remove(); 6937 jrpt.find('.report-sales-summary-by-booking').css({ "box-shadow": "inherit" }); 6938 } 6939 6940 GLO.Info.init(); 6941 _conRptSales.initStaffFilter(); 6942 6943 _initWideScreen(jrpt); 6944 _gotoByUri(); 6945 } 6946 function _initWideScreen(jrpt) { 6947 var columnCount = jrpt.find('#report-table-sales-summary').find('thead th').length; 6948 6949 if (columnCount > 12) { 6950 $('body').addClass('wide-report'); 6951 } 6952 } 6953 6954 function _gotoByUri() { 6955 if (GLO.Uri.hash('tab').toLowerCase() !== 'sales-summary') { return; } 6956 6957 var gt = GLO.Uri.query('goto'); 6958 var redirectFrom = UTIL.cleanString(GLO.Uri.query('redirectFrom')).toLowerCase(); 6959 6960 if (!UTIL.isEmpty(gt)) { 6961 var jsection = $('#sales-summary-container #report-sales-summary-' + gt + ':visible'); 6962 6963 if (jsection.length === 1) { 6964 $(window).scrollTop(jsection[0].offsetTop); 6965 UI.highlight(jsection); 6966 } 6967 } 6968 6969 if (!UTIL.isEmpty(redirectFrom) && GLO.Info.providerPackage == 4) { 6970 if (redirectFrom == 'staffgoal' || redirectFrom == 'staff-goal') { 6971 GLO.Info.isRequireGold(false, 'the Staff Goal report'); 6972 } else if (redirectFrom == 'staffsummary' || redirectFrom == 'staff-summary') { 6973 GLO.Info.isRequireGold(false, 'the Staff Summary report'); 6974 } 6975 } 6976 } 6977 6978 _conRptSales.infoSalesTotal = function(element, timePeriod, searchQuery) { 6979 var jelement = $('#ssh-total-top').find(searchQuery); //.closest('#sales-summary-totals'); 6980 6981 if (jelement.length === 0) { 6982 if (timePeriod) { 6983 var htm = '<div id="pop-info-sales-total-inner" style="margin-bottom: 24px;">No sales over ' + timePeriod + '</div>'; 6984 var jpop = GLO.Popup.Info.open(htm, timePeriod).getPopup().attr('id', 'pop-info-sales-total').css({ "margin-top": "0" }); 6985 } 6986 6987 return; 6988 } 6989 6990 var total = UTIL.coalesceMoney(jelement.attr('total_mn')), product = UTIL.coalesceMoney(jelement.attr('product_mn')); 6991 var service = UTIL.coalesceMoney(jelement.attr('service_mn')), tip = UTIL.coalesceMoney(jelement.attr('tip_mn')); 6992 var start = jelement.attr('start_d'), end = jelement.attr('end_d'); 6993 var backbar = UTIL.coalesceMoney(jelement.attr('backbar_mn')), gift = UTIL.coalesceMoney(jelement.attr('gift_mn')), membership = UTIL.coalesceMoney(jelement.attr('membership_mn')); 6994 6995 var htmTotal = '<label style="color: #aaa;">Total Sales</label> <b style="color: #BDE5F8;">' + UTIL.displayMoney(total, false, false, true) + '</b>';
6996 var pcss = 'margin-bottom: 0; cursor: pointer;'; 6997 var rptUri = 'reports/saleshistory?isfullpage=1&sfilter=' + GLO.Uri.query('sfilter'); 6998 6999 var ssales = UTIL.displayMoney(service, false, false, true); 7000 var cntLabel = UTIL.pluralLabel(jelement.attr('service_nr'), 'service'); 7001 var fn = 'GLO.Report.Template2.goToReport(\'Service Sales\', \'' + rptUri + '&inventoryfilter=-1\', event, true)'; 7002 var msg = '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Service Sales</label> <b>' + ssales + '</b> <small> (' + cntLabel + ')</small></p>'; 7003 7004 if (tip > 0) { 7005 msg += '<p><label>Service Tips</label> <b>' + UTIL.displayMoney(tip, false, false, true) + '</b></p>'; 7006 7007 if (!GLO.Info.isIndividual()) { 7008 htmTotal += '<div>' 7009 + '<label style="color: #aaa;">Total Sales <small style="letter-spacing: 0;">(including tip)</small></label>' 7010 + '<b style="padding-left: 4px; color: #BDE5F8;">' + UTIL.displayMoney(total + tip, false, false, true) + '</b>' 7011 + '</div>'; 7012 } 7013 } 7014 7015 if (product > 0) { 7016 var totalReturns = _returnTotal(); 7017 var psales = UTIL.displayMoney(product, false, false, true); 7018 var cntLabel = UTIL.pluralLabel(jelement.attr('product_nr'), 'product'); 7019 var fn = 'GLO.Report.Template2.goToReport(\'Backbar Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=r\', event, true)'; 7020 msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Product Sales</label> <b>' + psales + '</b> <small> (' + cntLabel + ')</small></p>'; 7021 7022 if (totalReturns) { 7023 var disclaimer = 'product sales of ' + psales + ' ignores returns<br/><i style="font-size: 11px;">for return details see the return\'s and tax columns in the report below</i>'; 7024 msg += '<p style="margin-left: -24px; margin-top: 0; line-height: 1.5;"><small style="display: inline-block; letter-spacing: 0; font-size: 12px;">' + disclaimer +'</p>'; 7025 } 7026 } 7027 7028 if (backbar > 0) { 7029 var bsales = UTIL.displayMoney(backbar, false, false, true); 7030 var cntLabel = UTIL.pluralLabel(jelement.attr('backbar_nr'), 'product'); 7031 var fn = 'GLO.Report.Template2.goToReport(\'Backbar Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=b\', event, true)'; 7032 msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Backbar Sales</label> <b>' + bsales + '</b> <small> (' + cntLabel + ')</small></p>'; 7033 } 7034 if (gift > 0) { 7035 var gsales = UTIL.displayMoney(gift, false, false, true); 7036 var cntLabel = UTIL.pluralLabel(jelement.attr('gift_nr'), 'gift card'); 7037 var fn = 'GLO.Report.Template2.goToReport(\'Retail Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=g\', event, true)'; 7038 msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Gift Card Sales</label> <b>' + gsales + '</b> <small> (' + cntLabel + ')</small></p>'; 7039 } 7040 if (membership > 0) { 7041 var msales = UTIL.displayMoney(membership, false, false, true); 7042 var cntLabel = UTIL.pluralLabel(jelement.attr('membership_nr'), 'membership'); 7043 var fn = 'GLO.Report.Template2.goToReport(\'Retail Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=r\', event, true)'; 7044 msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Membership Sales</label> <b>' + msales + '</b> <small> (' + cntLabel + ')</small></p>'; 7045 } 7046 7047 if (!UTIL.isEmpty(timePeriod)) { 7048 timePeriod = timePeriod + ': '; 7049 } else { 7050 timePeriod = ''; 7051 } 7052 7053 timePeriod = new Date(start).toGloDateString(true, true, true, true); 7054 7055 if (UTIL.isDate(end) && start != end) { 7056 timePeriod += ' - ' + new Date(end).toGloDateString(true, true, true, true); 7057 } 7058 7059 var htm = '<div id="pop-info-sales-total-inner" style="margin-bottom: 24px;">' + msg + '</div>'; 7060 var jpop = GLO.Popup.Info.open(htm, timePeriod).getPopup().attr('id', 'pop-info-sales-total').css({ "margin-top": "0" }); 7061 jpop.find('.msg').before('<div class="total-sales">' + htmTotal + '</div>'); 7062 7063 if (tip >
7063 0 && !GLO.Info.isIndividual()) { 7064 jpop.find('.pop-icon').css({ "margin-top": "24px" }); 7065 } 7066 } 7067 7068 function _returnTotal() { 7069 var tds = $('#report-table-sales-summary').find('tbody .summary-column-product-return'); 7070 var total = 0; 7071 7072 for (var i=0; i < tds.length; i++) { 7073 total += UTIL.coalesceMoney(tds.eq(i).text().replace('$', '')); 7074 } 7075 7076 return total; 7077 } 7078 7079 _conRptSales.changePaymentMethod = function() { 7080 var jby = $('#rpt-filter-pay-method').find('#filter-pay-processed-by'); 7081 7082 if (!UTIL.isEmpty(this.value)) { 7083 var headerText = SA.Resource.PaymentDetail; 7084 jby.removeClass('hide'); 7085 $('#doc3').addClass('is-payment-report'); 7086 } else { 7087 var headerText = SA.Resource.SalesDetail; 7088 jby.addClass('hide'); 7089 $('#doc3').removeClass('is-payment-report'); 7090 } 7091 7092 $('.shadow-content0 #detail-report-header-text').text(headerText); 7093 } 7094 7095 7096 _conRptSales.switchToTicketAverage = function(isAverage) { 7097 var jbig = $('#sales-summary-ticket-info'); 7098 var j = $('#report-sales-summary'); 7099 var jbtns = j.find('#sales-summary-ticket-buttons'); 7100 7101 if (isAverage) { 7102 jbig.addClass('average'); 7103 jbtns.find('#sales-average-ticket-on').addClass('selected'); 7104 jbtns.find('#sales-summary-ticket-on').removeClass('selected'); 7105 7106 j.find('#sales-summary-description-total, .report-sales-summary-by-booking').addClass('hide'); 7107 _displayProcessingBar(j); 7108 7109 setTimeout(function() { 7110 var j = $('#report-sales-summary'); 7111 j.find('#sales-summary-ticket-processing').addClass('hide'); 7112 j.find('#sales-summary-description-average, .report-sales-average-by-booking').removeClass('hide'); 7113 }, 900); 7114 7115 j.find('#sales-summary-ticket-data-right').removeClass('hide'); 7116 j.find('#ssh-payment-incorrect').addClass('hideX'); 7117 } else { 7118 jbig.removeClass('average'); 7119 jbtns.find('#sales-average-ticket-on').removeClass('selected'); 7120 jbtns.find('#sales-summary-ticket-on').addClass('selected'); 7121 7122 j.find('#sales-summary-description-average, .report-sales-average-by-booking').addClass('hide'); 7123 _displayProcessingBar(j); 7124 7125 setTimeout(function() { 7126 var j = $('#report-sales-summary'); 7127 j.find('#sales-summary-ticket-processing').addClass('hide'); 7128 j.find('#sales-summary-description-total, .report-sales-summary-by-booking').removeClass('hide'); 7129 }, 1100); 7130 7131 j.find('#sales-summary-ticket-data-right').addClass('hide'); 7132 j.find('#ssh-payment-incorrect').removeClass('hideX'); 7133 } 7134 } 7135 7136 function _displayProcessingBar(jcontainer) { 7137 var jprocessing = jcontainer.find('#sales-summary-ticket-processing'); 7138 var img = jprocessing.find('img'); 7139 var src = img.attr('src'); 7140 img.remove(); 7141 jprocessing.removeClass('hide').html('<img/>'); 7142 7143 setTimeout(function() { 7144 jprocessing.find('img').attr('src', src); 7145 }, 50); 7146 } 7147 7148 _conRptSales.searchToday = function() { 7149 var jrpt = $('#report-sales-summary'); 7150 var jtoday = jrpt.find('.btnAdd'); 7151 var today = new Date().toGloDate(); 7152 7153 jrpt.find('.Report_Begin_dt, .Report_End_dt').val(today); 7154 GLO.UI.Form.beginProcessing(jtoday); 7155 7156 GLO.Report.Template.search(); 7157 setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 2500); 7158 } 7159 7160 function _initMostPopular(isService) { 7161 if (isService) { var idPostfix = '-services'; } else { var idPostfix = '-products'; } 7162 7163 var jMost = $('#report-popular' + idPostfix); 7164 jMost.find('#rpt-filter-pay-method').remove(); 7165 7166 if (isService) { 7167 jMost.find('.inventory-filter-container').remove(); 7168 var jdd = jMost.find('.service-filter-container').css({ "margin-right": "90px" }); 7169 7170 var jopts = jdd.find('option:not(.sg-option)'); 7171 for (var i=1; i < jopts.length; i++) { jopts.eq(i).remove(); } 7172 7173 var svcfilter = GLO.Uri.query('inventoryfilter'); 7174 7175 if (svcfilter) { 7176 jdd.find('.Service_Filter').val(svcfilter); 7177 } 7178 } else { 7179 jMost.find('.service-filter-container').remove(); 7180 var jdd = jMost.find('.inventory-filter-container').css({ "margin-right": "90px" }); 7181 7182 var jopts = jdd.find('option:not(.v-option)'); 7183 for (var i=1; i < jopts.length; i++) { jopts.eq(i).remove(); } 7184 7185 var ifilter = GLO.Uri.query('inventoryfilter'); 7186 7187 if (ifilter) { 7188 jdd.find('.Inventory_Filter').val(ifilter); 7189 } 7190 } 7191 7192 var radio = '<fieldset class="popular-input">' 7193 + '<table> <tr>' 7194 + '<td class="popular-selection view-selected" onclick="GLO.Report.Sales.focusPopular(this)">' 7195 + '<input type="radio" id="radio-popular-most' + idPostfix + '" name="popular-switch' + idPostfix + '" class="popular-radio" checked="checked"/>' 7196 + '<input type="text" class="number-popular-most" value="10" maxlength="3" mask="int" pattern="[0-9]" onclick="GLO.Report.Sales.focusPopularText(this)"/>' 7197 + '<label for="radio-popular-most' + idPostfix + '">' + SA.Resource.MostPopular + '</label>' 7198 + '</td>' 7199 + '<td id="popular-input-center-column"></td>' 7200 + '<td class="popular-selection" onclick="GLO.Report.Sales.focusPopular(this)">' 7201 + '<input type="radio" id="radio-popular-least' + idPostfix + '" name="popular-switch' + idPostfix + '"/>' 7202 + '<input type="text" class="number-popular-least" value="10" maxlength="3" mask="int" pattern="[0-9]" onclick="GLO.Report.Sales.focusPopularText(this)"/>' 7203 + '<label for="radio-popular-least' + idPostfix + '">' + SA.Resource.LeastPopular + '</label>' 7204 + '</td>' 7205 7206 //+ '<span class="popular-selection">' 7207 // + '<input type="radio" id="radio-popular-all' + idPostfix + '" name="popular-switch' + idPostfix + '"/>' 7208 // + '<label for="radio-popular-all' + idPostfix + '" style="margin-left: 30px;">All</label>' 7209 //+ '</span>' 7210 + '</tr> </table>' 7211 + '</fieldse>'; 7212 7213 jMost.find('.report-search-header').append(radio); 7214 jMost.find('.popular-selection').click(GLO.Report.Sales.selectPopular) 7215 7216 if (GLO.Info.providerPackage === 1) { 7217 var mleft = "105px"; 7218 } else { 7219 var mleft = "-45px"; 7220 } 7221 7222 jMost.find('.btnSearch').css({ "position": "absolute", "margin-top": "65px", "margin-left": mleft, "font-size": "larger" }); //, "margin-left": "50px" 7223 jMost.find('.report-inventory-search-prev, .report-inventory-search-next').css({ "margin-top": "30px" }); 7224 jMost.find('.report-inventory-search-prev img, .report-inventory-search-next img').css({ "height": "90px" }); 7225 GLO.Report.CellSummary.initReport(jMost, false, true); 7226 } 7227 7228 _conRptSales.focusPopularText = function(inputElement) { 7229 var j = $(inputElement); 7230 j.closest('td').find(':radio').prop('checked', true); 7231 } 7232 7233 _conRptSales.focusPopular = function(tdElement) { 7234 $(tdElement).find(':radio').prop('checked', true); 7235 } 7236 7237 _conRptSales.goToTab = function(tab) { 7238 if (tab > _conRptSales.MAX_TAB) { 7239 tab = _conRptSales.MAX_TAB; 7240 } else if (tab < 1) { 7241 tab = 1; 7242 } 7243 7244 $('#report-sales-summary').addClass('hide'); 7245 $('#report-sales-history').addClass('hide'); 7246 7247 if (tab === 1) { 7248 $('#report-sales-summary').removeClass('hide'); 7249 } else if (tab === 2) { 7250 var historyRpt = $('#report-sales-history').removeClass('hide'); 7251 var jsearch2 = historyRpt.find('#report-search-header-line2') 7252 7253 if (jsearch2.length > 0) { 7254 historyRpt.find('.report-search-header .btnSearch').remove(); 7255 historyRpt.find('#report-search-header-line2').removeClass('hide'); 7256 } 7257 } 7258 7259 var backColor = $('.shadow-content0').css('backgroundColor'); 7260 var jhead = $('#report-portal-header'); 7261 var oj = jhead.find('table tr td span b'); 7262 7263 oj.each(function() { 7264 $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent'); 7265 }); 7266 7267 oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent(); 7268 oj.addClass('report-tab'); 7269 oj.css('backgroundColor', backColor); 7270 7271 _conRptSales.currentTab = tab; 7272 var hashTab = ''; 7273 7274 if (tab == 1) { 7275 hashTab = 'sales-summary'; 7276 } else if (tab == 2) { 7277 hashTab = 'sales-history'; 7278 //var pmeth = historyRpt.find('.Payment_Method_cd').val(); 7279 //if (!UTIL.isEmpty(pmeth)) { hashTab += '&paymethod=' + pmeth; } 7280 } 7281 7282 document.location.hash = 'tab=' + hashTab; 7283 } 7284 7285 _conRptSales.goToPopularTab = function(tab) { 7286 if (tab > _conRptSales.MAX_TAB) { 7287 tab = _conRptSales.MAX_TAB; 7288 } else if (tab < 1) { 7289 tab = 1; 7290 } 7291 7292 $('#report-popular-services').addClass('hide'); 7293 $('#report-popular-products').addClass('hide'); 7294 7295 if (tab === 1) { 7296 $('#report-popular-services').removeClass('hide'); 7297 } else if (tab === 2) { 7298 $('#report-popular-products').removeClass('hide'); 7299 } 7300 7301 var backColor = $('.shadow-content0').css('backgroundColor'); 7302 var jhead = $('#report-portal-header'); 7303 var oj = jhead.find('table tr td span b'); 7304 7305 oj.each(function() { 7306 $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent'); 7307 }); 7308 7309 oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent(); 7310 oj.addClass('report-tab'); 7311 oj.css('backgroundColor', backColor); 7312 7313 _conRptSales.currentTab = tab; 7314 var hashTab = ''; 7315 7316 if (tab == '1') { 7317 hashTab = 'popular-services'; 7318 } else if (tab == '2') { 7319 hashTab = 'popular-products'; 7320 } 7321 7322 document.location.hash = 'tab=' + hashTab; 7323 } 7324 7325 _conRptSales.selectPopular = function() { 7326 var me = $(this); //var j = me.closest('.popular-selection'); 7327 7328 me.closest('.popular-input').find('.view-selected').removeClass('view-selected'); 7329 me.addClass('view-selected'); 7330 } 7331 7332 _conRptSales.hideCommissionColumn = function() { 7333 var rptSalesSummary = $('#report-table-sales-summary'); 7334 _hideCommissionColumn2(rptSalesSummary); 7335 7336 var rptSalesHistory = $('#report-sales-history'); 7337 _hideCommissionColumn2(rptSalesHistory); 7338 } 7339 7340 function _hideCommissionColumn2(jContainer) { 7341 var totalCommission = UTIL.coalesceMoney(jContainer.find('tfoot, tr.tfoot').find('.commission-cell').text().replace('$', '').replace(',', ''), 0); 7342 7343 if (totalCommission === 0) { 7344 jContainer.find('.commission-cell').addClass('hideX'); 7345 var pcell = jContainer.find('thead th.product-cell:visible'); 7346 7347 if (pcell.length === 1) { 7348 pcell.removeClass('notify-cell-left notify-cell-top').css({ "vertical-align": "" }).html(SA.Resource.Product + '<br/>' + SA.Resource.Sales); 7349 } 7350 } 7351 } 7352 7353 function _setPaymentMethod(jrpt) { 7354 var pmeth = jrpt.find('.Payment_Method_cd').val(); 7355 GLO.Uri.hash('pay-method', pmeth); 7356 } 7357 7358 _conRptSales.displayDetail = function() { 7359 var throbber = $('#imgThrobber').outerHTML(); 7360 $('#sales-summary-more-detail').css({ "background-color": "inherit" }).attr('id', 'sales-summary-ticket-info').html(throbber); 7361 $('#report-sales-summary .report-inventory-header-search').click(); 7362 7363 //setTimeout(function() { $('#sales-summary-more-detail').css({ "background-color": "" }) }, 3000); 7364 } 7365 7366 _conRptSales.loadSalesSummary = function(data) { 7367 var tdEarly = data.find('tfoot .summary-column-service-commission-early'); 7368 7369 if (tdEarly.length === 0) { 7370 tdEarly = data.find('td.summary-column-service-commission-early'); 7371 } 7372 7373 var earlyTotal = $.trim(tdEarly.text()).replace('$', ''); 7374 7375 if (earlyTotal) { 7376 data.find('.summary-column-service-commission-early').removeClass('hideX'); 7377 } 7378 } 7379 7380 _conRptSales.initSummaryChart = function(data) { 7381 var ssh = $('#ss-header'); 7382 7383 if (data) { 7384 var j = $(data); 7385 7386 ssh.find('#sales-summary-chart').remove(); 7387 ssh.find('#sales-summary-totals').remove(); 7388 ssh.find('#sales-summary-client-data').remove(); 7389 } else { 7390 var j = $('#report-sales-summary'); 7391 } 7392 7393 var jchart = j.find('#sales-summary-chart'); 7394 var jtotals = j.find('#sales-summary-totals'); 7395 var jclient = j.find('#sales-summary-client-data'); 7396 7397 ssh.find('#ssh-chart').append(jchart); 7398 ssh.find('#ssh-totals').append(jtotals); 7399 ssh.find('#ssh-client-data').append(jclient); 7400 7401 j.find('#sales-summary-more-info').remove(); 7402 7403 if (data) { return j.outerHTML(); } 7404 } 7405 7406 _conRptSales.createSummaryChart = function() { 7407 if (GLO.Data.Chart === undefined) { 7408 $('#ssh-chart, #ssh-data').css({ "visibility": "hidden" }); 7409 $('#ss-no-results').css({ "letter-spacing": "1px" }); 7410 return; 7411 } else { 7412 $('#ssh-chart, #ssh-data').css({ "visibility": "" }); 7413 } 7414 7415 var mustHidePrevWk = true; 7416 var xShowLabel = true; 7417 var len = GLO.Data.Chart.labels.length; 7418 7419 if (GLO.Data.Chart.isBarChart) { 7420 if (!GLO.Data.Chart.isGroupByWeek && !GLO.Data.Chart.isGroupByMonth) { mustHidePrevWk = false; } 7421 7422 if (len > 14 || (!GLO.Data.Chart.isGroupByMonth && len > 7)) { xShowLabel = false; } 7423 7424 _createBarChart(xShowLabel); 7425 } else { 7426 _createLineChart(); 7427 } 7428 7429 if (GLO.Data.Chart.isMultiYearSearch) { 7430 $('.ct-chart-guide-prev-year').addClass('hide'); 7431 $('#ssh-chart .ct-chart').addClass('ct-chart-only-search-range'); 7432 } else { 7433 $('.ct-chart-guide-prev-year').removeClass('hide'); 7434 $('#ssh-chart .ct-chart').removeClass('ct-chart-only-search-range'); 7435 } 7436 7437 $('.ct-chart-guide-search-range td:last').text(GLO.Data.Chart.searchR
7437angeLabelShort); 7438 $('#ssh-data > h2').text(GLO.Data.Chart.searchRangeLabel); 7439 _displayPreviousWeek(mustHidePrevWk); 7440 _manageChartLabel(); 7441 //$('#sales-summary-data').html('<pre> <b>' + GLO.Data.Chart.labels + '</b> <div>' + GLO.Data.Chart.series + '</div> </pre>'); 7442 } 7443 7444 function _manageChartLabel() { 7445 var jchart = $('#ssh-chart .ct-chart'); 7446 var width = jchart.width(); 7447 var maxLen, mod = 0, len = GLO.Data.Chart.labels.length; 7448 7449 if (width < 360) { 7450 maxLen = 7; 7451 } else if (width < 400) { 7452 maxLen = 9; 7453 } else if (width < 500) { 7454 maxLen = 10; 7455 } else if (width < 600) { 7456 maxLen = 13; 7457 } else if (width < 700) { 7458 maxLen = 16; 7459 } else if (width < 800) { 7460 maxLen = 19; 7461 } else { 7462 maxLen = 23; 7463 } 7464 7465 if (GLO.Data.Chart.isGroupByWeek) { 7466 maxLen = parseInt(maxLen * .8); 7467 } else if (!GLO.Data.Chart.isGroupByMonth) { 7468 maxLen = parseInt(maxLen * 1.4); 7469 } 7470 7471 if (len > maxLen * 2) { 7472 _chartClearLabels(); 7473 7474 setTimeout(function() { 7475 jchart.find('.ct-labels .ct-horizontal').remove(); 7476 }, 100); 7477 7478 setTimeout(function() { 7479 jchart.find('.ct-labels .ct-horizontal').remove(); 7480 }, 1200); 7481 } else if (len > maxLen) { 7482 _setShortChartLabel(); 7483 } 7484 7485 //new GLO.Popup.Info('_manageChartLabel() width = ' + width + '; maxLen = ' + maxLen + '; len = ' + len); 7486 } 7487 7488 function _chartClearLabels() { 7489 var arr = GLO.Data.Chart.labels; 7490 7491 for (var i=0; i < arr.length; i++) { 7492 arr[i] = ''; 7493 } 7494 } 7495 7496 function _setShortChartLabel() { 7497 var arr = GLO.Data.Chart.labels; 7498 7499 if (GLO.Data.Chart.isGroupByMonth) { 7500 for (var i=0; i < arr.length; i++) { 7501 arr[i] = arr[i].substring(0,1); 7502 } 7503 } else { 7504 for (var i=0; i < arr.length; i++) { 7505 if (i % 2 == 1) { 7506 arr[i] = ''; 7507 } 7508 } 7509 } 7510 } 7511 7512 function _createLineChart() { 7513 var data = { 7514 labels: GLO.Data.Chart.labels, 7515 series: GLO.Data.Chart.series 7516 }; 7517 7518 var options = { 7519 showPoint: false, // Don't draw the line chart points 7520 lineSmooth: true, // Disable line smoothing 7521 axisX: { 7522 offset: 60, 7523 showGrid: false, // disable grid for this axis 7524 showLabel: true // and also don't show the label 7525 }, 7526 axisY: { 7527 offset: 80, // offset the chart a bit from the labels 7528 7529 labelInterpolationFnc: function(value) { //allows modify values used for the labels on each axis 7530 return UTIL.displayMoney(value, false, false, true); 7531 } 7532 } 7533 }; 7534 7535 new Chartist.Line('.ct-chart', data, options); 7536 7537 $('.ct-chart').addClass('ct-line-chart') 7538 } 7539 7540 function _createBarChart0() { 7541 $(function() { 7542 new Chartist.Bar('.ct-chart', { 7543 labels: GLO.Data.Chart.labels, 7544 series: GLO.Data.Chart.series 7545 }, { 7546 seriesBarDistance: 10, 7547 axisX: { 7548 offset: 20 7549 }, 7550 axisY: { 7551 offset: 60, 7552 labelInterpolationFnc: function (value) { 7553 return UTIL.displayMoney(value, false, false, true); 7554 }, 7555 scaleMinSpace: 15 7556 } 7557 }); 7558 }); 7559 } 7560 7561 function _createBarChart(xShowLabel) { 7562 $('.ct-chart').removeClass('ct-line-chart'); 7563 7564 new Chartist.Bar('.ct-chart', { 7565 labels: GLO.Data.Chart.labels, 7566 series: GLO.Data.Chart.series 7567 }, { 7568 seriesBarDistance: 10, 7569 axisX: { 7570 showLabel: xShowLabel, 7571 showGrid: false, 7572 offset: 20 7573 }, 7574 axisY: { 7575 offset: 60, 7576 labelInterpolationFnc: function (value) { 7577 return UTIL.displayMoney(value, false, false, true); 7578 }, 7579 scaleMinSpace: 15 7580 } 7581 }); 7582 } 7583 7584 function _displayPreviousWeek(mustHide) { 7585 if (mustHide) { 7586 $('.ct-chart-guide-prev-week').addClass('hide'); 7587 $('#sales-summary-chart .ct-chart').removeClass('ct-chart-prev-week'); 7588 } else { 7589 $('.ct-chart-guide-prev-week').removeClass('hide'); 7590 $('#sales-summary-chart .ct-chart').addClass('ct-chart-prev-week'); 7591 } 7592 } 7593 7594 _conRptSales.printScreenInit = function() { 7595 var jtbl = $('#report-sales-history .tablesorter'); 7596 var thStaff = jtbl.find('th.column-staff'); 7597 7598 if (thStaff.hasClass('headerSortDown')) { 7599 UI.Print.printOnDevice(); 7600 } else { 7601 thStaff.click(); 7602 7603 var ojpop = new GLO.Popup.Processing('Printing...');
7604 var delay = 400 + jtbl.find('tr').length; 7605 7606 setTimeout(function() { 7607 ojpop.close(); 7608 UI.Print.printOnDevice(); 7609 }, delay); 7610 } 7611 } 7612 7613 function _print() { 7614 7615 } 7616 7617 _conRptSales.printScreen = function() { 7618 UI.Print.printOnDevice(); 7619 7620 setTimeout(function() { $('#print-report-button > a').click(); }, 100); 7621 } 7622 7623 _conRptSales.printByStaff = function() { 7624 var jrpt = $('#report-sales-history'); 7625 var jtbl = jrpt.find('.tablesorter'); 7626 var tdStaff = jtbl.find('td.column-staff'); 7627 7628 if (GLO.Info.roleType < 219) { 7629 var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds 7630 var start = new Date(jrpt.find('.Report_Begin_dt').val()).getTime(); 7631 var end = new Date(jrpt.find('.Report_End_dt').val()).getTime(); 7632 7633 if ((end - start) / oneDay > 14) { 7634 var fn = function() { 7635 UI.highlight( jrpt.find('.Report_Begin_dt').closest('tr') ); 7636 }; 7637 var msg = '<div>Receptionist user role can only print 2 weeks</div><div style="max-width: 500px; margin-top: 24px;">To print more than 2 weeks please login as Manager or Admin</div>'; 7638 7639 GLO.Popup.Warning.open(msg, 'Receptionist Permission', fn); 7640 return; 7641 } 7642 } 7643 7644 if (tdStaff.length === 0) { 7645 _printByStaffWarning(); 7646 return; 7647 } 7648 7649 var arr = []; 7650 var sid = tdStaff.eq(0).attr('staff_id'); 7651 7652 if (!UTIL.isEmpty(sid)) { 7653 _addStaff(arr, sid, tdStaff, 0); 7654 } 7655 7656 for (var i=1; i < tdStaff.length; i++) { 7657 var sid = tdStaff.eq(i).attr('staff_id'); 7658 7659 if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) { 7660 _addStaff(arr, sid, tdStaff, i); 7661 } 7662 } 7663 7664 arr = UTIL.sortArray(arr, "name"); 7665 7666 if (arr.length === 1) { 7667 _conRptSales.printByStaff2(arr[0].id); 7668 } else { 7669 var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>'; 7670 var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>'; 7671 var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;'; 7672 var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>'; 7673 var reportFormatHtm = ''; 7674 7675 var reportFormatSelectHeader = document.createElement('h5'); 7676 reportFormatSelectHeader.innerHTML = '<div>Select Report Format:</div>'; 7677 7678 var reportFormatSelect = document.createElement('select'); 7679 reportFormatSelect.name = 'reportFormatSelect'; 7680 reportFormatSelect.id = 'reportFormatSelect'; 7681 7682 var reportFormats = [ 7683 "Receipt Printer", 7684 "Normal", 7685 ]; 7686 7687 var format_options_str = ""; 7688 7689 reportFormats.forEach( function(format) { 7690 format_options_str += '<option value="' + format + '">' + format + '</option>'; 7691 }); 7692 7693 reportFormatSelect.innerHTML = format_options_str; 7694 reportFormatHtm = reportFormatSelectHeader.outerHTML + reportFormatSelect.outerHTML; 7695 7696 for (var a=0; a < arr.length; a++) { 7697 ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>'; 7698 } 7699 7700 var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);' 7701 var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>'); 7702 var oj = new GLO.Popup.Custom(jhtm); 7703 var jpop = oj.getPopup().addClass('no-persist'); 7704 var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" }); 7705 7706 jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" }); 7707 jpop.find('.friendly-responsive').css({ "padding-top": "0" }); 7708 7709 jbtn.find('.btnSave').remove(); 7710 jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" }); 7711 } 7712 } 7713 7714 _conRptSales.printByStaffFromPOS = function() { 7715 var jrpt = $('#pos-staff-list'); 7716 var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]'); 7717 7718 if (tdStaff.length === 0) { 7719 _printByStaffWarning(); 7720 return; 7721 } 7722 7723 var arr = []; 7724 var sid = tdStaff.eq(0).attr('staff_id'); 7725 7726 for (var i=0; i < tdStaff.length; i++) { 7727 var sid = tdStaff.eq(i).attr('staff_id'); 7728 var staffName = tdStaff.eq(i).find('.pos-staff-name').text(); 7729 7730 if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) { 7731 arr.push({ "id": sid, "name": staffName }); 7732 } 7733 } 7734 7735 arr = UTIL.sortArray(arr, "name"); 7736 7737 if (arr.length === 1) { 7738 _conRptSales.printByStaff2(arr[0].id); 7739 } else { 7740 var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>'; 7741 var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>'; 7742 var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;'; 7743 var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>'; 7744 var reportFormatHtm = ''; 7745 7746 var reportFormatSelect = document.createElement('select'); 7747 reportFormatSelect.name = 'reportFormatSelect'; 7748 reportFormatSelect.id = 'reportFormatSelect'; 7749 reportFormatSelect.className ='hide'; 7750 7751 var reportFormats = [ 7752 "Receipt Printer" 7753 ]; 7754 7755 var format_options_str = ""; 7756
7757 reportFormats.forEach( function(format) { 7758 format_options_str += '<option value="' + format + '">' + format + '</option>'; 7759 }); 7760 7761 reportFormatSelect.innerHTML = format_options_str; 7762 reportFormatHtm = reportFormatSelect.outerHTML; 7763 7764 for (var a=0; a < arr.length; a++) { 7765 ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>'; 7766 } 7767 7768 var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);' 7769 var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>'); 7770 var oj = new GLO.Popup.Custom(jhtm); 7771 var jpop = oj.getPopup().addClass('no-persist'); 7772 var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" }); 7773 7774 jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" }); 7775 jpop.find('.friendly-responsive').css({ "padding-top": "0" }); 7776 7777 jbtn.find('.btnSave').remove(); 7778 jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" }); 7779 } 7780 } 7781 7782 _conRptSales.printByReceptionistFromMenu = function() { 7783 7784 var uri = GLO.Link.Object.Provider.Ajax + 'StaffModelList'; 7785 7786 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false }) 7787 .success(function(data, textStatus, jqXHR) { 7788 7789 //data is invalid 7790 if (!$.trim(data)){ 7791 _printByStaffWarning(); 7792 } 7793 7794 var jrpt = $(data); 7795 var tdStaff = jrpt.find('li'); 7796 7797 if (tdStaff.length === 0) { 7798 _printByStaffWarning(); 7799 return; 7800 } 7801 7802 var arr = []; 7803 // var sid = tdStaff.eq(0).attr('staff_id'); 7804 7805 for (var i=0; i < tdStaff.length; i++) { 7806 var sid = tdStaff.eq(i).attr('staff_id'); 7807 var staffName = tdStaff.eq(i).find('label>b').text(); 7808 7809 if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) { 7810 arr.push({ "id": sid, "name": staffName }); 7811 } 7812 } 7813 7814 arr = UTIL.sortArray(arr, "name"); 7815 7816 if (arr.length === 1) { 7817 _conRptSales.printByStaff2(); 7818 } else { 7819 var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>'; 7820 var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>'; 7821 var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;'; 7822 var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>'; 7823 var reportFormatHtm = ''; 7824 7825 var reportFormatSelect = document.createElement('select'); 7826 reportFormatSelect.name = 'reportFormatSelect'; 7827 reportFormatSelect.id = 'reportFormatSelect'; 7828 reportFormatSelect.className ='hide'; 7829 7830 var reportFormats = [ 7831 "Receipt Printer" 7832 ]; 7833 7834 var format_options_str = ""; 7835 7836 reportFormats.forEach( function(format) { 7837 format_options_str += '<option value="' + format + '">' + format + '</option>'; 7838 }); 7839 7840 reportFormatSelect.innerHTML = format_options_str; 7841 reportFormatHtm = reportFormatSelect.outerHTML; 7842 7843 for (var a=0; a < arr.length; a++) { 7844 ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>'; 7845 } 7846 7847 var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);' 7848 var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>'); 7849 var oj = new GLO.Popup.Custom(jhtm); 7850 var jpop = oj.getPopup().addClass('no-persist'); 7851 var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" }); 7852 7853 jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" }); 7854 jpop.find('.friendly-responsive').css({ "padding-top": "0" }); 7855 7856 jbtn.find('.btnSave').remove(); 7857 jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" }); 7858 } 7859 7860 }).fail(function(jqXHR, textStatus, errorThrown) { 7861 GLO.UI.Form.resetProcessing(); 7862 new GLO.Popup.Error('Could not get the sales detail report data. Please try again.'); 7863 }); 7864 7865 7866 7867 } 7868 7869 function _addStaff(arr, sid, tdStaff, index) { 7870 var sname = $.trim(UTIL.directTagOnly(tdStaff.eq(index))); 7871 arr.push({ "id": sid, "name": sname }); 7872 } 7873 7874 function _printByStaffWarning() { 7875 var msg1 = '<div>No Sales over selected date range and filter criteria</div>'; 7876 var msg2 = '<div>
7876Please change the search filter and press the search button</div>'; 7877 var htm = '<div class="friendly-responsive"><h1 class="friendly-responsive">No Sales</h1><div>' + msg1 + msg2 + '</div></div>'; 7878 7879 var fn = function() { 7880 var jfilter = $('#report-sales-history .report-search-header'); 7881 UI.highlight(jfilter, 800, 6400, true); 7882 } 7883 7884 new GLO.Popup.Warning(htm, fn); 7885 } 7886 7887 _conRptSales.printByStaff2 = function(staffid) { 7888 var jtbl = $('#report-sales-history .tablesorter'); 7889 var thStaff = jtbl.find('th.column-staff'); 7890 7891 var selectedReportFormat = ''; 7892 if (staffid) { 7893 //assume star printer and try printing 7894 7895 selectedReportFormat = 'Receipt Printer'; 7896 } 7897 else { 7898 selectedReportFormat = document.querySelector('#reportFormatSelect').value; 7899 } 7900 7901 if (selectedReportFormat == 'Receipt Printer') { 7902 //get report html 7903 var jrpt = $('#report-sales-history'); 7904 var start = jrpt.find('.Report_Begin_dt').val(); 7905 var end = jrpt.find('.Report_End_dt').val(); 7906 7907 if (typeof start === "undefined") { 7908 start = new Date().toLocaleDateString(); 7909 } 7910 7911 if (typeof end === "undefined") { 7912 end = new Date().toLocaleDateString(); 7913 } 7914 var shrUri = ''; 7915 if (staffid) { 7916 shrUri = GLO.Link.WebsiteDomain + 'reports/saleshistory?sfilter=' + staffid + '&start=' + start + '&end=' + end + '&inventoryfilter=-1&isemp=1'; 7917 } 7918 else { 7919 shrUri = GLO.Link.WebsiteDomain + 'reports/saleshistory?sfilter=&start=' + start + '&end=' + end + '&inventoryfilter=-1&isemp=1'; 7920 } 7921 7922 var jqxhr = $.ajax({ type: "GET", url: shrUri, "cache": false, data: null, dataType: 'text' }) 7923 .done(function(data, textStatus, jqXHR) { 7924 window.onbeforeunload = null; 7925 if(data!=null && data!== '') { 7926 var reportHtml = data; 7927 7928 var hasHtmlContent = /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/.test(data); 7929 //check data 7930 if (hasHtmlContent && $(data).find('#ss-no-results').length > 0) { 7931 _printByStaffWarning(); 7932 } 7933 else { 7934 7935 7936 if (SA.App.isWKWebView() && window.webkit.messageHandlers.PrintToStarPrinter) { 7937 //assume star printer and try printing 7938 7939 var jprocessing = $('#pop-printing-report').closest('.glopop'); 7940 7941 if (jprocessing.length === 0) { 7942 var htm = '<div id="pop-printing-report">Printing Report...</div>'; 7943 jprocessing = GLO.Popup.Processing.open(htm, 'Report').getPopup(); 7944 } 7945 7946 _getSalesDetailRaster(reportHtml,start,end,jprocessing); 7947 } 7948 else { 7949 _generateSalesDetailThermalReceipt(reportHtml,start,end); 7950 } 7951 } 7952 } else { 7953 new GLO.Popup.Error('Could not get the sales detail report data'); 7954 } 7955 }) 7956 .fail(function(jqXHR, textStatus, errorThrown) { 7957 GLO.UI.Form.resetProcessing(); 7958 new GLO.Popup.Error('Could not get the sales detail report data'); 7959 }); 7960 } 7961 else { 7962 7963 if (thStaff.hasClass('headerSortDown')) { 7964 _printByStaff3(staffid); 7965 } else { 7966 thStaff.click(); 7967 7968 var ojpop = new GLO.Popup.Processing('Printing...'); 7969 var delay = 400 + jtbl.find('tr').length; 7970 7971 setTimeout(function() { 7972 ojpop.close(); 7973 _printByStaff3(staffid); 7974 }, delay); 7975 } 7976 } 7977 } 7978 7979 7980 function _generateSalesDetailThermalReceipt(reportHtml,start,end) { 7981 7982 if (reportHtml && reportHtml.length > 100) { 7983 7984 //main receipt element 7985 var reportEl = document.createElement("div"); 7986 reportEl.className='receipt'; 7987 reportEl.setAttribute("style", "margin:0;"); 7988 7989 7990 //report name 7991 var reportNameEl = document.createElement("div"); 7992 reportNameEl.className='headerSubTitle'; 7993 reportNameEl.innerHTML='Sales Report'; 7994 reportEl.append(reportNameEl); 7995 7996 var staffIds=[]; 7997 var staffList=[]; 7998 7999 $(reportHtml).find('.service-row').each(function() { 8000 var staffId = $(this).find('td:first-child').attr("staff_id"); 8001 var staffName = $(this).find('.column-staff').text(); 8002 if(staffIds.indexOf(staffId) === -1) { 8003 var staff = { 8004 "staffid": staffId, 8005 "name": staffName 8006 }; 8007 staffIds.push(staffId); 8008 staffList.push(staff); 8009 8010 } 8011 }); 8012 8013 if (staffList.length > 0) { 8014 staffList.forEach(function(staff) { 8015 8016 var staffNameEl = document.createElement("div"); 8017 staffNameEl.className='location'; 8018 staffNameEl.innerHTML=staff.name; 8019 8020 var dateRangeEl = document.createElement("div"); 8021 dateRangeEl.className='headerSubTitle'; 8022 dateRangeEl.innerHTML = start + ' - ' + end; 8023 8024 reportEl.append(staffNameEl); 8025 reportEl.append(dateRangeEl); 8026 8027 var flexEl = document.createElement("div"); 8028 flexEl.className='flex'; 8029 // flexEl.setAttribute("style", "page-break-after: always;"); 8030 8031 var itemsWrapperEl = document.createElement("div"); 8032 itemsWrapperEl.className='totals'; 8033 8034 var itemSectionEl = document.createElement("div"); 8035 itemSectionEl.className='section'; 8036 8037 //add column names 8038 var headerRowEl = document.createElement("div"); 8039 headerRowEl.className='row headerRow'; 8040 var hCol1El = document.createElement("div"); 8041 hCol1El.className='col1'; 8042 hCol1El.innerHTML = 'Client'; 8043 var hCol2El = document.createElement("div"); 8044 hCol2El.className='col2'; 8045 hCol2El.innerHTML = 'Service'; 8046 var hCol3El = document.createElement("div"); 8047 hCol3El.className='col3'; 8048 hCol3El.innerHTML = ''; 8049 var hCol4El = document.createElement("div"); 8050 hCol4El.className='col4'; 8051 hCol4El.innerHTML = 'Service'; 8052 var hCol5El = document.createElement("div"); 8053 hCol5El.className='col5'; 8054 hCol5El.innerHTML = 'Comm.'; 8055 var hCol6El = document.createElement("div"); 8056 hCol6El.className='col6'; 8057 hCol6El.innerHTML = 'Tip'; 8058 8059 headerRowEl.append(hCol1El); 8060 headerRowEl.append(hCol2El); 8061 // headerRowEl.append(hCol3El); 8062 if (GLO.Data.provider.report.reportCanViewPrice) { 8063 headerRowEl.append(hCol4El); 8064 } 8065 if (GLO.Data.provider.report.reportCanViewCommission) { 8066 headerRowEl.append(hCol5El); 8067 } 8068 if (GLO.Data.provider.report.reportCanViewTip) { 8069 headerRowEl.append(hCol6El); 8070 } 8071 8072 itemSectionEl.append(headerRowEl); 8073 8074 var serviceTotal = 0.00, commissionTotal=0.00, tipTotal = 0.00; 8075 $(reportHtml).find('.service-row').each(function() { 8076 8077 var staffId = $(this).find('td:first-child').attr("staff_id"); 8078 if (staff.staffid == staffId) { 8079 var rowEl = document.createElement("div"); 8080 rowEl.className='row'; 8081 var col1El = document.createElement("div"); 8082 col1El.className='col1'; 8083 var clientName = $(this).find('.column-buyer a').text(); 8084 clientName = clientName.replace(/(\r\n|\n|\r)/gm, ""); 8085 col1El.innerHTML = clientName.substring(0,12); 8086 var col2El = document.createElement("div"); 8087 col2El.className='col2'; 8088 var serviceName = $(this).find('.column-variety').text(); 8089 serviceName = serviceName.replace(/(\r\n|\n|\r)/gm, ""); 8090 col2El.innerHTML = serviceName.substring(0,11); 8091 var col3El = document.createElement("div"); 8092 col3El.className='col3'; 8093 col3El.innerHTML = ''; 8094 var col4El = document.createElement("div"); 8095 col4El.className='col4'; 8096 var servicePrice = $(this).find('.column-price').text().replace('$',''); 8097 col4El.innerHTML = parseFloat(servicePrice) || ' '; 8098 serviceTotal += parseFloat(servicePrice) || 0; 8099 var col5El = document.createElement("div"); 8100 col5El.className='col5'; 8101 var commissionAmount = $(this).find('.commission-cell').text().replace('$',''); 8102 col5El.innerHTML = parseFloat(commissionAmount) || ' '; 8103 commissionTotal += parseFloat(commissionAmount) || 0; 8104 var col6El = document.createElement("div"); 8105 col6El.className='col6'; 8106 var tipAmount = $(this).find('.column-tip').text().replace('$',''); 8107 col6El.innerHTML = parseFloat(tipAmount) || ' '; 8108 tipTotal += parseFloat(tipAmount) || 0; 8109 8110 rowEl.append(col1El); 8111 rowEl.append(col2El); 8112 // rowEl.append(col3El); 8113 if (GLO.Data.provider.report.reportCanViewPrice) { 8114 rowEl.append(col4El); 8115 } 8116 if (GLO.Data.provider.report.reportCanViewCommission) { 8117 rowEl.append(col5El); 8118 } 8119 if (GLO.Data.provider.report.reportCanViewTip) { 8120 rowEl.append(col6El); 8121 } 8122 8123 itemSectionEl.append(rowEl); 8124 8125 } 8126 });
8127 8128 var itemTotalSectionEl = document.createElement("div"); 8129 itemTotalSectionEl.className='section'; 8130 8131 var totalRowEl = document.createElement("div"); 8132 totalRowEl.className='row totalRow'; 8133 var col1El = document.createElement("div"); 8134 col1El.className='col1'; 8135 col1El.innerHTML = 'Totals'; 8136 var col2El = document.createElement("div"); 8137 col2El.className='col2'; 8138 col2El.innerHTML = ' '; 8139 var col3El = document.createElement("div"); 8140 col3El.className='col3'; 8141 col3El.innerHTML = ''; 8142 var col4El = document.createElement("div"); 8143 col4El.className='col4'; 8144 8145 if (serviceTotal > 0) { 8146 col4El.innerHTML = UTIL.displayMoney(serviceTotal, false, false, true); 8147 } else { 8148 col4El.innerHTML = ' '; 8149 } 8150 8151 var col5El = document.createElement("div"); 8152 col5El.className='col5'; 8153 8154 if (commissionTotal > 0) { 8155 col5El.innerHTML = UTIL.displayMoney(commissionTotal, false, false, true); 8156 } else { 8157 col5El.innerHTML = ' '; 8158 } 8159 8160 var col6El = document.createElement("div"); 8161 col6El.className='col6'; 8162 8163 if (tipTotal > 0) { 8164 col6El.innerHTML = UTIL.displayMoney(tipTotal, false, false, true); 8165 } else { 8166 col6El.innerHTML = ' '; 8167 } 8168 8169 totalRowEl.append(col1El); 8170 totalRowEl.append(col2El); 8171 // totalRowEl.append(col3El); 8172 if (GLO.Data.provider.report.reportCanViewPrice) { 8173 totalRowEl.append(col4El); 8174 } 8175 if (GLO.Data.provider.report.reportCanViewCommission) { 8176 totalRowEl.append(col5El); 8177 } 8178 if (GLO.Data.provider.report.reportCanViewTip) { 8179 totalRowEl.append(col6El); 8180 } 8181 8182 itemTotalSectionEl.append(totalRowEl); 8183 8184 // itemsWrapperEl.append(staffNameEl); 8185 // itemsWrapperEl.append(dateRangeEl); 8186 itemsWrapperEl.append(itemSectionEl); 8187 itemsWrapperEl.append(itemTotalSectionEl); 8188 itemsWrapperEl.innerHTML += `<div style="break-after:page"></div>`; 8189 8190 flexEl.append(itemsWrapperEl); 8191 reportEl.append(flexEl); 8192 }); 8193 8194 var reportWrapperEl = document.querySelector('.thermal-receipt'); 8195 reportWrapperEl.innerHTML=''; 8196 reportWrapperEl.append(reportEl); 8197 8198 8199 // console.log(reportWrapperEl.innerHTML); 8200 // UI.Print.print(document.documentElement.outerHTML,true,false); 8201 UI.Print.print(document.getElementsByClassName('thermal-receipt')[0].innerHTML,true,false) 8202 } else { 8203 //staff ids in the result set 8204 } 8205 } 8206 else { 8207 //do nothing 8208 //display error message, log error 8209 } 8210 } 8211 8212 //for print from iOS to receipt printer 8213 function _getSalesDetailRaster(reportText,start,end,jprocessing) { 8214 8215 GLO.Popup.closeIfExist(jprocessing); 8216 if ((typeof(reportText) !== 'undefined') && (reportText !== null) && reportText !== '') { 8217 SA.App.sendToiOSStarPrinter(reportText); 8218 } 8219 else { 8220 GLO.Popup.closeIfExist(jprocessing); 8221 GLO.UI.Form.resetProcessing(); 8222 new GLO.Popup.Error('Unable to print report to selected printer.'); 8223 8224 } 8225 8226 8227 // var uri = GLO.Link.WebsiteDomain + 'mobilepay/getRasterReceiptText'; 8228 // var uri = 'http://www.test2.com/reports/saleshistory?sfilter=&start=04/01/2024&end=5/19/2024&inventoryfilter=-1&isEmp=1'; 8229 8230 // var cleanedHtmData= htmData.outerHTML().replace(/ no-cents| line-item-darker| line-item-normal| line-item-smaller| line-item-larger| line-item-big| line-item-very-big/gi, function (x) { 8231 // return ''; 8232 // }); 8233 8234 // var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, "data":cleanedHtmData, contentType: "application/xml" }) 8235 // .success(function(data, textStatus, jqXHR) { 8236 // console.log(data); 8237 // GLO.Popup.closeIfExist(jprocessing); 8238 // if ((typeof(data) !== 'undefined') && (data !== null) && data !== '') { 8239 // SA.App.sendToiOSStarPrinter(data); 8240 // } 8241 // else { 8242 // GLO.Popup.closeIfExist(jprocessing); 8243 // GLO.UI.Form.resetProcessing(); 8244 // new GLO.Popup.Error('Invalid receipt data. Please try again or Send receipt via email or text.'); 8245 // } 8246 8247 // }) 8248 // .error(function(jqXHR, textStatus, errorThrown) { 8249 // GLO.Popup.closeIfExist(jprocessing); 8250 // GLO.UI.Form.resetProcessing(); 8251 // new GLO.Popup.Error('Unable to print receipt to selected printer. Please try again or Send receipt via email or text.'); 8252 // }); 8253 } 8254 8255 function _printByStaff3(staffid) { 8256 GLO.Popup.close($('#pop-select-print-staff-sales-summary').closest('.glopop')); 8257 8258 var jtbl = $('#report-sales-history .tablesorter'); 8259 //var thead = _cleanRow(jtbl.find('thead > tr')).outerHTML(); 8260 var tbody = _getPrintByStaff(jtbl, staffid); 8261 8262 var tbl = '<table class="tablesorter" style="width: 100%;">
8262' + tbody + '</table>'; 8263 var ft = '<div id="staff-printout-footer" style="color: #666;"><small>printed </small><i>' + new Date().toPrettyDate(!GLO.Info.isMobile()) + '</i></div>'; 8264 var htm = '<div id="print-receipt" class="hide sales-history">' + tbl + ft + '</div>'; 8265 8266 UI.Print.print(htm, null, false); 8267 setTimeout(function() { $('#print-report-button > a').click(); }, 900); 8268 } 8269 8270 function _reportDateRange() { 8271 var j = $('#report-sales-history'); 8272 var start = new Date(j.find('.Report_Begin_dt').val()); 8273 var end = new Date(j.find('.Report_End_dt').val()); 8274 8275 if (start.getTime() == end.getTime()) { 8276 return start.toSADate(true); 8277 } else { 8278 return start.toSADate(true) + ' - ' + end.toSADate(true); 8279 } 8280 } 8281 8282 function _getPrintByStaff(jtbl, staffid) { 8283 var trs = jtbl.find('.service-row'); 8284 var trStaffPrint = '', tbody = '', prevStaff = null, priceTotal = 0, tipTotal = 0, isFirst = true; 8285 var searchDate = _reportDateRange(); 8286 8287 for (var i=0; i < trs.length; i++) { 8288 //var currStaff = UTIL.directTagOnly(trs.eq(i).find('.column-staff')); 8289 var currStaff = trs.eq(i).find('.column-staff').attr('staff_id'); 8290 8291 if (!UTIL.isEmpty(staffid)) { 8292 if (prevStaff === null && currStaff == staffid) { 8293 prevStaff = currStaff; 8294 tbody += _staffHeaderRow(UTIL.directTagOnly(trs.eq(i).find('.column-staff')), searchDate, i, isFirst); 8295 } 8296 } else if (prevStaff != currStaff) { 8297 if (prevStaff !== null) { 8298 tbody += _staffFooter(trStaffPrint, trs.eq(i), priceTotal, tipTotal); 8299 trStaffPrint = ''; 8300 } 8301 8302 prevStaff = currStaff; 8303 tbody += _staffHeaderRow(UTIL.directTagOnly(trs.eq(i).find('.column-staff')), searchDate, i, isFirst); 8304 isFirst = false; 8305 priceTotal = tipTotal = 0; 8306 } 8307 8308 if (UTIL.isEmpty(staffid) || currStaff == staffid) { 8309 var price = UTIL.coalesceMoney(trs.eq(i).find('.column-price').text().replace('$', '')); 8310 8311 if (GLO.Data.provider.commission_fee_type_cd == 10) { 8312 price -= UTIL.coalesceMoney(trs.eq(i).find('.column-staff-fee').text().replace('$', '')); 8313 trs.eq(i).find('.column-price').text(UTIL.displayMoney(price)); 8314 } 8315 8316 priceTotal += price; 8317 tipTotal += UTIL.coalesceMoney(trs.eq(i).find('.column-tip').text().replace('$', '')); 8318 trStaffPrint += _cleanRow(trs.eq(i)).outerHTML(); 8319 } 8320 } 8321 8322 if (i > 0) { 8323 tbody += _staffFooter(trStaffPrint, trs.eq(i-1), priceTotal, tipTotal); 8324 } 8325 8326 return '<tbody>' + tbody + '</tbody>'; 8327 } 8328 8329 function _staffFooter(trStaffPrint, tr, priceTotal, tipTotal) { 8330 tr = _cleanRow(tr); 8331 tr.css({ "border-top": "1px solid #666" }); 8332 8333 var tds = tr.find('td'); 8334 8335 for (var i=0; i < tds.length; i++) { 8336 var td = tds.eq(i); 8337 8338 if (td.hasClass('column-price')) { 8339 td.html(UTIL.displayMoney(priceTotal)); 8340 } else if (td.hasClass('column-tip')) { 8341 td.html(UTIL.displayMoney(tipTotal)); 8342 } else { 8343 td.html(''); 8344 } 8345 } 8346 8347 trStaffPrint = UI.sortTable(trStaffPrint, 'purchase-date'); 8348 return trStaffPrint + tr.outerHTML(); 8349 } 8350 8351 function _cleanRow(tr, isHeader) { 8352 tr = tr.clone(); 8353 8354 tr.find('.column-staff').remove(); 8355 tr.find('.column-cost').remove(); 8356 tr.find('.column-profit').remove(); 8357 tr.find('.commission-cell').remove(); 8358 8359 return tr; 8360 } 8361 8362 function _staffHeaderRow(staffName, searchDate, rowNumber, isFirst) { 8363 var colspan = 3, pt = 80; 8364 8365 if (rowNumber == 0 || isFirst) { pt = 4; } 8366 var css = 'padding-top: ' + pt + 'px; padding-bottom: 8px; letter-spacing: 1px; text-align: center; font-weight: bold; font-size: large; color: black;'; 8367 8368 if (innerWidth >= 360) { ++colspan; } 8369 if (innerWidth >= 420) { ++colspan; } 8370 if (innerWidth >= 600) { ++colspan; } 8371 8372 return '<tr> <td colspan="' + colspan + '" style="' + css + '">' + staffName + ': ' + searchDate + '</td></tr>'; 8373 } 8374 8375 function _getPriceLabel(price, discount, addOnFee, split, splitPercent, staffServiceFee, membershipCommissionPriceBase) { 8376 var priceLabel = 'Price'; 8377 var isBizSplitDiscount = UTIL.coalesceInt(split, GLO.Data.provider.commission_split_discount_cd); // ($.trim(split).toLowerCase() == 'business'); 8378 var isBizSplitFee = UTIL.coalesceInt(split, GLO.Data.provider.commission_split_fee_cd); 8379 8380 if (membershipCommissionPriceBase > 0) { 8381 price = UTIL.coalesceMoney(membershipCommissionPriceBase); 8382 priceLabel += ' <small>(Membership Commission Price Base)</small>'; 8383 } else if (discount > 0 && !isBizSplitDiscount) { 8384 //if (split != 2) { //= subtract discount, unless split is from business 8385 price = UTIL.coalesceMoney(price) - UTIL.coalesceMoney(discount); 8386 priceLabel += ' <small>after subtracting ' + UTIL.displayMoney(discount) + ' discount</small>'; 8387 } 8388 8389 if (addOnFee > 0 && !isBizSplitDiscount) { 8390 //if (split != 2) { //= subtract discount, unless split is from business 8391 price = UTIL.coalesceMoney(price) + UTIL.coalesceMoney(addOnFee); 8392 priceLabel += ' <small>after adding ' + UTIL.displayMoney(addOnFee) + ' add-on fee</small>'; 8393 } 8394 8395 if (GLO.Data.provider.commission_fee_type_cd == 10 && UTIL.coalesceMoney(staffServiceFee) !== 0) { 8396 price = UTIL.coalesceMoney(price) - UTIL.coalesceMoney(staffServiceFee); 8397 priceLabel += ' <small>after subtracting ' + UTIL.displayMoney(staffServiceFee) + ' staff service fee</small>'; 8398 } 8399 8400 return '<p id="custom-commission-service-price"><label>' + priceLabel + '</label><b>' + UTIL.displayMoney(price, false, false, true) + '</b></p>'; 8401 } 8402 _conRptSales.openCustomCommissionFromCellSummary = function() {
8403 var tr = $('#report-sales-history').find('td.cell-summary-selected').closest('tr'); 8404 8405 var scheduleInventoryId = UTIL.coalesceInt(tr.attr('schedule_inventory_id')); 8406 var scheduleId = UTIL.coalesceInt(tr.attr('schedule_id')), scid = UTIL.coalesceInt(tr.attr('schedule_client_id')); 8407 var staffName = tr.find('.column-staff').text(); 8408 var serviceName = tr.find('.column-name').text(); 8409 8410 var tdCommission = tr.find('.commission-cell'); 8411 var commission = UTIL.coalesceMoney(UTIL.directTagOnly(tdCommission).replace('$', '')); 8412 var actualCommissionPercent = tdCommission.attr('actual_commission_pct'); 8413 8414 //var price = UTIL.coalesceMoney(tr.find('.column-price').text().replace('$', '')); //cannot use this value as displayed price might be different for different provider settings 8415 var price = UTIL.coalesceMoney(tr.attr('price_mn')); 8416 8417 var discount = UTIL.coalesceMoney(tr.find('.column-discount').text().replace('$', '')); 8418 var addOnFee = UTIL.coalesceMoney(tr.find('.column-add-on').text().replace('$', '')); 8419 var split = tr.attr('commission_split_cd'), splitPercent = tr.attr('commission_split_pct'); 8420 var staffServiceFee = UTIL.coalesceMoney(tr.find('.column-staff-fee').text().replace('$', '')); 8421 //var isProductSale = UTIL.parseBool(tr.hasClass('product-row')); 8422 var membershipCommissionPriceBase = UTIL.coalesceMoney(tr.attr('membership_commission_price_base_mn')); 8423 8424 var msg1 = '<p style="text-align: center;">' + staffName + ' ' + serviceName + '</p>'; 8425 var priceHtm = _getPriceLabel(price, discount, addOnFee, split, splitPercent, staffServiceFee, membershipCommissionPriceBase); 8426 var msg = msg1 + priceHtm; 8427 8428 _openCustomCommission(scheduleId, scid, scheduleInventoryId, msg, commission, staffServiceFee); 8429 } 8430 function _openCustomCommission(scheduleId, scid, scheduleInventoryId, msg, commission, staffServiceFee) { 8431 var dollarSign = '<span class="dollar-sign" style="margin-left: 12px;">$</span>'; 8432 8433 var labelCommission = '<label for="Custom_Commission_mn">Commission</label>'; 8434 var inputCommission = '<input type="text" id="Custom_Commission_mn" value="' + UTIL.displayMoney(commission, true) + '"/>'; 8435 var tr1 = '<tr><td>' + labelCommission + '</td><td>' + dollarSign + inputCommission + '</td></tr>'; 8436 8437 if (!UTIL.isEmpty(scheduleInventoryId)) { 8438 var tr2 = ''; 8439 } else { 8440 var labelFee = '<label for="Staff_Service_Fee_mn">Staff Service Fee</label>'; 8441 var inputFee = '<input type="text" id="Staff_Service_Fee_mn" value="' + UTIL.displayMoney(staffServiceFee, true) + '"/>'; 8442 var tr2 = '<tr><td>' + labelFee + '</td><td>' + dollarSign + inputFee + '</td></tr>'; 8443 } 8444 8445 var tbl = '<table style="margin: auto; margin-bottom: 16px;">' + tr1 + tr2 + '</table>'; 8446 8447 var htm = '<div id="pop-custom-commission" schedule_id="' + scheduleId + '" schedule_client_id="' + $.trim(scid) + '" schedule_inventory_id="' + scheduleInventoryId + '">' + msg + tbl + '</div>'; 8448 var jpop = GLO.Popup.Custom.openSimple(htm, 'Custom Commission', GLO.Report.Sales.saveCustomCommission); 8449 var btnResetLabel = 'Reset'; 8450 8451 if (innerWidth > 550) { 8452 btnResetLabel = 'Reset to Default'; 8453 jpop.find('.pop-buttons').css({ "min-width": "500px" }); 8454 } 8455 8456 if (UTIL.isEmpty(scheduleInventoryId)) { 8457 var btnReset = '<span class="btnAdd btnReset" style="position: absolute; right: 4px;"><a onclick="GLO.Report.Sales.resetCustomCommission()">' + btnResetLabel + '</a></span>'; 8458 jpop.find('.btnSave').css({ "position": "relative", "right": "inherit", "margin": "0" }).after(btnReset); 8459 } 8460 8461 var price = UTIL.coalesceMoney(jpop.find('#custom-commission-service-price b').text().replace('$', '')); 8462 var pct = parseInt(UTIL.coalesceMoney(commission/price) * 100); 8463 var btnPercentCommission = '<span id="btnPercentCommission" class="btnAdd"><a onclick="GLO.Report.Sales.openCustomCommissionChangePercent()">' + pct + '%</a></span>'; 8464 jpop.find('#Custom_Commission_mn').after(btnPercentCommission); 8465 } 8466 8467 _conRptSales.openCustomCommissionChangePercent = function() { 8468 var pct = $('#pop-custom-commission #btnPercentCommission > a').text().replace('%', ''); 8469 var htmPercent = '<input id="Custom_Commission_pct" type="number" value="' + pct + '" min="0" max="100" style="width: 50px; letter-spacing: 1px; text-align: center; font-weight: bold;">'; 8470 var htm = '<div id="pop-custom-commission-percent">' + htmPercent + '</div>'; 8471 8472 var jpop = GLO.Popup.Custom.openSimple(htm, 'Change Commission Percent for this Service'); 8473 GLO.Popup.Custom.singleButtonNew(jpop, 'Change', GLO.Report.Sales.changeCustomCommissionPercent).find('> a'); 8474 } 8475 _conRptSales.changeCustomCommissionPercent = function() { 8476 var jPopPercent = $('#pop-custom-commission-percent').closest('.glopop'); 8477 var pct = parseInt(jPopPercent.find('#Custom_Commission_pct').val()); 8478 8479 var jPopMain = $('#pop-custom-commission').closest('.glopop'); 8480 var price = UTIL.coalesceMoney(jPopMain.find('#custom-commission-service-price b').text().replace('$', '')); 8481 var newCommission = UTIL.displayMoney(pct/100 * price, true); 8482 8483 jPopMain.find('#Custom_Commission_mn').val(newCommission); 8484 jPopMain.find('#btnPercentCommission > a').text(pct + '%'); 8485 8486 GLO.Popup.close(jPopPercent); 8487 } 8488 8489 _conRptSales.resetCustomCommission = function() { 8490 var jpop = $('#pop-custom-commission').closest('.glopop'); 8491 jpop.find('#Custom_Commission_mn').val(''); 8492 jpop.find('#Staff_Service_Fee_mn').val(''); 8493 8494 GLO.UI.Form.beginProcessing( jpop.find('.btnReset') ); 8495 _conRptSales.saveCustomCommission(true); 8496 } 8497 _conRptSales.saveCustomCommission = function(isReset) { 8498 var jpop = $('#pop-custom-commission'); 8499 var scheduleId = jpop.attr('schedule_id'), scid = UTIL.coalesceInt(jpop.attr('schedule_client_id')), scheduleInventoryId = jpop.attr('schedule_inventory_id'); 8500 var commission = jpop.find('#Custom_Commission_mn').val(); 8501 8502 if (!UTIL.isEmpty(scheduleInventoryId)) { 8503 var url = GLO.Link.WebsiteDomain + 'schedule/CustomCommissionProduct?siid=' + scheduleInventoryId; 8504 } else { 8505 var url = GLO.Link.WebsiteDomain + 'schedule/CustomCommission?scheduleid=' + scheduleId; 8506 var fee = jpop.find('#Staff_Service_Fee_mn').val(); 8507 8508 if (!UTIL.isEmpty(scid)) { 8509 url += '&scid=' + scid; 8510 } 8511 8512 if (!UTIL.isEmpty(fee)) { 8513 url += '&fee=' + UTIL.coalesceMoney(fee); 8514 } 8515 } 8516 8517 if (!UTIL.isEmpty(commission)) { 8518 url += '&commission=' + UTIL.coalesceMoney(commission); 8519 } 8520 8521 if (isReset) { 8522 url += '&isReset=true'; 8523 } 8524 8525 jpop = jpop.closest('.glopop'); 8526 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 8527 GLO.Popup.close( $('#pop-help-cell-summary').closest('.glopop') ); 8528
8529 $.ajax({ type: "POST", url: url, "cache": false, data: {} }) 8530 .success(function(data, textStatus, jqXHR) { 8531 if (isReset) { 8532 var msg = '<p>Commission and Staff Service Fee reset to default</p>'; 8533 var tr = $('#report-sales-history').find('tr[schedule_id="' + scheduleId + '"]'); 8534 } else { 8535 commission = UTIL.displayMoney(commission); 8536 fee = UTIL.displayMoney(fee); 8537 8538 if (commission == '') { commission = '$0'; } 8539 if (fee == '') { fee = '$0'; } 8540 8541 if (!UTIL.isEmpty(scheduleInventoryId)) { 8542 var msg = '<p>Product Commission updated to: ' + commission + '<p>'; 8543 var tr = $('#report-sales-history').find('tr[schedule_inventory_id="' + scheduleInventoryId + '"]'); 8544 } else { 8545 var msg = '<p>Service Commission updated to: ' + commission + '<p><p>Staff Service Fee updated to: ' + fee + '</p>'; 8546 var tr = $('#report-sales-history').find('tr[schedule_id="' + scheduleId + '"]'); 8547 tr.find('.column-staff-fee').text(fee); 8548 } 8549 } 8550 8551 tr.find('.commission-cell').text(commission); 8552 GLO.Popup.close(jpop); 8553 GLO.Popup.Success.open(msg); 8554 GLO.Report.Template.search(); 8555 }) 8556 .error(function(jqXHR, textStatus, errorThrown) { 8557 GLO.Popup.Error('Unable to customize commission at this time. Please try again.'); 8558 GLO.UI.Form.resetProcessing(); 8559 }); 8560 } 8561 8562 _conRptSales.openHelpApptvsProductDate = function(element, serviceCount, productCount, apptStartDate, productPurchaseDate) { 8563 var msg1 = '<h4>Ticket has ' + UTIL.pluralLabel(serviceCount, 'service') + ' and ' + UTIL.pluralLabel(productCount, 'product') + '</h4>'; 8564 var arrow = ' <b class="arrow-right">➜</b> '; 8565 8566 if (serviceCount > 0 && productCount > 0) { 8567 var header = 'Appointment + Product Purchase Date Different'; 8568 var labelProductPurchaseDate = '<b class="narrow-text">Product Purchase Date</b>'; 8569 var labelApptStartDate = '<b class="narrow-text">Appointment Start Date</b>'; 8570 8571 var labelServiceTicketDate = '<b class="narrow-text">Service Ticket Date</b>'; 8572 var labelProductTicketDate = '<b class="narrow-text">Product Ticket Date</b>'; 8573 8574 var dtAppt = labelApptStartDate + ' <i>' + apptStartDate + '</i>'; 8575 var dtProd = labelProductPurchaseDate + ' <i>' + productPurchaseDate + '</i>'; 8576 8577 var msg2a = dtAppt + ' and ' + dtProd + ' are different'; 8578 var msg2b = 'So the ' + labelServiceTicketDate + ' and ' + labelProductTicketDate + ' are different on this appointment'; 8579 var msg2 = '<p>' + msg2a + arrow + msg2b + '</p>'; 8580 8581 var rptSalesSummary = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/sales#tab=sales-summary\')" style="font-weight: bold;">Sales Summary</a>'; 8582 var rptSalesDetail = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/sales#tab=sales-history\')" style="font-weight: bold;">Sales Detail</a>'; 8583 //var rptOther = ' and on the Staff Summary and Staff Goal reports'; 8584 8585 var rptException = '<i class="narrow-text">like on the ' + rptSalesSummary + ' and ' + rptSalesDetail + ' reports where the sales will show up on the ' + labelProductPurchaseDate + '</i>'; 8586 var payProductDateExplain = '<span class="narrow-text">(the date the product payment was made)</span>'; 8587 8588 var msg3 = '<p style="letter-spacing: 0;">This ticket\'s service sales will show up on reports on the appointment start date</p>'; 8589 var msg4 = '<p>This ticket prouduct sales will show up on some reports on the product sale date ' + payProductDateExplain + rptException + '</p>'; 8590 } else { 8591 var header = 'Ticket Info'; 8592 var msg2 = '', msg3 = '', msg4 = ''; 8593 } 8594 8595 var htm = '<div id="pop-help-appt-vs-product-date">' + msg1 + msg2 + msg3 + msg4 + '</div>'; 8596 GLO.Popup.Info.open(htm, header); 8597 } 8598 8599 _conRptSales.changeIncludeUnpaid = function() { 8600 if ($('#Include_Unpaid_Tickets_fl').prop('checked')) { 8601 var isIncludeUnpaid = '1'; 8602 } else { 8603 var isIncludeUnpaid = '0'; 8604 } 8605 8606 UTIL.setCookie('sales-detail-display-pay-warning', isIncludeUnpaid); 8607 UTIL.setCookie('sales-detail-is-include-unpaid', isIncludeUnpaid); 8608 } 8609 8610 _conRptSales.helpIncludeUnpaid = function() { 8611 var msg1 = '<p>When checked all services and products are returned <span class="narrow-text">(that match report filter)</span></p>'; 8612 var msg2 = '<p></p>'; 8613 var msg3 = '<p>When un-checked only tickets that are either checked-out or have a payment <span class="narrow-text">(includes tickets partially paid)</span></p>'; 8614 var msg4 = '<p></p>'; 8615 8616 var header = '<b style="white-space: nowrap;">Sales Detail Report:</b> <b style="white-space: nowrap;">Include Un-Paid Tickets</b>'; 8617 var htm = '<div id="pop-help-include-unpaid">' + msg1 + msg2 + msg3 + msg4 + '</div>'; 8618 GLO.Popup.Info.open(htm, ); 8619 } 8620 8621 return _conRptSales; 8622})(); 8623 8624
8625GLO.Report.CreditCardMerged = (function() { 8626 function _conRptCC2() { } 8627 8628 _conRptCC2.init = function() { 8629 UI.initTableSorter( $('table.tablesorter:visible') ); 8630 8631 GLO.Report.setupFastClick(); 8632 } 8633 8634 return _conRptCC2; 8635})(); 8636 8637 8638GLO.Report.CreditCard = (function() { 8639 function _conRptCC() { } 8640 8641 _conRptCC.currentTab = 1; 8642 _conRptCC.MAX_TAB = 3; 8643 8644 _conRptCC.init = function() { 8645 var rptHistory = $('#report-payment-history') 8646 rptHistory.find('.Payment_Method_cd').val(10).addClass('hide').addClass('use'); 8647 8648 $('#report-unsettled-transactions .Merchant_id').attr('onchange', 'GLO.Report.CreditCard.fiterUnSettled(this)'); 8649 8650 _conRptCC.postSearch(rptHistory, 'payment-history'); 8651 _addBuyerAutoComplete(); 8652 8653 var initTab = GLO.Report.Template.init(); //GLO.Report.setupFastClick(); 8654 initTab = _getTabNumber(initTab); 8655 _conRptCC.goToTab(initTab); 8656 } 8657 8658 function _getTabNumber(tab) { 8659 tab = String(tab).toLowerCase(); 8660 8661 if (tab === 'unsettled-transactions' || tab == '1') { 8662 tab = 1; 8663 } else if (tab === 'settled-transactions' || tab == '2') { 8664 tab = 2; 8665 } else if (tab === 'refund-history' || tab == '3') { 8666 tab = 3; 8667 } else { 8668 if (tab > _conRptCC.MAX_TAB) { 8669 tab = _conRptCC.MAX_TAB; 8670 } else {
8671 tab = _conRptCC.currentTab; 8672 } 8673 } 8674 8675 return tab; 8676 } 8677 8678 _conRptCC.goToTab = function(tab) { 8679 $('#report-unsettled-transactions').addClass('hide'); 8680 $('#report-settled-transactions').addClass('hide'); 8681 $('#report-refund-history').addClass('hide'); 8682 8683 if (tab === 1) { 8684 var hashTab = 'unsettled-transactions'; 8685 $('#report-unsettled-transactions').removeClass('hide'); 8686 } else if (tab === 2) { 8687 var hashTab = 'settled-transactions'; 8688 $('#report-settled-transactions').removeClass('hide'); 8689 } else if (tab === 3) { 8690 var hashTab = 'refund-history'; 8691 $('#report-refund-history').removeClass('hide'); 8692 } 8693 8694 var backColor = $('.shadow-content0').css('backgroundColor'); 8695 var jhead = $('#report-portal-header'); 8696 var oj = jhead.find('table tr td span b'); 8697 8698 oj.each(function() { 8699 $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent'); 8700 }); 8701 8702 oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent(); 8703 oj.addClass('report-tab'); 8704 oj.css('backgroundColor', backColor); 8705 8706 _conRptCC.currentTab = tab; 8707 document.location.hash = 'tab=' + hashTab; 8708 } 8709 8710 function _addBuyerAutoComplete() { 8711 var jAuto = $('.buyer-autocomplete'); 8712 var jselect = $('td.merchant-account-column'); 8713 8714 if (jselect.find('option').length > 2) { 8715 $('th.merchant-account-column label').html('Merchant Account'); 8716 } else { 8717 $('th.merchant-account-column').remove(); 8718 jselect.remove(); 8719 } 8720 8721 for (var i=0; i < jAuto.length; i++) { 8722 var jBuyer = jAuto.eq(i); 8723 8724 jBuyer.autocomplete({ 8725 source: GLO.Link.Object.Provider.Ajax + 'ClientAndStaffSearch', 8726 minLength: 2, 8727 select: function(event, ui) { 8728 jBuyer.attr('buyer_id', ui.item.id); 8729 } 8730 }); 8731 8732 jAuto.eq(i).data("ui-autocomplete")._renderItem = function(ul, item) { 8733 var cssClass = ""; 8734 if (item.id.substring(0,1) === 'S') { cssClass = " class='item-staff'"; } 8735 8736 return $("<li" + cssClass + "></li>") 8737 .data("ui-autocomplete-item", item) 8738 .append("<a>" + item.label + "</a>") 8739 .appendTo(ul); 8740 } 8741 } 8742 8743 //jAuto.focus(); 8744 } 8745 8746 _conRptCC.changeBuyer = function(element) { 8747 if (UTIL.isEmpty(element.value)) { $(element).attr('buyer_id', ''); } 8748 } 8749 8750 _conRptCC.fiterUnSettled = function(select) { 8751 var rpt = $('.report-container:visible'); 8752 var tr = rpt.find('tbody tr'); 8753 var merchantId = select.value; 8754 var tip = 0, refund = 0, total = 0; 8755 8756 if (!UTIL.isEmpty(merchantId)) { 8757 for (var i=0; i < tr.length; i++) { 8758 if (tr.eq(i).attr('merchant_id') == merchantId) { 8759 tr.eq(i).removeClass('hide'); 8760 tip += UTIL.coalesceMoney(tr.eq(i).find('td.tip').text().replace('$', '')); 8761 total += UTIL.coalesceMoney(tr.eq(i).find('td.payment').text().replace('$', '')); 8762 refund += UTIL.coalesceMoney(tr.eq(i).find('td.refund').text().replace('$', '')); 8763 } else { 8764 tr.eq(i).addClass('hide'); 8765 } 8766 } 8767 } else { 8768 for (var i=0; i < tr.length; i++) { 8769 tr.eq(i).removeClass('hide'); 8770 tip += UTIL.coalesceMoney(tr.eq(i).find('td.tip').text().replace('$', '')); 8771 total += UTIL.coalesceMoney(tr.eq(i).find('td.payment').text().replace('$', '')); 8772 refund += UTIL.coalesceMoney(tr.eq(i).find('td.refund').text().replace('$', '')); 8773 } 8774 } 8775 8776 var tfoot = rpt.find('tfoot'); 8777 tfoot.find('.tip').text(UTIL.displayMoney(tip)); 8778 tfoot.find('.refund').text(UTIL.displayMoney(refund)); 8779 tfoot.find('.payment').text(UTIL.displayMoney(total)); 8780 } 8781 8782 _conRptCC.movePrev = function() { 8783 GLO.Report.Template.moveDates(-1); 8784 _conRptCC.searchTransaction(); 8785 } 8786 8787 _conRptCC.moveNext = function() { 8788 GLO.Report.Template.moveDates(1); 8789 _conRptCC.searchTransaction(); 8790 } 8791 8792 _conRptCC.searchTransaction = function(launchSettleBatch) { 8793 var jhead = $('.report-search-header:visible'); 8794 var jrpt = $('.entire-report:visible'); 8795 var rtype = jrpt.attr('id').replace('report-', ''); 8796 jrpt = jrpt.find('.report-container'); 8797 8798 var start = UTIL.cleanString(jhead.find('.Report_Begin_dt').val()) 8799 var end = UTIL.cleanString(jhead.find('.Report_End_dt').val()); 8800 var mid = jhead.find('.Merchant_id').val(); 8801 var uhash = 'rtype=' + rtype + '&merchant_id=' + mid; 8802 8803 if (rtype === 'unsettled-transactions' || rtype === 'batch') { 8804 8805 } else if (!_isValidDate(start, end)) { 8806 return; 8807 } else { 8808 var buyer = jhead.find('.buyer-autocomplete').attr('buyer_id'); 8809 uhash += '&start=' + start + '&end=' + end; 8810 8811 if (!UTIL.isEmpty(buyer)) { 8812 if (buyer.substring(0, 1) === 'S') { 8813 uhash += '&payment_from_staff_id=' + buyer.substring(1); 8814 } else { 8815 if (buyer.substring(0, 1) === 'C') { buyer = buyer.substring(1); } 8816 8817 uhash += '&payment_from_client_id=' + buyer; 8818 } 8819 } 8820 } 8821 8822 var url = GLO.Link.Page.Provider.Home + 'report/SearchCreditTransaction?' + uhash; 8823 var searchBtn = jhead.parent().find('.btnSearch:visible') 8824 GLO.UI.Form.beginProcessing(searchBtn); 8825
8826 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 8827 .success(function(data, textStatus, jqXHR) { 8828 GLO.UI.Form.resetProcessing(); 8829 GLO.Report.CreditCard.searchTransactionLoad(jrpt, data); 8830 8831 if (launchSettleBatch) { 8832 GLO.Report.CreditCard.settleBatch(); 8833 } 8834 }) 8835 .error(function(jqXHR, textStatus, errorThrown) { 8836 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 8837 GLO.UI.Form.resetProcessing(); 8838 }); 8839 } 8840 8841 _conRptCC.searchTransactionLoad = function(jrpt, data) { 8842 GLO.UI.Form.resetProcessing(); 8843 8844 if (!UTIL.isEmpty(data)) { 8845 jrpt.html(data); 8846 UI.initTableSorter( jrpt.find('table.tablesorter:visible') ); 8847 } else { 8848 GLO.Popup.Info(SA.Resource.NoResultsFound); 8849 } 8850 } 8851 8852 function _isValidDate(start, end) { 8853 if (!UTIL.isDate(start)) { 8854 GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('.Report_Begin_dt:visible'); }); 8855 return false; 8856 } else if (!UTIL.isDate(end)) { 8857 GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('.Report_End_dt:visible'); }); 8858 return false; 8859 } else if (new Date(start) > new Date(end)) { 8860 GLO.Popup.Warning(SA.Resource.BeginDateWarning2); 8861 return false; 8862 } else { 8863 return true; 8864 } 8865 } 8866 8867 _conRptCC.postSearch = function(jrpt, report) { 8868 jrpt = jrpt.find('table.payment-history'); 8869 jrpt.find('th#payment-header').css({ "text-align": "right" }); 8870 8871 if (jrpt.find('th#pay-meth-header').length === 1) { jrpt.find('th:last-child, td:last-child').remove(); } 8872 jrpt.find('th:last-child, td:last-child').remove(); 8873 } 8874 8875 _conRptCC.settleBatch = function() { 8876 var jrpt = $('#cc-report'); 8877 var tranCount = jrpt.find('tbody tr:not(.hide)').length; 8878 var preAuthCount = jrpt.find('tbody tr.cc-pre-auth:not(.hide)').length; 8879 var merchantName = jrpt.find('.Merchant_id option:selected'); 8880 var mName = ''; 8881 var pmid = $('#report-batch').attr('merchant_id'); 8882 var merchantCo = UserPortal.Price.Payment.getMerchantCompany(pmid, 30); //UTIL.coalesceInt(GLO.Data.provider.merchant_vendor_cd, 30); 8883 8884 if (merchantName.length > 0) { 8885 if (merchantName.text() == 'All') { 8886 mName = ' for all merchant accounts'; 8887 } else { 8888 mName = ' for ' + merchantName.text(); 8889 } 8890 } 8891 8892 var msg = '<div id="pop-settle-batch">' 8893 + '<h1 class="friendly-msg2" style="margin-bottom: 0; padding-bottom: 1px;">' + SA.Resource.SettleBatch + '?</h1>' 8894 + '<div>' 8895 + '<div id="pop-settle-batch-warning">' + SA.Resource.AfterSettleBatchCannotAddTips + '</div>' 8896 + '<div class="friendly-msg2">' + SA.Resource.Settle + ' ' + tranCount + ' ' + SA.Resource.Transactions + mName + '?</div>' //(tranCount - preAuthCount) 8897 + '<div id="pop-settle-batch-explanation">' + SA.Resource.SettleBatchHelp + '</div>' 8898 + '</div>' 8899 + '</div>'; 8900 8901 if (false && preAuthCount > 0) { //= no longer support not upgrading auths 8902 var warnMsg = '<div><h1 class="friendly-quick-msg" style="margin-bottom: 0; padding-bottom: 1px;">' + SA.Resource.AuthorizePayments + '?</h1>' 8903 + '<div class="friendly-quick-msg" style="color: Red; line-height: 200%;">'; 8904 8905 if (preAuthCount == 1) { 8906 warnMsg += '1 ' + SA.Resource.PaymentIsNotAuthorized + '<br/>' + SA.Resource.AuthorizeThisPayment + '?</div></div>'; 8907 } else { 8908 warnMsg += preAuthCount + ' ' + SA.Resource.PaymentsAreNotAuthorized + '<br/>' + SA.Resource.AuthorizeThesePayments + '?</div></div>'; 8909 } 8910 8911 var oj = new GLO.Popup.Warning(warnMsg); 8912 var jbtn = oj.getPopup().find('.pop-buttons'); 8913 8914 var btnNo = jbtn.find('.btnOk').click(function() { GLO.Report.Credit
8914Card.settleBatchQues(msg); }) 8915 btnNo.css({ "float": "none", "position": "absolute", "left": "0", "padding-left": "9px" }).addClass('btnNo').removeClass('btnOk').find('a').text('No'); 8916 8917 jbtn.append('<span class="btnSave" onclick="GLO.Report.CreditCard.upgradeBatch()" style="position: absolute; right: 0;"><a>' + SA.Resource.Yes + '</a></span>'); 8918 } else if (merchantCo === 30) { //= send email only 8919 _conRptCC.settleBatchConfirmed(); 8920 } else { 8921 _conRptCC.settleBatchQues(msg); 8922 } 8923 } 8924 8925 _conRptCC.settleBatchQues = function(msg) { 8926 var oj = new GLO.Popup.Confirm(msg, GLO.Report.CreditCard.settleBatchConfirmed); 8927 var jpop = oj.getPopup(); 8928 8929 jpop.find('.msg').css({ "text-align": "center", "padding-right": "20px" }); 8930 8931 var jbtn = jpop.find('.pop-buttons'); 8932 jbtn.find('.btnNo').css({ "padding-left": "70px" }); 8933 } 8934 8935 _conRptCC.upgradeBatch = function() { 8936 var jrpt = $('#report-unsettled-transactions'); 8937 8938 if (jrpt.length === 1) { 8939 var mid = jrpt.find('.Merchant_id').val(); 8940 var jhead = jrpt; 8941 } else { 8942 jrpt = $('#report-batch'); //tr.cc-pre-auth 8943 var jhead = $('.report-search-header:visible'); 8944 var mid = jhead.find('.Merchant_id').val(); 8945 } 8946 8947 var url = GLO.Link.WebsiteDomain + 'payment/UpgradeBatch'; 8948 8949 var jWarnPop = $('.pop-warning:visible'); 8950 GLO.UI.Form.beginProcessing( jWarnPop.find('.btnSave') ); 8951 8952 $.ajax({ type: "POST", url: url, "cache": false, data: { "merchant_id": mid } }) 8953 .success(function(data, textStatus, jqXHR) { 8954 GLO.Popup.close(jWarnPop); 8955 GLO.Report.CreditCardBatch.refresh(true); //GLO.Report.CreditCard.searchTransaction(true); //$('#report-unsettled-transactions').find('.report-search-header .btnSearch').find('a').click(); 8956 }) 8957 .error(function(jqXHR, textStatus, errorThrown) { 8958 GLO.Popup.Error('Unable to upgrade these payments at this time. Please try again.'); 8959 GLO.UI.Form.resetProcessing(); 8960 }); 8961 } 8962 8963 _conRptCC.settleBatchConfirmed = function() { 8964 var jrpt = $('#report-unsettled-transactions'); 8965 8966 if (jrpt.length === 1) { 8967 var mid = jrpt.find('.Merchant_id').val(); 8968 var jhead = jrpt; 8969 } else { 8970 jrpt = $('#report-batch'); 8971 var jhead = $('.report-search-header:visible'); 8972 var mid = jhead.find('.Merchant_id').val(); 8973 } 8974 8975 var url = GLO.Link.WebsiteDomain + 'payment/SettleBatch'; 8976 GLO.UI.Form.beginProcessing( jhead.find('.btnSave') ); 8977 8978 $.ajax({ type: "POST", url: url, "cache": false, data: { "merchant_id": mid } }) 8979 .success(function(data, textStatus, jqXHR) { 8980 _settleBatchCompleted(data, jhead); 8981 }) 8982 .error(function(jqXHR, textStatus, errorThrown) { 8983 GLO.Popup.Error('Unable to settle batch at this time. Please try again later.'); 8984 GLO.UI.Form.resetProcessing(); 8985 }); 8986 } 8987 8988 function _settleBatchCompleted(data, jhead) { 8989 GLO.UI.Form.resetProcessing(); 8990 8991 var jbatch = $(data).find('batch'); 8992 var status, amt = 0, cnt = 0, totalTransactions = 0, nm = '', msgErr = '', msgSuccess = ''; 8993 8994 for (var i=0; i < jbatch.length; i++) { 8995 amt = UTIL.coalesceMoney(jbatch.eq(i).attr('amount_mn')); 8996 cnt = UTIL.coalesceInt(jbatch.eq(i).attr('transaction_count_nr'));
8997 nm = _getMerchantBatchName(jbatch.eq(i), i); 8998 status = jbatch.eq(i).attr('status'); 8999 totalTransactions += cnt; 9000 9001 if (status.indexOf(';') !== -1) { 9002 var status0 = status.substring(0, status.indexOf(';')); 9003 } else { 9004 var status0 = status; 9005 } 9006 9007 if (status0 === 'ACCEPTED' || status0 === 'SUCCESS' || status0 === 'APPROVED') { 9008 if (!UTIL.isEmpty(nm)) { nm = '<b>' + nm + '</b>: '; } 9009 9010 if (amt > 0 && cnt > 0) { 9011 msgSuccess += '<li class="successful-batch">' + nm + SA.Resource.BatchSuccessfullySettled + ', ' + cnt + ' ' + SA.Resource.transactions_batch_amount + ': ' + _displayBatchAmount(amt) + '</li>'; 9012 } 9013 } else { 9014 var err = jbatch.eq(i).html(); 9015 9016 if (UTIL.isEmpty(err)) { 9017 if (status0 !== 'EMPTY' && status0 !== 'ACCEPTED' && status0 !== 'SUCCESS' && status0 === 'APPROVED') { 9018 err = SA.Resource.ErrorProcessingBatch; 9019 } else { 9020 err = SA.Resource.BatchIsEmpty + ', ' + cnt + ' ' + SA.Resource.transactions_batch_amount + ' = ' + _displayBatchAmount(amt) + '</li>'; 9021 } 9022 } 9023 9024 msgErr += '<li><b>' + nm + '</b>: ' + err + '</li>'; 9025 } 9026 } 9027 9028 if (i > 1) { 9029 var ul = '<div><h1 class="friendly-quick-msg">' + SA.Resource.BatchResults + '</h1><ul id="settle-batch-result">'; 9030 } else { 9031 var ul = '<div><h1 class="friendly-quick-msg">' + SA.Resource.BatchResults + '</h1><ul>'; 9032 } 9033 9034 if (!UTIL.isEmpty(msgErr)) { 9035 if (!UTIL.isEmpty(msgSuccess)) { msgErr = msgSuccess + msgErr; } 9036 9037 if (status0 === 'EMPTY') { 9038 new GLO.Popup.Warning(ul + msgErr + '</ul></div>'); 9039 } else { 9040 new GLO.Popup.Error(ul + msgErr + '</ul></div>'); 9041 } 9042 } else if (!UTIL.isEmpty(msgSuccess)) { 9043 new GLO.Popup.Success(ul + msgSuccess + '</ul></div>'); 9044 } 9045 9046 jhead.find('.btnSearch > a').click(); //if (totalTransactions > 0) { GLO.Report.CreditCard.searchTransaction(); } 9047 } 9048 9049 function _displayBatchAmount(amt) { 9050 if (amt == 0) { 9051 return '$0'; 9052 } else { 9053 return UTIL.displayMoney(amt); 9054 } 9055 } 9056 9057 function _getMerchantBatchName(batch) { 9058 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 9059 9060 if (GLO.Info.providerPackage !== 1 && mt > 9 && mt < 90) { 9061 var nm = batch.attr('mname'); 9062 9063 if (UTIL.isEmpty(nm) && !UTIL.isEmpty(batch.attr('staff_id'))) { 9064 nm = UserPortal.lookupStaffName(batch.attr('staff_id')); 9065 } 9066 9067 //if (!UTIL.isEmpty(nm)) { nm = ' for ' + nm; } 9068 return nm; 9069 } else { 9070 return ''; 9071 } 9072 } 9073 9074 return _conRptCC; 9075})(); 9076 9077 9078GLO.Report.CreditCardBatch = (function() { 9079 function _conRptCCB() { } 9080 9081 _conRptCCB.init = function() { 9082 //$('#header-icon-container').remove(); 9083 var jtbl = $('table#cc-report.tablesorter:visible'); 9084 9085 UI.initTableSorter(jtbl); 9086 var mid = GLO.Uri.query('mid'); 9087 var jmerchant = $('#report-main .Merchant_id'); 9088 9089 if (!UTIL.isEmpty(mid)) { jmerchant.val(mid); } 9090 9091 jmerchant.attr('id', 'Merchant_id').change(GLO.Report.CreditCardBatch.changeMerchant); 9092 9093 $('#report-batch-day').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 9094 , minDate: "-6m", maxDate: 0, dateFormat: "M d, yy", numberOfMonths: 1, beforeShow: UI.loadDatepicker }); 9095 _onLoad(); 9096 GLO.Report.setupFastClick(); 9097 GLO.Report.enableFullPageCheck(); 9098 GLO.Report.CellSummary.initReport(jtbl); 9099 $('#doc3').addClass('is-payment-report'); 9100 } 9101 9102 function _onLoad() { 9103 var jmerchant = $('#bd #report-main .Merchant_id'); 9104 var jhead = $('#bd #report-main .report-search-header') 9105 var co = jmerchant.find(':selected').attr('merchant_vendor_cd'); 9106 9107 if (UTIL.isEmpty(co)) { 9108 co = GLO.Data.provider.merchant_vendor_cd; 9109 } 9110 9111 if (co == 30) { 9112 jhead.find('#report-batch-day, #help-batch-header-card-connect').removeClass('hide'); 9113 jhead.addClass('display-arrows'); 9114 } else { 9115 jhead.find('#report-batch-day, #help-batch-header-card-connect').addClass('hide'); 9116 jhead.removeClass('display-arrows'); 9117 } 9118 } 9119 9120 _conRptCCB.changeMerchant = function() { 9121 _conRptCCB.refresh();
9122 _onLoad(); 9123 } 9124 9125 _conRptCCB.moveBatchDay = function(moveByDays) { 9126 var jday = $('#report-batch-day'); 9127 var day = _getSearchDate(jday); 9128 9129 if (UTIL.isEmpty(day)) { 9130 return; 9131 } 9132 9133 day.addDays(moveByDays); 9134 9135 if (UTIL.isEmpty(day)) { 9136 var fn = function() { 9137 $('#report-batch-day').focus(); 9138 } 9139 9140 GLO.Popup.Warning.open('Please Enter Batch Day', 'Batch Day Empty', fn); 9141 return; 9142 } else if (day > new Date()) { 9143 var htm = '<p>' + day.toGloDateString(true, true) + ' is in the future</p><p>No Batch Information for Future Days</p>'; 9144 GLO.Popup.Warning.open(htm, 'Invalid Day'); 9145 return; 9146 } 9147 9148 UI.setDateInput(jday, day); 9149 GLO.Report.CreditCardBatch.refresh(); 9150 } 9151 function _getSearchDate(jdt) { 9152 if (jdt.hasClass('is-sa-date')) { 9153 var dt = UTIL.fromSADate(jdt.val()); 9154 } else { 9155 var dt = UTIL.replaceAll(jdt.val(), '-', '/'); //= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone). 9156 } 9157 9158 if (UTIL.isDate(dt)) { 9159 return new Date(dt); 9160 } else { 9161 return null; 9162 } 9163 } 9164 9165 _conRptCCB.refresh = function(launchSettleBatch) { 9166 var jd = {}, jrpt = $('#report-main'); 9167 var btnRefresh = jrpt.find('#btnRefresh'); 9168 var mid = jrpt.find('#Merchant_id').val(); 9169 var dayText = jrpt.find('#report-batch-day:visible').val(); 9170 var pageTitle = SA.Resource.BatchReport; 9171 var url = GLO.Link.WebsiteDomain + 'payment/ReportBatch'; 9172 9173 if (!GLO.Report.hasReportPassword(jd)) { 9174 return; 9175 } 9176 9177 if (!UTIL.isEmpty(mid)) { 9178 url = GLO.Uri.addQueryKeyAndValue(url, 'mid=' + mid); 9179 pageTitle = jrpt.find('#Merchant_id').find(':selected').text() + ' ' + pageTitle; 9180 } 9181 9182 if (UTIL.isDate(dayText)) { 9183 var day = UTIL.fromSADate(dayText); 9184 pageTitle = dayText + ' ' + pageTitle; 9185 9186 if (!UTIL.isToday(day)) { //if (day.toGloDate() != new Date().toGloDate()) { 9187 url = GLO.Uri.addQueryKeyAndValue(url, 'day=' + day.toGloDate()); 9188 } 9189 } 9190 9191 var urlFullScreen = url; 9192 url = GLO.Uri.addQueryKeyAndValue(url, 'ispartial=1'); 9193 9194 GLO.UI.Form.beginProcessing(btnRefresh); 9195 jrpt = jrpt.find('.report-container'); 9196 9197 var ml = (jrpt.width() - 40)/2; 9198 var throbber = $('.loadingDiv').clone().find('img').css({ "margin": "40px auto", "margin-left": ml }); 9199 jrpt.html(throbber); 9200 9201 $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd }) 9202 .success(function(data, textStatus, jqXHR) { 9203 jrpt.html(data); 9204 jrpt = jrpt.find('#cc-report:visible') 9205 9206 if (jrpt.length === 1) { 9207 UI.initTableSorter(jrpt); 9208 GLO.Report.CellSummary.initReport(jrpt); 9209 } 9210 9211 GLO.UI.Form.resetProcessing(); 9212 window.history.pushState("", pageTitle, urlFullScreen); //window.history.pushState({ "pageTitle": pageTitle } , "", urlFullScreen); 9213 document.title = pageTitle; 9214 9215 if (launchSettleBatch) { 9216 GLO.Report.CreditCard.settleBatch(); 9217 } 9218 }) 9219 .error(function(jqXHR, textStatus, errorThrown) { 9220 GLO.UI.Form.resetProcessing(); 9221 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 9222 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 9223 }); 9224 } 9225 9226 _conRptCCB.addToBatch = function(checkbox) { 9227 var tr = $(checkbox).closest('tr').addClass('add-to-batch'); 9228 var sptid = tr.attr('transaction_id'); 9229 var svcCount = UTIL.coalesceInt(tr.attr('service_count_nr'), 0); 9230 var tip = UTIL.coalesceMoney(tr.find('.cc-tip').text().replace('$', '')); 9231 9232 if (svcCount > 0 && tip === 0) { 9233 new GLO.Popup.Confirm(SA.Resource.AddTipQuestion 9234 , function() { 9235 tr.find('.cc-date').find('a').click(); 9236 }
9237 , function() { GLO.Report.CreditCardBatch.addToBatchConfirmed(sptid); }); 9238 } else { 9239 _conRptCCB.addToBatchConfirmed(sptid); 9240 } 9241 } 9242 9243 _conRptCCB.addToBatchConfirmed = function(transactionId) { 9244 var url = GLO.Link.WebsiteDomain + 'payment/AddToBatch?transaction_id=' + transactionId; 9245 var btnRefresh = $('#btnRefresh:visible'); 9246 9247 GLO.UI.Form.beginProcessing(btnRefresh); 9248 9249 $.ajax({ type: "POST", url: url, "cache": false }) 9250 .success(function(data, textStatus, jqXHR) { 9251 new GLO.Popup.Success(SA.Resource.AddedToBatch + '!'); 9252 9253 $('#report-batch .add-to-batch').css({ "background-color": "lightgreen" }); 9254 9255 GLO.UI.Form.resetProcessing(); 9256 btnRefresh.find('a').click(); 9257 }) 9258 .error(function(jqXHR, textStatus, errorThrown) { 9259 GLO.UI.Form.resetProcessing(); 9260 GLO.Popup.Error('Unable to add to batch at this time. Please try again.'); 9261 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 9262 }); 9263 } 9264 9265 return _conRptCCB; 9266})(); 9267 9268 9269GLO.Report.CreditCard2 = (function() { 9270 function _conRptCC2() { } 9271 9272 _conRptCC2.init = function() { 9273 //$('#header-icon-container').remove(); 9274 9275 var jhead = $('.report-search-header'); 9276 var jmerchant = jhead.find('.Merchant_id'); 9277 var jtbl = $('#cc-report.tablesorter, #cc-ticket-report.tablesorter'); 9278 var mid = GLO.Uri.query('mid'); 9279 9280 UI.initTableSorter(jtbl); 9281 9282 if (!UTIL.isEmpty(mid)) { jmerchant.val(mid); } 9283 jmerchant.attr('id', 'Merchant_id').change(GLO.Report.CreditCard2.changeMerchant); 9284 9285 GLO.Report.Template.initDateRange(jhead, false); 9286 GLO.Report.setupFastClick(); 9287 GLO.Report.enableFullPageCheck(); 9288 _loadCCData(); 9289 _conRptCC2.displayFilterArrows(); 9290 } 9291 function _initDisplayAll() { 9292 if (innerWidth > 640) { 9293 $('#cc-search').find('.btnReportAll, .btnReportFit').remove(); 9294 } 9295 9296 GLO.Report.enableFullPageCheck(); 9297 } 9298 function _loadCCData() { 9299 var jtbl = $('#cc-report.tablesorter, #cc-ticket-report.tablesorter'); 9300 9301 UI.initTableSorter(jtbl); 9302 GLO.Report.CellSummary.initReport(jtbl); 9303 GLO.Report.initIcons(jtbl); 9304 } 9305 9306 _conRptCC2.displayFilterArrows = function() { 9307 var jfilter = $('#cc-date-range-filter'); 9308 var start = UTIL.fromSADate(jfilter.find('#report-start').val()); 9309 var end = UTIL.fromSADate(jfilter.find('#report-end').val());
9310 var days = UTIL.dayDiff(start, end) + 1; 9311 9312 if (days < 8) { 9313 jfilter.addClass('display-arrows'); 9314 } else { 9315 jfilter.removeClass('display-arrows'); 9316 } 9317 } 9318 _conRptCC2.movePrev = function(isBatch) { 9319 GLO.Report.Template.moveDates(-1); 9320 9321 if (isBatch) { 9322 GLO.Report.CreditCardBatch.refresh(); 9323 } else { 9324 _conRptCC2.search(); 9325 } 9326 } 9327 _conRptCC2.moveNext = function(isBatch) { 9328 GLO.Report.Template.moveDates(1); 9329 9330 if (isBatch) { 9331 GLO.Report.CreditCardBatch.refresh(); 9332 } else { 9333 _conRptCC2.search(); 9334 } 9335 } 9336 9337 _conRptCC2.changeMerchant = function() { 9338 var jhead = $('.report-search-header:visible'); 9339 var jbkg = jhead.find('#Booking'); 9340 var jstart = jhead.find('#report-start'); 9341 var jend = jhead.find('#report-end'); 9342 9343 if (jbkg.length > 0) { 9344 if (!UTIL.isEmpty(jbkg.val())) { 9345 _conRptCC2.search(); 9346 } 9347 } else if (jstart.length > 0) { 9348 if (!UTIL.isEmpty(jstart.val())) { 9349 _conRptCC2.search(); 9350 } 9351 } 9352 } 9353 9354 _conRptCC2.search = function() { 9355 var jrpt = $('#report-main'); 9356 var btnSearch = jrpt.find('#btnSearch'); 9357 var mid = jrpt.find('#Merchant_id').val(); 9358 var pageUrl, qstring = '', jd = {}; 9359 9360 var jbkg = jrpt.find('#booking:visible'); 9361 var bkg = jbkg.val(); 9362 var start = jrpt.find('#report-start:visible').val(); 9363 var end = jrpt.find('#report-end:visible').val(); 9364 9365 if (!UTIL.isEmpty(mid)) { 9366 var pageTitle = jrpt.find('#Merchant_id').find(':selected').text() + ' ' + SA.Resource.Report; 9367 } else { 9368 var pageTitle = SA.Resource.Report; 9369 } 9370 9371 if (!UTIL.isEmpty(mid)) { qstring += '&mid=' + mid; } 9372 9373 if (!UTIL.isEmpty(bkg)) { 9374 pageUrl = 'ReportTicket'; 9375 qstring += '&booking=' + bkg; 9376 } else if (UTIL.isEmpty(start) && UTIL.isEmpty(end) && jbkg.length) { 9377 var fn = function() { jbkg.focus(); } 9378 GLO.Popup.Warning.open('Please Enter Booking Number', 'Booking Number Empty', fn); 9379 return; 9380 } else { 9381 pageUrl = 'ReportDateRange'; 9382 qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true); 9383 } 9384 9385 if (!GLO.Report.hasReportPassword(jd)) { 9386 return; 9387 } 9388 9389 GLO.UI.Form.beginProcessing(btnSearch); 9390 if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); } 9391 9392 var url = GLO.Link.WebsiteDomain + 'payment/ReportLookupTransactions?' + qstring; 9393 var jRptData = jrpt.find('.report-container'); 9394 9395 $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd }) 9396 .success(function(data, textStatus, jqXHR) { 9397 jRptData.html(data); 9398 _loadCCData(); 9399 9400 GLO.UI.Form.resetProcessing(); 9401 pageUrl = GLO.Link.WebsiteDomain + 'payment/' + pageUrl + '?' + qstring; 9402 window.history.pushState("", pageTitle, pageUrl); 9403 }) 9404 .error(function(jqXHR, textStatus, errorThrown) { 9405 GLO.UI.Form.resetProcessing(); 9406 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 9407 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 9408 }); 9409 } 9410 9411 return _conRptCC2; 9412})(); 9413 9414 9415GLO.Report.PaymentSummary = (function() { //Used by Payment Summary + Gift Card report 9416 function _conRptPaySum() { } 9417 9418 _conRptPaySum.init = function() { 9419 _loadPaySummaryData(); 9420 9421 var jhead = $('.report-search-header'); 9422 GLO.Report.Template.initDateRange(jhead, true); 9423 9424 _setDateMin(jhead, "#report-start", "Jan 1, 2015"); 9425 _setDateMin(jhead, "#report-end", "Jan 1, 2015"); 9426 //$('#header-icon-container').remove(); 9427 9428 GLO.Report.setupFastClick(); 9429 GLO.Report.enableFullPageCheck(); 9430 9431 $('#doc3').addClass('is-payment-report'); 9432 } 9433 9434 function _setDateMin(j, id, minDate) { 9435 var jdt = j.find(id); 9436 var val = jdt.val(); 9437 9438 jdt.datepicker("option", "minDate", minDate); 9439 jdt.val(val); 9440 } 9441 9442 _conRptPaySum.viewGiftCardUseOtherLocation = function(element, event) {
9443 var tr = $('.gift-history').find('td.cell-summary-selected').closest('tr'); 9444 var minOtherPid = tr.attr('min_other_provider_id'), maxOtherPid = tr.attr('max_other_provider_id'); 9445 9446 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 9447 9448 if (!UTIL.isEmpty(minOtherPid)) { 9449 var urlGoTo = GLO.Link.WebsiteDomain + 'reports/saleshistory?isfullpage=1&paymethod=20&giftcard=' + tr.attr('gift_card_id'); 9450 var gcnr = tr.find('.gift-column-number').text(); 9451 9452 var locationName = SA.Parent.getLocationName(minOtherPid); 9453 var locationColor = SA.Parent.getLocationColor(minOtherPid); 9454 9455 if (minOtherPid == maxOtherPid) { 9456 //GLO.Popup.Processing.open('Loading Gift Card Payments at ' + locationName + '...', gcnr + ' Payments'); 9457 GLO.Staff.Filter.switchLocation(minOtherPid, locationName, locationColor, urlGoTo); 9458 } else { 9459 var locationName2 = SA.Parent.getLocationName(maxOtherPid); 9460 var locationColor2 = SA.Parent.getLocationColor(maxOtherPid); 9461 9462 var btn1 = '<p style="margin: 24px 4px; text-align: center;"><span id="btnGiftPay1" class="btnAdd"><a>View Payments at ' + locationName + '</a></span></p>'; 9463 var btn2 = '<p style="margin: 24px 4px; text-align: center;"><span id="btnGiftPay2" class="btnAdd"><a>View Payments at ' + locationName2 + '</a></span></p>'; 9464 var htm = '<div id="pop-view-payments-at-other-locations">' + btn1 + btn2 + '</div>'; 9465 var jpop = GLO.Popup.Custom.openSimple(htm, 'Payments at Other Locations'); 9466 GLO.Popup.Custom.singleButton(jpop, 'Close'); 9467 9468 jpop.find('#btnGiftPay1 > a').click(function() { 9469 GLO.Staff.Filter.switchLocation(minOtherPid, locationName, locationColor, urlGoTo); 9470 }); 9471 9472 jpop.find('#btnGiftPay2 > a').click(function() { 9473 GLO.Staff.Filter.switchLocation(maxOtherPid, locationName2, locationColor2, urlGoTo); 9474 }); 9475 } 9476 } 9477 } 9478 9479 _conRptPaySum.changeGiftReportDate = function(element, event) { 9480 $('#gift-option-date-range').prop('checked', true).change(); 9481 } 9482 _conRptPaySum.changeGiftNumber = function(element, event) { 9483 $('#gift-option-number').prop('checked', true).change(); 9484 } 9485 _conRptPaySum.allGiftCardsWithBalance = function(element, event) { 9486 $('.report-search-header #btnSearch > a').click(); 9487 } 9488 _conRptPaySum.giftByClientName = function() { 9489 $('#gift-option-client-name').prop('checked', true).change(); 9490 $('.report-search-header #Gift_Client_Name_vc').click(); 9491 } 9492 9493 _conRptPaySum.gotoReport = function(event, url) { 9494 var j = $('.report-search-header:visible'); 9495 var start = UTIL.fromSADate(j.find('#report-start').val(), true, true); 9496 var end = UTIL.fromSADate(j.find('#report-end').val(), true, true); 9497 9498 url = GLO.Uri.addQueryKeyAndValue(url, 'start=' + start + '&end=' + end); 9499 GLO.Report.TicketHistory.gotoReport(event, url); 9500 } 9501 9502 _conRptPaySum.goToReportTotal = function(event, url) { 9503 var trs = $('#report-payment-summary').find('tbody > tr'); 9504 var sid, sids = ''; 9505 var houseSIDs = GLO.Staff.Filter.getHouseStaff(); 9506 9507 for (var i=0; i < trs.length; i++) { 9508 sid = trs.eq(i).attr('staff_id'); 9509 9510 if (!UTIL.isEmpty(sid)) { 9511 if (sids !== '') { sids += ','; } 9512 sids += sid; 9513 } 9514 } 9515 9516 if (!UTIL.isEmpty(houseSIDs)) { 9517 if (sids !== '') { sids += ','; } 9518 sids += ',' + houseSIDs; 9519 } 9520 9521 url += '&sfilter=' + sids; 9522 GLO.Report.TicketHistory.gotoReport(event, url); 9523 } 9524 9525 function _loadPaySummaryData() { 9526 var jtbl = $('table#report-payment-summary.tablesorter'); 9527 UI.initTableSorter(jtbl); 9528 9529 GLO.Report.hideEmptyColumn(jtbl, 'ps-check-column'); 9530 GLO.Report.hideEmptyColumn(jtbl, 'ps-gift-column'); 9531 GLO.Report.hideEmptyColumn(jtbl, 'ps-loyalty-column'); 9532 GLO.Report.hideEmptyColumn(jtbl, 'ps-other-column'); 9533 9534 GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-check-column'); 9535 GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-gift-column'); 9536 GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-loyalty-column'); 9537 GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-other-column'); 9538 9539 GLO.Report.hideEmptyColumn(jtbl, 'ps-incorrect-column'); 9540 9541 GLO.Report.CellSummary.initReport(jtbl, true, true); 9542 } 9543 9544 _conRptPaySum.openHelpDateRange = function() { 9545 var hTicket = '<h3 style="color: rgb(40, 120, 240);">Ticket Date</h3>'; 9546 var bTicketDate = '<b class="narrow-text" style="color: rgb(40, 120, 240);">Ticket Date</b>'; 9547 var bPayDate = '<b class="narrow-text" style="color: rgba(20,200,20, 1)">Payment Date</b>'; 9548 9549 var msgTicket1 = '<p>' + bTicketDate + ' for service tickets is the service start date</p>'; 9550 var msgTicket2 = '<p>' + bTicketDate + ' for product tickets is the product purchase date</p>'; 9551 9552 var hPay = '<h3 style="color: rgba(20,200,20, 1)">Payment Date</h3>' 9553 var msgPay1 = '<p>The ' + bPayDate + ' is the date/time the payment was made</p>'; 9554 9555 var divNote = '<div class="help-date-range-note">'; 9556 var payIncorrect = '<span class="narrow-text" style="display: inline;">(except the Incorrect Payment report which uses the checkout date / ticket date)</span>'; 9557 var noteTop = '<p style="text-align: center;">Filter payments by the ' + bTicketDate + ' or ' + bPayDate + '</p>'; 9558
9559 var rptPaySummary = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/PaymentSummary\')" style="font-weight: bold;">Payment Summary report</a>'; 9560 var rptPayDetail = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1&paymethod=0\')" style="font-weight: bold;">Payment Detail report</a>'; 9561 9562 var noteBottom = '<p style="margin-top: 32px">Payment reports filter by the ' + bPayDate + ' ' + payIncorrect + '</p>'; 9563 noteBottom += '<p>Most other reports filter by the ' + bTicketDate + '</p>'; 9564 noteBottom += '<p style="margin: 20px 0;">The ' + rptPaySummary + ' and ' + rptPayDetail + ' allow filtering by either ' + bTicketDate + ' or ' + bPayDate + '</p>'; 9565 noteBottom = '<div id="help-date-range-note-bottom">' + noteBottom + '</div>'; 9566 9567 var htm = '<div id="pop-help-date-range-info">' + divNote + noteTop + '</div>' + hTicket + msgTicket1 + msgTicket2 + hPay + msgPay1 + divNote + noteBottom + '</div> </div>'; 9568 var jpop = GLO.Popup.Info.open(htm, 'Filter Date Range').getPopup(); 9569 9570 jpop.find('.msg').css({ "padding-top": 0 }); 9571 } 9572 _conRptPaySum.openHelpIncorrect = function() { 9573 var jDateRange = $('#report-payment-summary-date-range'); 9574 var dateRange = '<b>' + jDateRange.find('#report-start').val() + ' - ' + jDateRange.find('#report-end').val() + '</b>'; 9575 var isPayDateRange = $('#report-payment-summary-select-range #Date_Range_Type_Pay_fl').prop('checked'); 9576 var ticketDateLabel = '<b class="narrow-text" style="color: rgb(40, 120, 240);">Ticket Date</b>'; 9577 9578 if (isPayDateRange) { 9579 var dateLabel = '<b class="narrow-text" style="color: rgba(20,200,20, 1);">Payment Date</b>'; 9580 } else { 9581 var dateLabel = ticketDateLabel; 9582 } 9583 9584 var rpt = '<b class="narrow-text">Payment Summary <span style="letter-spacing: 0; color: inherit;">report</span></b>'; 9585 var msg = '<p>The Incorrect payment amount on this ' + rpt + ' looks for past tickets with a ' + dateLabel + ' between ' + dateRange + ' and includes tickets with</p>'; 9586 9587 var listIncluded = '<ul> <li><b class="narrow-text">Incorrect payment amount:</b> the amount a ticket was over-paid or under-paid</li> </ul>'; 9588 var headerNot = '<h4 style="text-align: left; color: rgb(255,0,0);">Does Not Include</h4>'; 9589 var listNot = '<ul> <li><b class="narrow-text">Un-paid Ticket amount:</b> ticket has no payment</li> </ul>'; 9590 9591 var htm = '<div id="pop-help-incorrect-info">' + msg + listIncluded + headerNot + listNot + '</div>'; 9592 var jpop = GLO.Popup.Info.open(htm, 'Incorrect Payment').getPopup(); 9593 } 9594 _conRptPaySum.openHelpTip = function() { 9595 var msg = '<p>If there is more than one payment method on a ticket, the tip is taken from the payment methods on the ticket in this order:</p>'; 9596 9597 var li1 = '<li><b>Cash</b> <i>payment</i></li>'; 9598 var li2 = '<li><b>Credit</b> <i>payment</i></li>'; 9599 var li3 = '<li><b>Check</b> <i>payment</i></li>'; 9600 var li4 = '<li><b>Other</b> <i>payment method</i></li>'; 9601 var li5 = '<li><b>Gift Card</b> <i>payment</i></li>'; 9602 var li6 = '<li><b>Loyalty</b> <i>payment</i></li>'; 9603 9604 var list = '<ol>' + li1 + li2 + li3 + li4 + li5 + li6 + '</ol>'; 9605 var ex1 = 'A ticket with a service price of $90 and tip of $10 with a $50 cash payment and $50 credit payment'; 9606 var ex2 = 'the $10 tip with come from the cash payment, so will be a <b class="narrow-text">$10 cash tip</b>'; 9607 var example = '<p class="example-help"><i>For example,</i> ' + ex1 + ' <b class="arrow-right">➜</b> ' + ex2 + '</p>'; 9608 9609 var htm = '<div id="pop-help-tip-info">' + msg + list + example + '</div>'; 9610 var jpop = GLO.Popup.Info.open(htm, 'Tip Split Across Different Payment Methods on a Ticket').getPopup(); 9611 } 9612 9613 _conRptPaySum.changeFilterDateRangeType = function() { 9614 if ($('#Date_Range_Type_Ticket_fl').prop('checked')) { 9615 var filterDateRangeType = 'ticket-date'; 9616 } else if ($('#Date_Range_Type_Pay_fl').prop('checked')) { 9617 var filterDateRangeType = 'pay-date'; 9618 } else { 9619 var filterDateRangeType = null; 9620 } 9621 9622 UTIL.setCookie('Filter_Date_Range_Type_cd', filterDateRangeType); 9623 } 9624 9625 _conRptPaySum.search = function() { 9626 var jrpt = $('#report-main'); 9627 var btnSearch = jrpt.find('#btnSearch'); 9628 var jd = {}; 9629 9630 var start = jrpt.find('#report-start:visible').val(); 9631 var end = jrpt.find('#report-end:visible').val(); 9632 var isPayDate = jrpt.find('#Date_Range_Type_Pay_fl').prop('checked'); 9633 9634 var pageTitle = SA.Resource.PaymentSummary + ': ' + start + ' - ' + end; 9635 var qstring = '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&ispaydate=' + isPayDate; 9636 9637 GLO.UI.Form.beginProcessing(btnSearch); 9638 if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); } 9639 9640 var url = GLO.Link.WebsiteDomain + 'report/PaymentSummary?' + qstring; 9641 var jRptData = jrpt.find('.report-container'); 9642 9643 if (!GLO.Report.hasReportPassword(jd)) { 9644 return; 9645 } 9646
9647 $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd }) 9648 .success(function(data, textStatus, jqXHR) { 9649 jRptData.html(data); 9650 _loadPaySummaryData(); 9651 9652 GLO.UI.Form.resetProcessing(); 9653 window.history.pushState("", pageTitle, url); 9654 9655 if (GLO.Info.isMobile(true) || GLO.Mobile.isTablet) { 9656 var jlinks = $('#report-payment-summary').find('a'); 9657 GLO.UI.initAnimateLink(jlinks, 4, GLO.UI.pinkify); 9658 } 9659 9660 //_conRptPaySum.loadGiftCardReport(); 9661 }) 9662 .error(function(jqXHR, textStatus, errorThrown) { 9663 GLO.UI.Form.resetProcessing(); 9664 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 9665 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 9666 }); 9667 } 9668 9669 return _conRptPaySum; 9670})(); 9671 9672 9673GLO.Report.Payroll = (function() { 9674 function _conRptPayroll() { } 9675 9676 _conRptPayroll.initByDayPopup = function(staffId) { 9677 var jpop = $('#report-payroll-days-all-data').closest('.glopop'); 9678 jpop.find('#report-payroll-today').addClass('hideX'); 9679 9680 var jpopStatus = jpop.find('#pop-payroll-day-status'); 9681 jpopStatus.find('h2').addClass('hideX'); 9682 jpop.find('#report-payroll-days-header').before(jpopStatus); 9683 9684 var headerText = jpop.find('#report-payroll-days-staff-label').text() + ' <span class="narrow-text">Payroll Today</span>'; 9685 jpop.find('.pop-header > h1').html(headerText); 9686 9687 _loadPayrollByDayData(jpop); 9688 var width = 320; 9689 9690 /* if (innerWidth >= 1100) { 9691 width = 1100; 9692 } else if (innerWidth >= 980) { 9693 width = 980; 9694 } else if (innerWidth >= 900) { 9695 width = 900; 9696 } else if (innerWidth >= 800) { 9697 width = 800; 9698 } else if (innerWidth >= 720) { 9699 width = 700; 9700 } else */ if (innerWidth >= 640) { 9701 width = 600; 9702 } else if (innerWidth >= 520) { 9703 width = 500; 9704 } else if (innerWidth >= 420) { 9705 width = 400; 9706 } 9707 9708 jpop.width(width); 9709 var label = 'Print Today\'s Staff Commission'; 9710 var sname = UserPortal.getStaffName(staffId); 9711 9712 if (!UTIL.isEmpty(sname)) { 9713 label = 'Print ' + label + ' Commission'; 9714 } 9715 9716 var btnPrint = '<span id="btnPrintStaffCommission" class="btnAdd" title="' + label + '"><a onclick="SA.POS.printTodayCommissionToPrinter(this)">Print</a></span>'; 9717 var jbtns = jpop.find('.pop-buttons').css({ "width": "100%" }); 9718 jbtns.prepend(btnPrint); 9719 return jpop; 9720 } 9721 _conRptPayroll.initByDay = function() { 9722 GLO.Info.init(); 9723 GLO.Report.portalName = 'payroll-days'; 9724 GLO.Staff.Filter.isReportPortal = true; 9725 9726 if (!GLO.Report.Sales.initStaffFilter()) { 9727 GLO.Report.Template.initStaffFilter(true); 9728 } 9729 9730 var jRptData = $('#report-main').find('.report-container'); 9731 var jhead = $('.report-search-header'); 9732 9733 GLO.Report.Template.initDateRange(jhead, true, true); 9734 GLO.Report.initReportPassword(jRptData); 9735 9736 var start = UTIL.fromSADate(jhead.find('#report-start').val(), true, true); 9737 var end = UTIL.fromSADate(jhead.find('#report-end').val(), true, true); 9738 9739 _loadPayrollByDayData(jRptData, start, end); 9740 _initPayrollUri(); 9741 9742 setTimeout(function() { UI.highlightStaffFilter(1200); }, 3200); 9743 } 9744 _conRptPayroll.init = function() { 9745 GLO.Info.init(); 9746 GLO.Report.portalName = 'payroll'; 9747 9748 GLO.Staff.Filter.isReportPortal = true; 9749 9750 if (!GLO.Report.Sales.initStaffFilter()) { 9751 GLO.Report.Template.initStaffFilter(true); 9752 } 9753 9754 var jRptData = $('#report-payroll'); 9755 _loadPayrollData(jRptData); 9756 9757 var jhead = $('.report-search-header'); 9758 GLO.Report.Template.initDateRange(jhead, true); 9759 GLO.Report.setupFastClick(); 9760 GLO.Report.enableFullPageCheck(); //$('body').addClass('report-full-page'); 9761 GLO.Report.initReportPassword(jRptData); 9762 9763 GLO.Provider.Commission.initPayrollSchedule(); 9764 _initPayrollUri();
9765 9766 setTimeout(function() { 9767 _initMissingValue(); 9768 }, 1500); 9769 } 9770 function _initMissingValue() { 9771 var payrollSchedule = $('#report-payroll-date-range').attr('value'); 9772 9773 if (UTIL.isEmpty(payrollSchedule) && $('.glopop .msg').length === 0 && $('#simplemodal-container').length === 0) { 9774 GLO.Provider.Commission.openPayrollDateRange(); 9775 } 9776 } 9777 function _initPayrollUri() { 9778 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 9779 var step = UTIL.cleanString(GLO.Uri.url('step')).toLowerCase(); 9780 var column = UTIL.cleanString(GLO.Uri.url('column')).toLowerCase(); 9781 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 9782 var staffId = UTIL.cleanString(GLO.Uri.url('staff')); 9783 9784 if (open == 'print') { 9785 GLO.Report.Payroll.openPrintReport(); 9786 } else if (open == 'help') { 9787 GLO.Provider.Commission.openReportHelp(step); 9788 } else if (open == 'export') { 9789 GLO.Report.Payroll.exportReport(); 9790 } else if (open == 'automatic-commission') { 9791 GLO.Provider.Commission.openReportHelp(22); 9792 } else if (open == 'save') { 9793 GLO.Report.Payroll.saveHistoryPopup(); 9794 } else if (open == 'history') { 9795 GLO.Report.Payroll.viewHistoryPopup(); 9796 } else if (!UTIL.isEmpty(column)) { 9797 var jtbody = $('#report-payroll-summary-container tbody'); 9798 9799 if (!UTIL.isEmpty(staffId)) { 9800 var tr = jtbody.find('tr[staff_id="' + staffId + '"]'); 9801 } else { 9802 var tr = jtbody.find('tr').eq(0); 9803 } 9804 9805 var jcolumn = tr.find('td.' + column + '-column'); 9806 9807 if (jcolumn.length && !jcolumn.is(':visible') && !$('body').hasClass('report-full-page')) { 9808 GLO.Report.enableFullPage(true); 9809 } 9810 9811 jcolumn.click(); 9812 9813 if (highlight == 'print') { 9814 var jhighlight = $('#pop-help-report-list'); 9815 9816 if (jhighlight.length > 0) { 9817 UI.highlight(jhighlight, 800, 6400, true); 9818 } 9819 9820 return; 9821 } 9822 } 9823 9824 if (!UTIL.isEmpty(highlight)) { 9825 var jrpt = $('#report-payroll'); 9826 var jhigh = jrpt.find('#' + highlight); 9827 9828 if (jhigh.length === 0) { 9829 jhigh = jrpt.find('.' + highlight); 9830 } 9831 9832 if (jhigh.length && !jhigh.is(':visible') && !$('body').hasClass('report-full-page')) { 9833 GLO.Report.enableFullPage(true); 9834 } 9835 9836 UI.highlight(jhigh, 800, 6400, true); 9837 } 9838 } 9839 function _initHideEmptyColumns() { 9840 var j = $('#report-payroll-summary'); 9841 var tdPlusMin = j.find('td.plus-min-column'); 9842 9843 if (tdPlusMin.length > 0 && GLO.Report.Template.hideEmptyColumn(j, 'plus-min-column')) { 9844 var td = j.find('tr#report-payroll-header2 .group-commission-dollar'); 9845 9846 if (td.length > 0) { 9847 var cols = parseInt(td.attr('colspan')) - 1; 9848 td.attr('colspan', cols); 9849 } 9850 } 9851 } 9852 function _historyReportHideEmptyColumns(j) { 9853 GLO.Report.Template.hideEmptyColumn(j, 'product-percent-column'); 9854 GLO.Report.Template.hideEmptyColumn(j, 'product-percent-actual-column'); 9855 9856 GLO.Report.Template.hideEmptyColumn(j, 'hourly-rate-column'); 9857 GLO.Report.Template.hideEmptyColumn(j, 'paid-vacation-column'); 9858 GLO.Report.Template.hideEmptyColumn(j, 'paid-sick-column'); 9859 GLO.Report.Template.hideEmptyColumn(j, 'full-days-column'); 9860 9861 GLO.Report.Template.hideEmptyColumn(j, 'sale-product-column'); 9862 GLO.Report.Template.hideEmptyColumn(j, 'product-dollar-column'); 9863 GLO.Report.Template.hideEmptyColumn(j, 'plus-min-column'); 9864 9865 GLO.Report.Template.hideEmptyColumn(j, 'service-fee-column'); 9866 GLO.Report.Template.hideEmptyColumn(j, 'credit-fee-column'); 9867 GLO.Report.Template.hideEmptyColumn(j, 'supply-fee-column'); 9868 GLO.Report.Template.hideEmptyColumn(j, 'clean-fee-column'); 9869 9870 GLO.Report.Template.hideEmptyColumn(j, 'adjust-column'); 9871 GLO.Report.Template.hideEmptyColumn(j, 'adjust-note'); 9872 9873 GLO.Report.Template.hideEmptyColumn(j, 'hourly-wage-column'); 9874 GLO.Report.Template.hideEmptyColumn(j, 'overtime-column'); 9875 GLO.Report.Template.hideEmptyColumn(j, 'gift-card-column'); 9876 GLO.Report.Template.hideEmptyColumn(j, 'tip-column'); 9877 9878 GLO.Report.Template.hideEmptyColumn(j, 'early-column'); 9879 GLO.Report.Template.hideEmptyColumn(j, 'normal-column'); 9880 GLO.Report.Template.hideEmptyColumn(j, 'profit-column'); 9881 } 9882 9883 _conRptPayroll.openFirstIncompleteTicket = function() { 9884 var smid = $('#report-payroll-days').find('tr.has-incomplete-tickets').attr('first_incomplete_smid'); 9885 var jsonPostOpen = { "processing_message_vc": "Retrieving first incomplete ticket..." }; 9886 9887 UserPortal.Edit.get(null, smid, true, false, false, jsonPostOpen); 9888 } 9889 _conRptPayroll.openIncompleteTicket1 = function() {
9890 var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr'); 9891 var smid = tr.attr('first_incomplete_smid'); 9892 _openIncompleteTicket(tr, smid); 9893 } 9894 _conRptPayroll.openIncompleteTicket2 = function() { 9895 var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr'); 9896 var smid = tr.attr('last_incomplete_smid'); 9897 _openIncompleteTicket(tr, smid); 9898 } 9899 function _openIncompleteTicket(tr, smid) { 9900 UserPortal.Edit.get(null, smid, true); 9901 } 9902 9903 _conRptPayroll.moveDateRange = function(up) { 9904 var jhead = $('.report-search-header'); 9905 var jstart = jhead.find('.Begin_dt'), jend = jhead.find('.End_dt'); 9906 9907 var dt1 = new Date(UTIL.fromSADate(jstart.val(), true, true)); 9908 var dt2 = new Date(UTIL.fromSADate(jend.val(), true, true)); 9909 var oneDay = 24*60*60*1000; //hours * minutes * seconds * milliseconds. 9910 9911 if (GLO.Report.Template.isMonthRange(dt1, dt2)) { 9912 var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1); 9913 dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount)); 9914 dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount); 9915 } else if (_isBiWeeklyDateRange(dt1, dt2)) { 9916 if (up > 0) { 9917 if (dt1.getDate() == 1) { 9918 dt1 = new Date(dt1.getFullYear(), dt1.getMonth(), 16); 9919 dt2 = new Date(dt2.getFullYear(), dt2.getMonth() + 1, 0); 9920 } else if (dt1.getDate() == 16) { 9921 dt1 = new Date(dt1.getFullYear(), dt1.getMonth() + 1, 1); 9922 dt2 = new Date(dt2.getFullYear(), dt2.getMonth() + 1, 15); 9923 } 9924 } else { 9925 if (dt1.getDate() == 1) { 9926 dt2 = new Date(dt1).addDays(-1); 9927 dt1 = new Date(dt1.getFullYear(), dt1.getMonth() - 1, 16); 9928 } else if (dt1.getDate() == 16) { 9929 dt1 = new Date(dt1.getFullYear(), dt1.getMonth(), 1); 9930 dt2 = new Date(dt2.getFullYear(), dt2.getMonth(), 15); 9931 } 9932 } 9933 } else { //= advance 9934 var moveBy = Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + 1; 9935 9936 dt1.setDate(dt1.getDate() + (moveBy * up)); 9937 dt2.setDate(dt2.getDate() + (moveBy * up)); 9938 } 9939 9940 jstart.val(dt1.toGloDate()); 9941 jend.val(dt2.toGloDate()); 9942 9943 _conRptPayroll.search(); 9944 } 9945 function _isBiWeeklyDateRange(start, end) { 9946 var payrollSchedule = $('#report-payroll-date-range').attr('value'); 9947 9948 if (payrollSchedule == 10) { 9949 if (start.getMonthDiff(end) === 0) { 9950 if ( (start.getDate() == 1 && end.getDate() == 15) || (start.getDate() == 16 && end.getDate() == new Date(end.getFullYear(), end.getMonth() + 1, 0).getDate()) ) { 9951 return true; 9952 } 9953 } 9954 } 9955 9956 return false; 9957 } 9958 function _isAllowPayrollSearch(jd, btnSearch) { 9959 var fnReload = function() { 9960 location.reload(); 9961 }; 9962 9963 if ($('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected').hasClass('btnProcessing4')) { 9964 GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Multiple Request'); 9965 setTimeout(fnReload, 1500); 9966 return false; 9967 } else if (btnSearch.hasClass('btnProcessing4')) { 9968 GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Report Request'); 9969 setTimeout(fnReload, 1500); 9970 return false; 9971 } else if (!GLO.Report.hasReportPassword(jd, true)) { 9972 return false; 9973 } 9974 9975 return true; 9976 } 9977 _conRptPayroll.search = function(isPrint) { 9978 var jd = {}, jrpt = $('#report-main'); 9979 var btnSearch = jrpt.find('#btnSearch'); 9980 9981 if (!_isAllowPayrollSearch(jd, btnSearch)) { return; } 9982 9983 var start = jrpt.find('#report-start:visible').val(); 9984 var end = jrpt.find('#report-end:visible').val(); 9985 var pageTitle = SA.Resource.PayrollReport + ': ' + start + ' - ' + end; 9986 var qstring = '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&sfilter=' + GLO.Uri.query('sfilter'); 9987 9988 if (jrpt.find('.block-container #report-payroll-summary').length > 0) { 9989 var msg = '<div> <h1 class="friendly-msg3">Upgrade Required</h1> <div class="friendly-msg3">Please upgrade to the Silver or Gold Package to use the Payroll Report</div> </div>'; 9990 new GLO.Popup.Info(msg); 9991 return; 9992 } 9993 9994 GLO.UI.Form.beginProcessing(btnSearch); 9995 if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); } 9996 9997 var jRptData = jrpt.find('.report-container'); 9998 var url = GLO.Link.WebsiteDomain + 'report/payroll?' + qstring; 9999 10000 if (GLO.Report.portalName == 'payroll-days') { 10001 url = GLO.Link.WebsiteDomain + 'report/payrollDays?' + qstring + '&period=' + UTIL.cleanString(jrpt.find('.btnMultiChild .btnAdd.selected').parent().attr('value')); 10002 } 10003
10004 $.ajax({ type: "POST", url: url, "cache": false, "data": jd }) 10005 .success(function(data, textStatus, jqXHR) { 10006 jRptData.html(data); 10007 10008 if (GLO.Report.portalName == 'payroll-days') { 10009 _loadPayrollByDayData(jRptData, start, end); 10010 var warningHtm = UTIL.cleanString($('#report-header-warning').remove().html()); 10011 10012 $('#daily-payroll-report-header-help').html(warningHtm); 10013 //$('#report-header-warning').remove(); 10014 } else { 10015 _loadPayrollData(jRptData, start, end); 10016 } 10017 10018 GLO.UI.Form.resetProcessing(); 10019 window.history.pushState("", pageTitle, url); 10020 10021 if (isPrint) { 10022 $('#btnPrintPayrollByDay').find('>a').click(); 10023 } 10024 }) 10025 .error(function(jqXHR, textStatus, errorThrown) { 10026 GLO.UI.Form.resetProcessing(); 10027 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 10028 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10029 }); 10030 } 10031 10032 function _getHistorySettings(tr) { 10033 var servicePct = UTIL.coalesceMoney(tr.find('.expected-percent-column').text().replace('%', '')); 10034 var serviceEarlyPct = UTIL.coalesceMoney(tr.attr('service_commission_early_pct')); 10035 var productPct = UTIL.coalesceMoney(tr.find('.expected-percent-column').text().replace('%', '')); 10036 var hourlyWage = UTIL.coalesceMoney(tr.find('.hourly-rate-column').text().replace('$', '')); 10037 10038 var minWeek = UTIL.coalesceMoney(tr.attr('minWeek')); 10039 var minDay = UTIL.coalesceMoney(tr.attr('minDay')); 10040 var minHr = UTIL.coalesceMoney(tr.attr('minHour')); 10041 10042 var minDayHours = UTIL.coalesceMoney(tr.attr('minDayHours')); 10043 var minDayHalfHours = UTIL.coalesceMoney(tr.attr('minDayHalfHours')); 10044 var minWeekDays = UTIL.coalesceMoney(tr.attr('minWeekDays')); 10045 var minIncludesTip = UTIL.coalesceMoney(tr.attr('minIncludeTip')); 10046 10047 var minAndFeeStart = UTIL.cleanString(tr.attr('minAndFeeStart')); 10048 var minOvertimePerHr = UTIL.coalesceMoney(tr.attr('minOvertimePerHour')); 10049 var overtimePerHr = UTIL.coalesceMoney(tr.attr('overtimePerHour')); 10050 10051 return { "ServiceCommission": servicePct, "ServiceCommissionEarlyPercent": serviceEarlyPct, "ProductCommission": productPct, "HourlyRate": hourlyWage 10052 , "MinHour": minHr, "MinDay": minDay, "MinWeek": minWeek 10053 , "MinHoursPerDay": minDayHours, "MinHoursPerHalfDay": minDayHalfHours, "MinDaysPerWeek": minWeekDays, "MinIncludesTip": minIncludesTip 10054 , "MinAndFeeStart": minAndFeeStart, "MinOvertimePerHr": minOvertimePerHr, "OvertimePerHr": overtimePerHr }; 10055 } 10056 function _getHistoryTotals(tr) { 10057 var sid = tr.attr('staff_id'); 10058 var hrs = UTIL.coalesceMoney(tr.find('.hours-worked-column').text());
10059 var days = UTIL.coalesceMoney(tr.find('.actual-days-column').text()); 10060 var fullDays = UTIL.coalesceMoney(tr.find('.full-days-column').text()); 10061 var serviceDays = UTIL.coalesceMoney(tr.attr('days_worked_service_sr')); 10062 10063 var total = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', '')); //profit-column 10064 var timesheet = UTIL.coalesceMoney(tr.find('.hourly-wage-column').text().replace('$', '')); 10065 var overtime = UTIL.coalesceMoney(tr.find('.overtime-column').text().replace('$', '')); 10066 var servicePayment = UTIL.coalesceMoney(tr.find('.sale-service-payment-column').text().replace('$', '')); 10067 var profit = UTIL.coalesceMoney(tr.find('.profit-column > span').text().replace('$', '')); 10068 10069 var actualHourlyRate = UTIL.coalesceMoney(tr.find('.actual-hourly-rate-column').text().replace('$', '')); 10070 var actualServicePct = UTIL.coalesceMoney(tr.find('.service-percent-actual-column').text().replace('%', '')); 10071 var actualProductPct = UTIL.coalesceMoney(tr.find('.product-percent-actual-column').text().replace('%', '')); 10072 10073 var productCommission = UTIL.coalesceMoney(tr.find('.product-dollar-column').text().replace('$', '')); 10074 var serviceCommission = UTIL.coalesceMoney(tr.find('.service-dollar-column').text().replace('$', '')); 10075 var early = UTIL.coalesceMoney(tr.find('.early-column').text().replace('$', '')); 10076 var normal = UTIL.coalesceMoney(tr.attr('normal_commission_mn')); //tr.find('.normal-column').text().replace('$', '') 10077 10078 var tipCommission = UTIL.coalesceMoney(tr.find('.tip-column').text().replace('$', '')); 10079 var paymentTip = UTIL.coalesceMoney(tr.attr('payment_tip_mn')); 10080 var paymentTipCredit = UTIL.coalesceMoney(tr.attr('payment_tip_credit_mn')); 10081 10082 var serviceSales = UTIL.coalesceMoney(tr.find('.sale-service-column').text().replace('$', '')); 10083 var productSales = UTIL.coalesceMoney(tr.find('.sale-product-column').text().replace('$', '')); 10084 var tipTotal = UTIL.coalesceMoney(tr.attr('tip_mn')); 10085 10086 var vacation = UTIL.coalesceMoney(tr.find('.paid-vacation-column').text().replace('$', '')); 10087 var sick = UTIL.coalesceMoney(tr.find('.paid-sick-column').text().replace('$', '')); 10088 var plusMin = UTIL.coalesceMoney(tr.find('.plus-min-column').text().replace('$', '')); 10089 var adjustment = UTIL.coalesceMoney(tr.find('.adjust-input').val()); 10090 10091 var serviceFee = Math.abs(UTIL.coalesceMoney(tr.find('.service-fee-column > span').text().replace('$', ''))); 10092 var ccFee = UTIL.coalesceMoney(tr.find('.credit-fee-column').text().replace('$', '')); 10093 10094 var supplyFee = UTIL.coalesceMoney(tr.find('.supply-fee-column span').text().replace('-$', '')); //UTIL.coalesceMoney(days * UTIL.coalesceMoney(tr.attr('day_supply_fee_mn'))); 10095 var cleanFee = UTIL.coalesceMoney(tr.find('.clean-fee-column span').text().replace('-$', '')); //UTIL.coalesceMoney(days * UTIL.coalesceMoney(tr.attr('day_clean_fee_mn'))); 10096 10097 var withheld = UTIL.coalesceMoney(tr.attr('total_withheld_mn')); //federal_tax_mn, wage_after_tax_mn 10098 var socialSecurity = UTIL.coalesceMoney(tr.attr('social_security_mn')); 10099 var medicare = UTIL.coalesceMoney(tr.attr('medicare_mn')); 10100 var employmentInsurance = UTIL.coalesceMoney(tr.attr('employment_insurance_mn')); 10101 var note = UTIL.htmlEncode(tr.find('.payroll-adjust-note > a').text()); 10102 10103 return { "StaffId": sid, "HoursWorked": hrs, "DaysWorked": days, "FullDaysWorked": fullDays, "DaysWorkedService": serviceDays 10104 , "ActualHourlyRate": actualHourlyRate, "ActualServiceCommissionPercent": actualServicePct, "ActualProductCommissionPercent": actualProductPct 10105 , "TotalWage": total, "Timesheet": timesheet, "Overtime": overtime, "ServicePayment": servicePayment, "Profit": profit 10106 , "ProductCommission": productCommission, "ServiceCommission": serviceCommission, "ServiceCommissionEarly": early, "ServiceCommissionNormal": normal 10107 , "TipCommission": tipCommission, "PaymentTip": paymentTip, "PaymentTipCredit": paymentTipCredit 10108 10109 , "Vacation": vacation, "Sick": sick, "MinAdded": plusMin, "Adjustment": adjustment 10110 , "ServiceSales": serviceSales, "ProductSales": productSales, "TipTotal": tipTotal
10111 , "ServiceFee": serviceFee, "CreditCardFee": ccFee, "SupplyFee": supplyFee, "CleaningFee": cleanFee 10112 , "Withheld": withheld, "SocialSecurity": socialSecurity, "Medicare": medicare, "EmploymentInsurance": employmentInsurance, "Note": note }; 10113 } 10114 function _createSaveHistoryJson() { 10115 var trs = $('#report-payroll-summary').find('tbody > tr'); 10116 var jsonStaffList = []; 10117 10118 for (var i=0; i < trs.length; i++) { 10119 //if (i > 0) { jsonStaffList += ', '; } 10120 10121 var tr = trs.eq(i); 10122 var jsonStaff = _getHistoryTotals(tr); 10123 var settings = _getHistorySettings(tr); 10124 10125 jsonStaff.Settings = settings; 10126 jsonStaffList.push(jsonStaff); 10127 } 10128 return { "StaffList": jsonStaffList }; 10129 } 10130 _conRptPayroll.saveHistory = function(isOverride) { 10131 var jpayroll = $('#report-payroll-summary'); 10132 var start = jpayroll.attr('start_d'); 10133 var end = jpayroll.attr('end_d'); 10134 10135 var jsonStaffList = { "payrollPeriod": _createSaveHistoryJson() }; //_getIOSBookingResult(jd); 10136 var url = GLO.Link.WebsiteDomain + 'report/PayrollPeriodInsert?start=' + start + '&end=' + end; 10137 10138 if (isOverride) { 10139 url += '&override=1'; 10140 } 10141 10142 GLO.UI.Form.beginProcessing($('.btnSavePayrollHistory')); 10143 10144 $.ajax({ type: "POST", url: url, "cache": false, data: jsonStaffList }) 10145 .success(function(data, textStatus, jqXHR) { 10146 var jdata = $(data); 10147 GLO.UI.Form.resetProcessing(); 10148 10149 if (jdata.hasClass('success')) { 10150 GLO.Popup.closeIfExist($('#pop-payroll-history-duplicates').closest('.glopop')); 10151 GLO.Popup.Success.open(data, 'Payroll History Saved!', 69000); 10152 } else { 10153 _displayDuplicateWarning(data); 10154 } 10155 }) 10156 .error(function(jqXHR, textStatus, errorThrown) { 10157 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10158 }); 10159 } 10160 function _displayDuplicateWarning(data) { 10161 var ojpop = GLO.Popup.Warning.open(data, 'Save Payroll History Failed'); 10162 var jpop = ojpop.getPopup(); 10163 var tblDup = jpop.find('#payroll-history-duplicate-table'); 10164 10165 jpop.find('.msg').css({ "padding": "0" }); 10166 UI.initTableSorter(tblDup); 10167 GLO.Popup.Custom.singleButton(jpop, 'Close'); 10168 10169 var btnSave = '<span class="btnSave btnSavePayrollHistory" style="margin-left: 200px; font-size: 18px;"><a onclick="GLO.Report.Payroll.saveHistory(true)">Override + Save</a></span>'; 10170 jpop.find('.btnSA').after(btnSave); 10171 10172 if (!GLO.Info.isMobile() && jpop.height() + 50 >
10172 innerHeight) { 10173 var topHeight = jpop.find('#payroll-history-warning').height() + jpop.find('.pop-header').height(); 10174 var bottomHeight = jpop.find('.pop-buttons-parent').height(); 10175 var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px'; 10176 10177 jpop.find('#payroll-history-duplicate-data').css({ "max-height": tableHeight, "overflow-y": "auto" }); 10178 } 10179 10180 ojpop.realign(); 10181 } 10182 _conRptPayroll.saveHistoryPopup = function(isViewOnly, message) { 10183 var jrpt = $('#report-payroll-summary'); 10184 var start = jrpt.attr('start_d'), end = jrpt.attr('end_d'); 10185 10186 var helpIcon = '<b class="question-icon" onclick="GLO.Report.Payroll.openHelpHistory(this)" style="margin-left: 4px;">?</b>'; 10187 var cssSmaller = 'letter-spacing: 0; line-height: 1.4; font-size: 93%; font-family: arial; font-stretch: condensed;'; 10188 var htmHelp = '<p style="' + cssSmaller + '">When you do payroll, we recommend saving your payroll information in the payroll history ' + helpIcon + '</p>'; 10189 var msg = '<p style="padding-bottom: 24px; ' + cssSmaller + '">' + UTIL.cleanString(message) + '</p>'; 10190 10191 if (UTIL.parseBool(isViewOnly)) { 10192 return '<div id="info-save-payroll-history">' + htmHelp + msg + '</div>'; 10193 } 10194 10195 var htmWarn = _getSaveHistoryWarning(jrpt, start, end); 10196 var h1 = 'Save Payroll Period: ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true); 10197 10198 var labelSave = '<b>Save payroll for ' + jrpt.find('tbody > tr').length + ' staff ?</b>'; 10199 var btnSave = '<span class="btnSave btnSavePayrollHistory"><a onclick="GLO.Report.Payroll.saveHistory()">Save</a></span>'; 10200 var htmSave = '<div id="pop-save-payroll-history-summary">' + labelSave + btnSave + '</div>'; 10201 10202 var about = '<p style="margin-top: 40px; text-align: center;"><a onclick="GLO.Provider.Commission.openReportHelp(21)">About Payroll History</a></p>'; 10203 var htm = '<div id="pop-save-payroll-history">' + htmWarn + htmSave + about + htmHelp + msg + '</div>'; 10204 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 10205 GLO.Popup.Custom.singleButton(jpop, 'Close'); 10206 } 10207 function _getSaveHistoryWarning(jrpt, start, end) { 10208 var sfilter = GLO.Uri.url('sfilter'); 10209 var jStaffLabel = $('#staffFilter .hello-bar-label > span'); //.html(); 10210 var htmWarn = _verifyIsSameDateRange(start, end); 10211 10212 if (!UTIL.isEmpty(sfilter) || jStaffLabel.length > 0) { 10213 htmWarn += '<p class="warning-emphasis" style="text-align: center;">Staff filter limiting current payroll report to ' + jrpt.find('tbody > tr').length + ' staff</p>'; 10214 } 10215 10216 return htmWarn; 10217 } 10218 function _verifyIsSameDateRange(start, end) { 10219 var dtStart = new Date(start), dtEnd = new Date(end); 10220 var dayDiff = UTIL.dayDiff(dtStart, dtEnd) + 1; 10221 var payrollSchedule = $('#report-payroll-date-range').attr('value'); //.attr('last_period_end_dt') 10222 var p1 = '<p class="warning-emphasis">'; 10223 var dateRange = '<b class="narrow-text">' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true) + '</b>'; 10224 var warnMsg = '<i>Current Date Range</i> ' + dateRange + ' <i>does not match your normal payroll schedule</i> <b class="narrow-text">'; 10225 10226 if (UTIL.isEmpty(payrollSchedule)) { 10227 var btnPaySchedule = '<span id="btnPayrollDateRangePop" class="btnAdd"><a onclick="GLO.Provider.Commission.openPayrollDateRange()">Payroll Schedule</a></span>'; 10228 return p1 + 'Before saving, please press ' + btnPaySchedule + ' button to set your normal payroll schedule</p>'; 10229 } else if (payrollSchedule == 10) { //= 2/mo 10230 if (dtStart.getMonthDiff(dtEnd) != 0 10231 && !( (dtStart.getDate() == 1 && dtEnd.getDate() == 15) || !(dtStart.getDate() == 16 && dtEnd.getDate() == new Date(dtEnd.getFullYear(), dtEnd.getMonth() + 1, 0).getDate()) )) { 10232 return p1 + warnMsg + ' twice a month</b> </p>'; 10233 } 10234 } else if (payrollSchedule == 20) { 10235 if (dtStart.getMonthDiff(dtEnd) != 0 || !(dtStart.getDate() == 1 && dtEnd.getDate() == new Date(dtEnd.getFullYear(), dtEnd.getMonth() + 1, 0).getDate())) { 10236 return p1 + warnMsg + ' once a month</b> </p>'; 10237 } 10238 } else if (payrollSchedule > 29 && payrollSchedule < 40) { 10239 if (dayDiff != 14) { 10240 return p1 + warnMsg + ' every 2 weeks</b> </p>'; 10241 } else if (payrollSchedule % 10 != dtStart.getDay() + 1) { 10242 return p1 + warnMsg + ' starting on ' + UTIL.getWeekDayName(payrollSchedule % 10 - 1) + '</b> </p>'; 10243 } 10244 } else if (payrollSchedule > 39 && payrollSchedule < 50) { 10245 if (dayDiff != 7) { 10246 return p1 + warnMsg + ' once a week</b> </p>'; 10247 } else if (payrollSchedule % 10 != dtStart.getDay() + 1) { 10248 return p1 + warnMsg + ' starting on ' + UTIL.getWeekDayName(payrollSchedule % 10 - 1) + '</b> </p>'; 10249 } 10250 } 10251 10252 return ''; 10253 } 10254 10255 _conRptPayroll.viewHistoryPopup = function() { 10256 var url = GLO.Link.WebsiteDomain + 'report/PayrollHistorySummary?sfilter=' + UTIL.cleanString(GLO.Uri.url('sfilter')); 10257 GLO.UI.Form.beginProcessing($('#btnViewPayrollHistory')); 10258
10259 $.ajax({ type: "GET", url: url, "cache": false }) 10260 .success(function(data, textStatus, jqXHR) { 10261 var jdata = $(data); 10262 GLO.UI.Form.resetProcessing(); 10263 10264 var ojpop = GLO.Popup.Custom.open(data, 'Payroll History Summary'); 10265 var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": "0" }); 10266 var tbl = jpop.find('#payroll-history-summary-table'); 10267 10268 var msg = 'Press any period below for Payroll Period History'; 10269 var htmHelp = _conRptPayroll.saveHistoryPopup(true, msg); 10270 tbl.before(htmHelp); 10271 10272 var cssAbout = 'position: absolute; left: 0; bottom: 0; padding: 8px 8px 6px; border-bottom-left-radius: 6px; border-top-left-radius: 0; border-bottom-right-radius: 0;'; 10273 var lblAbout = 'About <i>Payroll History</i>'; 10274 var btnAbout = '<span class="btnAboutPayrollHistory btnAdd"><a onclick="GLO.Provider.Commission.openReportHelp(21)" style="' + cssAbout + '">' + lblAbout + '</a></span>'; 10275 jpop.find('.pop-buttons').append(btnAbout); 10276 10277 jpop.find('.msg').css({ "padding": "0" }); 10278 UI.initTableSorter(tbl); 10279 GLO.Popup.Custom.singleButton(jpop, 'Close'); 10280 10281 if (!GLO.Info.isMobile() && jpop.height() + 50 >
10281 innerHeight) { 10282 var topHeight = jpop.find('.pop-header').height(); 10283 var bottomHeight = jpop.find('.pop-buttons-parent').height(); 10284 var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px'; 10285 10286 jpop.find('#payroll-history-summary-data').css({ "max-height": tableHeight, "overflow-y": "auto" }); 10287 } 10288 10289 ojpop.realign(); 10290 }) 10291 .error(function(jqXHR, textStatus, errorThrown) { 10292 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10293 }); 10294 } 10295 _conRptPayroll.viewHistoryPeriod = function(tr) { 10296 var jtr = $(tr); 10297 var start = jtr.attr('start_d'), end = jtr.attr('end_d'), sfilter = UTIL.cleanString(GLO.Uri.url('sfilter')); 10298 10299 _conRptPayroll.viewHistoryPeriod2(sfilter, start, end, false); 10300 } 10301 _conRptPayroll.viewHistoryPeriod2 = function(sfilter, start, end, isExport) { 10302 var url = GLO.Link.WebsiteDomain + 'report/PayrollHistory?sfilter=' + sfilter + '&start=' + start + '&end=' + end; 10303 var header = 'Payroll History: ' + start + ' - ' + end; 10304 10305 if (isExport) { 10306 url += '&export=1'; 10307 10308 var btnExport = $('#pop-view-payroll-history-period').closest('.glopop').find('#btnExportHistory'); 10309 GLO.UI.Form.beginProcessing(btnExport); 10310 10311 window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 4500); 10312 10313 var childWindow = UI.openChildWindow(url, '', true); 10314 return; 10315 } 10316 10317 GLO.Popup.closeIfExist($('#pop-payroll-history-summary').closest('.glopop')); 10318 var ojprocessing = GLO.Popup.Processing.open('Loading Payroll History for the Period: ' + start + ' - ' + end + '...', header); 10319 //GLO.UI.Form.beginProcessing($('#btnViewPayrollHistory')); 10320 10321 $.ajax({ type: "GET", url: url, "cache": false }) 10322 .success(function(data, textStatus, jqXHR) { 10323 ojprocessing.close(); 10324 var msg = ''; 10325 10326 if ($('#report-main #payroll-history-diff-warning').length) { 10327 var link = '<a onclick="GLO.Report.Template2.goToReport(\'Payroll Report\', \'reports/payroll\')">Payroll Report</a>'; 10328 var btnSavePayroll = '<span class="btnSave"><a>Save</a></span>'; 10329 var warnStyle = ' style="margin-bottom: 20px; padding: 8px; text-align: center;"'; 10330 10331 msg = '<p' + warnStyle + '>To re-save payroll go to the ' + link + ' and press the ' + btnSavePayroll + ' button</p>'; 10332 } 10333 10334 var htm = '<div id="pop-view-payroll-history-period">' + msg + data + '</div>'; 10335 var ojpop = GLO.Popup.Custom.open(htm, header); 10336 var jpop = ojpop.getPopup().addClass('no-persist'); 10337 var tbl = jpop.find('#report-payroll-history-detail'); 10338 10339 GLO.Popup.Custom.singleButton(jpop, 'Close'); 10340 jpop.find('.msg').css({ "padding": "0" }); 10341 UI.initTableSorter(tbl); 10342 10343 _historyReportHideEmptyColumns(tbl); 10344 10345 if (!GLO.Info.isMobile()) { 10346 var fnExport = 'GLO.Report.Payroll.viewHistoryPeriod2(\'' + sfilter + '\', \'' + start + '\', \'' + end + '\', true)'; 10347 var cssExport1 = 'position: absolute; right: 0; bottom: 0;'; 10348 var cssExport2 = 'display: inline-block; padding: 6px 8px 4px; letter-spacing: 1px; font-size: 18px; border-radius: 10px; border-bottom-left-radius: 0; border-top-right-radius: 0;'; 10349 var btnExport = '<span id="btnExportHistory" class="btnAdd" style="' + cssExport1 + '"><a onclick="' + fnExport + '" style="' + cssExport2 + '">Export</a></span>'; 10350 10351 jpop.find('.pop-buttons-parent').css({ "position": "relative" }).append(btnExport); 10352 jpop.css({ "max-width": (parseInt(innerWidth - 50) + "px"), "padding-bottom": 0 }); 10353 10354 if (jpop.height() + 50 >
10354 innerHeight) { 10355 var topHeight = jpop.find('.pop-header').height(); 10356 var bottomHeight = jpop.find('.pop-buttons-parent').height(); 10357 var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px'; 10358 10359 jpop.find('#payroll-history-detail-view').css({ "max-height": tableHeight }); //, "overflow-y": "auto" 10360 } 10361 } 10362 10363 ojpop.realign(); 10364 //GLO.UI.Form.resetProcessing(); 10365 }) 10366 .error(function(jqXHR, textStatus, errorThrown) { 10367 ojprocessing.close(); 10368 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10369 }); 10370 } 10371 _conRptPayroll.openHelpHistory = function() { 10372 var htm = _getHistoryHelpInfo(); 10373 GLO.Popup.Info.open(htm, 'About Payroll History'); 10374 } 10375 function _getHistoryHelpInfo() { 10376 return $('#pop-payroll-history-help').outerHTML(); 10377 } 10378 10379 _conRptPayroll.processPayrollFromRow = function(that, isFindFirstDay) { 10380 if (UTIL.parseBool(isFindFirstDay)) { 10381 var tr = $('#report-payroll-days').find('tr.has-unprocessed-tickets'); //has-incomplete-tickets 10382 } else { 10383 var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr'); 10384 } 10385 10386 var day = tr.attr('day_d'); 10387 var label = tr.find('.payroll-column-day').attr('popupName'); 10388 var htm = '<div id="pop-processing-run-payroll">Running Payroll for ' + day + '...</div>'; 10389 var jpop = tr.closest('.glopop'); 10390 10391 if (jpop.length) { //is staff-preview popup 10392 var btnProcessPayroll = jpop.find('#pop-payroll-day-status-buttons .btnSave > a'); 10393 10394 if (btnProcessPayroll.length) { 10395 GLO.Popup.closeIfExist( $('#pop-help-cell-summary').closest('.glopop') ); 10396 btnProcessPayroll.click(); 10397 return; 10398 } 10399 } 10400 10401 GLO.Popup.Processing.open(htm, label); 10402 _conRptPayroll.processPayroll(day); 10403 } 10404 _conRptPayroll.openProcessingPayrollPopup = function(isOpenPopup, customMessage, isInfoPopup) { 10405 var dtUTC = new Date(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDay()); 10406 dtUTC.setSimpleTime(5, 50, 0); //= payroll automatically processed at 5:50 am UTC = [9:50 pm PST / 10:50 MT / 11:50 pm CST / 12:50 EST] (not during daylight savings) 10407 10408 // if (dt.getHours() > 9) { dt = new Date().addDays(1); } 10409 var dtLocalPayrollTime = dtUTC.toLocalTime(true); 10410 var msg0 = '', arrow = '<b class="arrow-right">➜</b>'; 10411 var icon = '<b class="question-icon" onclick="GLO.Report.Payroll.openHelpHistory(this)" style="margin-left: 4px;">?</b>'; 10412 10413 if (customMessage) { 10414 msg0 = '<p style="margin-bottom: 24px; text-align: center; font-weight: bold; color: #4F81BD;">' + customMessage + '...</p>'; 10415 } 10416 10417 var msg1 = '<p>Payroll is processed every night at ' + dtLocalPayrollTime.toGloTime() + '</p>'; 10418 var msg2 = '<p>Payroll can be manually processed earlier <span class="narrow-text">(for example, to print a staff\'s commission details)</span></p>'; 10419 var msg3 = '<p style="font-stretch: condensed;">After payroll is processed, if a ticket is changed ' + arrow + ' payroll must be manually re-processed' + icon + '</p>'; 10420 var htm = '<div id="pop-processing-payroll">' + msg0 + msg1 + msg2 + msg3 + '</div>'; 10421 10422 if (isOpenPopup) { 10423 var ojpop = GLO.Popup.Processing.open(htm, 'Processing Payroll...'); 10424 var jpop = ojpop.getPopup(); 10425 10426 if (isInfoPopup) { 10427 jpop.css({ "background-image": "none" }); 10428 jpop.find('.pop-header h1').text('Payroll Processing'); 10429 } 10430 10431 return ojpop; 10432 } else { 10433 return htm; 10434 } 10435 } 10436 _conRptPayroll.processPayroll = function(day, staffId) { 10437 var isSingleStaff = false, url = GLO.Link.WebsiteDomain + 'report/PayrollProcess?sfilter='; 10438 var reportPassword = $.trim($('#report-password-container #Report_Password_vc').val()); 10439 var jdPost = { "report_password_vc": reportPassword }; 10440
10441 if (!UTIL.isEmpty(staffId)) { 10442 url += staffId; 10443 isSingleStaff = true; 10444 } else { 10445 url += UTIL.cleanString(GLO.Uri.url('sfilter')); 10446 } 10447 10448 GLO.Popup.closeIfExist($('#pop-processing-run-payroll').closest('.glopop')); 10449 GLO.UI.Form.beginProcessing($('#btnViewPayrollByDay, #btnProcessPayrollByDay')); 10450 var ojProcessing = _conRptPayroll.openProcessingPayrollPopup(true); 10451 10452 if (UTIL.isDate(day)) { 10453 url += '&day=' + new Date(day).toGloDate(); 10454 } 10455 10456 $.ajax({ type: "POST", url: url, "cache": false, "data": jdPost }) 10457 .success(function(data, textStatus, jqXHR) { 10458 GLO.Popup.closeIfExist($('.pop-processing.glopop')); 10459 GLO.Popup.closeIfExist($('.pop-help-cell-summary').closest('.glopop')); 10460 ojProcessing.close(); 10461 GLO.UI.Form.resetProcessing(); 10462 10463 var fnReload = null, jdata = $(data); 10464 10465 if (GLO.Report.portalName == 'payroll-days') { 10466 fnReload = function() { 10467 //GLO.Popup.Processing.open('Re-Loading Daily Payroll Report...'); 10468 location.reload(); 10469 } 10470 } else if (isSingleStaff) { 10471 fnReload = function() { 10472 SA.POS.printTodayCommissionByStaff(null, staffId, true); 10473 } 10474 } 10475 10476 if (!UTIL.isEmpty(jdata.attr('warning_cd')) || jdata.hasClass('warning')) { 10477 var jpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Unable to Process Payroll').getPopup(); 10478 var btnLookupPass = jpop.find('#enter-report-password .btnSearchWithReportPassword.btnAdd > a'); 10479 10480 if (btnLookupPass.length) { 10481 btnLookupPass.attr('onclick', 'GLO.Report.Payroll.processPayroll("' + day + '", "' + UTIL.cleanString(staffId) + '")'); 10482 //btnLookupPass.off('click').on('click', 'GLO.Report.Payroll.processPayroll(' + day + ', "' + UTIL.cleanString(staffId) + '")'); 10483 } 10484 } else if (jdata.hasClass('success')) { 10485 GLO.Popup.closeIfExist($('#report-payroll-days-full-page').closest('.glopop')); 10486 10487 var htm = '<div id="pop-processing-payroll">' + jdata.outerHTML() + '<p>Re-Loading Daily Payroll... </p></div>'; 10488 var jpop = GLO.Popup.Processing.open(htm, 'Payroll Processed Successfully'); 10489 10490 setTimeout(fnReload, 2000); 10491 } else { 10492 _displayDaySummary(jdata); 10493 } 10494 }) 10495 .error(function(jqXHR, textStatus, errorThrown) { 10496 GLO.UI.Form.resetProcessing(); 10497 GLO.Popup.Error('Unable to lookup data at this time - Please try again'); 10498 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10499 }); 10500 } 10501 10502 function _loookupDaySummary(day) { 10503 var sfilter = UTIL.coalesceString($('#report-payroll-days-all-data').attr('sfilter'), GLO.Uri.url('sfilter')) 10504 var url = GLO.Link.WebsiteDomain + 'report/PayrollDayStatus?sfilter=' + sfilter; 10505 10506 GLO.Popup.closeIfExist($('#report-payroll-days-full-page').closest('.glopop')); 10507 10508 if (day) { 10509 url += '&day=' + day; 10510 } else { 10511 GLO.UI.Form.beginProcessing($('#btnViewPayrollByDay')); 10512 } 10513 10514 $.ajax({ type: "GET", url: url, "cache": false }) 10515 .success(function(data, textStatus, jqXHR) { 10516 var jdata = $(data); 10517 _displayDaySummary(jdata); 10518 10519 GLO.Popup.closeIfExist($('#pop-processing-view-payroll-day-summary').closest('.glopop')); 10520 GLO.UI.Form.resetProcessing(); 10521 }) 10522 .error(function(jqXHR, textStatus, errorThrown) { 10523 GLO.Popup.closeIfExist($('#pop-processing-view-payroll-day-summary').closest('.glopop')); 10524 GLO.UI.Form.resetProcessing(); 10525 GLO.Popup.Error.open('Unable to lookup data at this time - Please try again', 'Process Payroll Failed'); 10526 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 10527 }); 10528 } 10529 _conRptPayroll.viewDaySummaryFromRow = function() {
10530 var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr'); 10531 var day = tr.attr('day_d'); 10532 var label = tr.find('.payroll-column-day').attr('popupName'); 10533 var htm = '<div id="pop-processing-view-payroll-day-summary">Looking up Payroll Summary for ' + day + '...</div>'; 10534 10535 GLO.Popup.closeIfExist($('#pop-help-cell-summary').closest('.glopop')); 10536 GLO.Popup.Processing.open(htm, label); 10537 10538 _loookupDaySummary(day); 10539 } 10540 _conRptPayroll.viewToday = function() { 10541 var jrpt = $('#report-payroll-days-all-data'); 10542 //var dtLastProcess = jrpt.attr('process_dt'); 10543 var jpopDayStatus = jrpt.find('#report-payroll-day-status #pop-payroll-day-status'); 10544 10545 if (jpopDayStatus.length) { 10546 _displayDaySummary(jpopDayStatus); 10547 jpopDayStatus.remove(); 10548 } else { 10549 _loookupDaySummary(); 10550 } 10551 } 10552 function _displayDaySummary(jpopDayStatus, fnOnClose) { 10553 var jheader = jpopDayStatus.find('#pop-payroll-day-status-header'); 10554 var htmHeader = jheader.html(); 10555 jheader.remove(); 10556 10557 var htm = jpopDayStatus.outerHTML(); 10558 var jpop = GLO.Popup.Custom.openSimple(htm, htmHeader); 10559 GLO.Popup.Custom.singleButton(jpop, 'Close', fnOnClose); 10560 } 10561 10562 function _loadPayrollByDayData(jRptData, start, end) { 10563 var jtables = jRptData.find('table.tablesorter'); 10564 var isPopup = $('.quick-report.glopop #report-payroll-days-all-data').length; 10565 10566 for (var i=0; i < jtables.length; i++) { 10567 var jtbl = jtables.eq(i); 10568 UI.initTableSorter(jtbl); 10569 } 10570 10571 if (isPopup) { 10572 10573 } else { 10574 _setHeaderPeriod('payroll-report-by-day', start, end); 10575 GLO.Report.enableFullPageCheck(); 10576 10577 var jwarn = $('#payroll-history-diff-warning:visible'); 10578 var jfix = $('#report-payroll-warning-fix'); 10579 10580 if (jwarn.length && jfix.find('li').length) { 10581 var htm = '<div id="report-payroll-warning-fix-all"> <h4>Fix Differences</h4>' + jfix.removeClass('hideX').outerHTML() + '</div>'; 10582 jwarn.append(htm); 10583 } 10584 10585 jfix.remove(); 10586 } 10587 10588 GLO.Report.CellSummary.initReport(jRptData, true, true); 10589 } 10590 function _loadPayrollData(jRptData, start, end) { 10591 var jtbl = jRptData.find('table.tablesorter'); 10592 var sortArray = [1,0]; //= sort by employee, then staff 10593 UI.initTableSorter(jtbl, sortArray); 10594 10595 _initHideEmptyColumns(); 10596 _conRptPayroll.Adjust.loadDisplayAdjustment(jtbl); 10597 _loadFooter(jtbl); 10598 _initHeader(jtbl); 10599 _setHeaderPeriod('main-payroll-report', start, end); 10600 10601 GLO.Report.CellSummary.initReport(jRptData, true, true); 10602 GLO.Report.enableFullPageCheck(); 10603 } 10604 10605 _conRptPayroll.setPreviousPeriod = function(isMainPayrollReport) { 10606 _setPeriodAndSearch('previous', isMainPayrollReport); 10607 } 10608 _conRptPayroll.setCurrentPeriod = function(isMainPayrollReport) { 10609 _setPeriodAndSearch('current', isMainPayrollReport); 10610 } 10611 _conRptPayroll.setCustomPeriod = function(isMainPayrollReport) { 10612 _setPeriodAndSearch('other', isMainPayrollReport); 10613 } 10614 function _setPeriodAndSearch(period, isMainPayrollReport) { 10615 var jDatePeriod = $('#payroll-report-date-period'); 10616 var jDateRange = $('#payroll-report-date-range'); 10617 10618 if (!isMainPayrollReport) { 10619 jDateRange.addClass('hide'); 10620 } 10621 10622 jDatePeriod.find('.btnMultiChild .btnAdd.selected').removeClass('selected'); 10623 var btn = jDatePeriod.find('.btnMultiChild[value="' + period + '"]').find('.btnAdd').addClass('selected'); 10624 10625 if (period == 'previous') { 10626 var start = jDatePeriod.attr('previous_start_d'); 10627 var end = jDatePeriod.attr('previous_end_d'); 10628 } else if (period == 'current') { 10629 var start = jDatePeriod.attr('current_start_d'); 10630 var end = jDatePeriod.attr('current_end_d'); 10631 } else if (period == 'other') { 10632 jDateRange.removeClass('hide'); 10633 jDatePeriod.find('#report-start').focus(); 10634 return; 10635 } 10636 10637 jDateRange.find('#report-start').val(start).change(); 10638 jDateRange.find('#report-end').val(end).change(); 10639
10640 GLO.Report.Payroll.search(); 10641 GLO.UI.Form.beginProcessing(btn); 10642 } 10643 10644 function _initHeader(jtbl) { 10645 //var tr = jtbl.find('#report-payroll-header1'); 10646 10647 _initColumnGroup(jtbl, 'service-percent', 'commission-percent'); 10648 _initColumnGroup(jtbl, 'hourly-rate', 'hourly', 'hours-worked'); 10649 //_initColumnGroup(jtbl, 'min-weekly', 'day'); 10650 _initColumnGroup(jtbl, 'sale-product', 'sale', 'sale-service'); 10651 10652 _initColumnGroup(jtbl, 'product-dollar', 'commission-dollar', 'service-dollar'); 10653 _initColumnGroup(jtbl, 'service-fee', 'fee', 'supply-fee'); 10654 //_initColumnGroup(jtbl, 'adjust', 'adjust', 'adjust-note'); 10655 _initColumnGroup(jtbl, 'hourly-wage', 'total', 'total'); 10656 10657 _initColumnGroup(jtbl, 'full-days', 'day', 'actual-days'); 10658 } 10659 10660 function _setHeaderPeriod(reportClass, start, end) { 10661 if (UTIL.isDate(start) && UTIL.isDate(end)) { 10662 var jperiod = $('#report-main.' + reportClass + ' #payroll-report-date-period'); 10663 var btnPrev = jperiod.find('.btnMultiPreviousPeriod .btnAdd'); 10664 var btnCurr = jperiod.find('.btnMultiCurrentPeriod .btnAdd'); 10665 10666 var prevStart = new Date(jperiod.attr('previous_start_d')).toGloDate(); 10667 var prevEnd = new Date(jperiod.attr('previous_end_d')).toGloDate(); 10668 10669 var currStart = new Date(jperiod.attr('current_start_d')).toGloDate(); 10670 var currEnd = new Date(jperiod.attr('current_end_d')).toGloDate(); 10671 10672 var searchStart = new Date(start).toGloDate(); 10673 var searchEnd = new Date(end).toGloDate(); 10674 10675 if (searchStart == prevStart && searchEnd == prevEnd) { 10676 btnPrev.addClass('selected'); 10677 btnCurr.removeClass('selected'); 10678 } else if (searchStart == currStart && searchEnd == currEnd) { 10679 btnPrev.removeClass('selected'); 10680 btnCurr.addClass('selected'); 10681 } else { 10682 btnPrev.removeClass('selected'); 10683 btnCurr.removeClass('selected'); 10684 } 10685 } 10686 } 10687 function _initColumnGroup(jtbl, column, columnGroup, columnCheck) { 10688 var jgroup = jtbl.find('.group-' + columnGroup); 10689 var jtd = jtbl.find('tr#report-payroll-header1 .group-' + columnGroup + ':first'); //jtbl.find('tr#report-payroll-header1 .' + column + '-column'); 10690 10691 var jtd2 = jtbl.find('tr#report-payroll-header2 .group-' + columnGroup); 10692 var title = UTIL.coalesceString(jtd2.text(), columnGroup.replace('-', ' ')); 10693 10694 var isHide = SA.Help.getCookieItem('payroll-table', 'group-' + columnGroup); 10695 //var arrowOpen = '<span class="open-columns-icon"><b onclick="GLO.Report.Payroll.displayColumnGroup(true, \'' + column + '\', \'' + columnGroup + '\')">↔</b></span>'; 10696 var closeIcon = '<span class="close-columns-icon" title="' + title + '"><b onclick="GLO.Report.Payroll.displayColumnGroup(false, \'' + column + '\', \'' + columnGroup + '\')">✖</b></span>'; 10697 10698 if (!isHide) { 10699 isHide = true; 10700 10701 if (columnGroup === 'adjust') { 10702 var jcheck = jtbl.find('.adjust-input'); 10703 var jnote = jtbl.find('.adjust-note .payroll-adjust-note'); 10704 10705 if (jnote.length) { 10706 isHide = false; 10707 } else { 10708 for (var i=0; i < jcheck.length; i++) { 10709 if (UTIL.isEmpty(jcheck.eq(i).val())) { 10710 isHide = false; 10711 break; 10712 } 10713 } 10714 } 10715 } else { 10716 var jcheck = jtbl.find('.' + column + '-column, .' + columnCheck + '-column'); 10717 10718 for (var i=0; i < jcheck.length; i++) { 10719 if (UTIL.isEmpty(jcheck.eq(i).text())) { 10720 isHide = false; 10721 break; 10722 } 10723 } 10724 } 10725 } 10726 10727 jtd.html(closeIcon); 10728 10729 if (isHide) { 10730 _conRptPayroll.displayColumnGroup(false, column, columnGroup, true); 10731 } 10732 } 10733 _conRptPayroll.enableFullPage = function() { 10734 var cookie = $.cookies.get('payroll-table'); //if cookie exists -> reload page 10735 10736 UTIL.setCookie('payroll-table', null); 10737 GLO.Report.enableFullPage(true); 10738 10739 if (!UTIL.isEmpty(cookie)) { 10740 GLO.Popup.Processing.open('Reloading to display all columns', 'Display All Columns'); 10741 10742 setTimeout(function() { 10743 location.reload(); 10744 }, 100); 10745 } 10746 } 10747 _conRptPayroll.displayColumnGroup = function(isDisplay, column, columnGroup, isInit) { 10748 var jtbl = $('#report-payroll-summary'); 10749 var jgroup = jtbl.find('.group-' + columnGroup); 10750 var jcolumn = jtbl.find('.' + column + '-column'); 10751 10752 jtbl.find('.narrow-column.group-' + columnGroup).remove(); 10753 10754 if (isDisplay) { 10755 if (!isInit) { 10756 SA.Help.setCookieItem('payroll-table', 'group-' + columnGroup, true); 10757 } 10758 10759 jgroup.removeClass('hideX'); 10760 } else { 10761 if (!isInit) { 10762 SA.Help.setCookieItem('payroll-table', 'group-' + columnGroup); 10763 } 10764 10765 jgroup.addClass('hideX'); 10766 10767 var innerIcon = '<b onclick="GLO.Report.Payroll.displayColumnGroup(true, \'' + column + '\', \'' + columnGroup + '\')">↔</b>'; 10768 var title = UTIL.coalesceString(jgroup.closest('thead').find('tr#report-payroll-header2 .group-' + columnGroup).text(), columnGroup.replace('-', ' ')); 10769 var icon = '<span class="open-columns-icon" title="' + title + '">' + innerIcon + '</span>'; 10770 10771 var tdStart = '<td class="group-' + columnGroup + ' narrow-column">'; 10772 var jtd = jtbl.find('tr').find('th.group-' + columnGroup + ':first, td.group-' + columnGroup + ':first'); 10773 10774 for (var i=0; i < jtd.length; i++) { 10775 if (!jtd.eq(i).hasClass('hideX')) { 10776 if (i === 0) { 10777 jtd.eq(i).before(tdStart + icon + '</td>'); 10778 } else { 10779 jtd.eq(i).before(tdStart + '</td>'); 10780 } 10781 } 10782 } 10783 } 10784 } 10785 function _loadFooter(jtbl) { 10786 var tfoot = jtbl.find('tfoot'); 10787 var staffCount = UTIL.coalesceInt(tfoot.attr('staff_count_sr'));
10788 var hourlyCount = UTIL.coalesceInt(tfoot.attr('staff_hourly_count_sr')), commissionCount = UTIL.coalesceInt(tfoot.attr('staff_commission_count_sr')); 10789 10790 if (staffCount > hourlyCount + commissionCount || (hourlyCount > 0 && commissionCount > 0)) { 10791 jtbl.addClass('style-staff-type'); 10792 } else { 10793 jtbl.find('tr .staff-type-column').remove(); 10794 } 10795 } 10796 10797 _conRptPayroll.changeDateRange = function(start, end) { 10798 $('.report-search-header #report-start').val(start); 10799 $('.report-search-header #report-end').val(end); 10800 10801 GLO.Report.Payroll.search(); 10802 _conRptPayroll.highlightDateRange(); 10803 } 10804 10805 _conRptPayroll.highlightDateRange = function() { 10806 GLO.Popup.close(); 10807 UI.highlight($('.report-search-header > ul'), null, null, true); 10808 } 10809 10810 function _getPayrollLink(start) { 10811 var end = new Date(start).addDays(7).toGloDate(); 10812 var link = 'reports/payroll?start=' + start + '&end=' + end; 10813 var dt = new Date(start).getWeekDayString() + ' ' + new Date(start).toSADate(true); 10814 10815 return '<a onclick=\'GLO.Report.Payroll.changeDateRange("' + start + '", "' + end + '")\'>Starting ' + dt + '</a>'; 10816 } 10817 10818 _conRptPayroll.printReport = function() { 10819 //GLO.Report.enableFullPage(false); 10820 GLO.Popup.close($('#pop-print-payroll').closest('.glopop')); 10821 UI.Print.printOnDevice(); 10822 } 10823 _conRptPayroll.openPrintReport = function() { 10824 var jdt = $('#payroll-report-date-range'); 10825 var start = UTIL.fromSADate(jdt.find('#report-start').val(), true, true); 10826 var end = UTIL.fromSADate(jdt.find('#report-end').val(), true, true); 10827 var urlPayrollByDay = 'report/payrollDays?print=1&start=' + start + '&end=' + end + '&sfilter=' + GLO.Uri.query('sfilter'); 10828 10829 var btn1 = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUri(\'' + urlPayrollByDay + '\', this, event, true)">Daily Payroll</a></span>'; 10830 var btn2 = '<span class="btnAdd"><a onclick="GLO.Report.Payroll.printReport()">Payroll Report</a></span>'; 10831 var btn3 = '<span class="btnAdd"><a onclick="GLO.Report.Payroll.gotoPrintReport()">Sales History</a></span>'; 10832 10833 var htm = '<div id="pop-print-payroll"><div style="margin-top: 24px;">' + btn1 + '</div><div style="margin: 24px;">' + btn2 + '</div></div>'; 10834 var jpop = GLO.Popup.Custom.openSimple(htm, 'Print'); 10835 GLO.Popup.Custom.singleButton(jpop, 'Close'); 10836 } 10837 _conRptPayroll.gotoPrintReportByStaff = function() { 10838 var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr'); 10839 var sid = tr.attr('staff_id'); 10840 var sname = tr.find('.staff-column').text(); 10841 10842 _conRptPayroll.gotoPrintReport(sid, sname); 10843 } 10844 _conRptPayroll.gotoPrintReport = function(sid, sname) { 10845 GLO.Popup.close($('#pop-print-payroll').closest('.glopop')); 10846 10847 var msg = '', jrpt = $('#doc3 #report-main'); 10848 var start = UTIL.fromSADate(jrpt.find('#report-start:visible').val(), true, true); 10849 var end = UTIL.fromSADate(jrpt.find('#report-end:visible').val(), true, true); 10850 10851 var url = 'reports/saleshistory?isfullpage=1&open=print&start=' + start + '&end=' + end; //toDo: pass -> daily fees (supply, cleaning) | '+ min' 10852 var title = UTIL.coalesce(title, 'Print Sales'); 10853 10854 if (!UTIL.isEmpty(sid)) { 10855 url += '&sfilter=' + sid; 10856 } 10857 10858 if (!UTIL.isEmpty(sname)) { 10859 msg = 'Printing Sales report for ' + sname + '<br/><br/>'; 10860 } 10861 10862 GLO.Popup.Processing.open(msg + 'Loading Printable Report...', title); 10863 GLO.Report.CellSummary.gotoReport(url, null, event); 10864 } 10865 _conRptPayroll.exportReport = function() { 10866 //var tbody = document.getElementById('report-payroll-summary-container'); 10867 var jrpt = $('#report-payroll-summary'); 10868 var trs = jrpt.find('tr'); 10869 var fileName = 'Payroll ' + new Date(jrpt.attr('start_d')).toGloDate(true) + ' - ' + new Date(jrpt.attr('end_d')).toGloDate(true); 10870 10871 _exportExcel(trs, fileName); 10872 //exportTableToExcel('report-payroll-summary-container', filename = ''); 10873 } 10874 10875 function exportTableToExcel(tableID, filename = '') { 10876 var downloadLink; 10877 var dataType = 'application/vnd.ms-excel'; 10878 var tableSelect = document.getElementById(tableID); 10879 var tableHTML = tableSelect.outerHTML.replace(/ /g, '%20'); 10880 10881 filename = filename ? filename + '.xls' : 'excel_data.xls'; //Specify file name 10882 downloadLink = document.createElement("a"); //Create download link element 10883 document.body.appendChild(downloadLink); 10884 10885 if (navigator.msSaveOrOpenBlob) { 10886 var blob = new Blob(['\ufeff', tableHTML], { 10887 type: dataType 10888 }); 10889 navigator.msSaveOrOpenBlob(blob, filename); 10890 } else { 10891 downloadLink.href = 'data:' + dataType + ', ' + tableHTML; //Create a link to the file 10892 downloadLink.download = filename;
10892 //Setting the file name 10893 downloadLink.click(); //triggering the function 10894 } 10895 } 10896 10897 function _exportExcel(trs, fileName) { 10898 var htm = '<table border="2px">'; 10899 var textRange, j=0, rowCount = 0; 10900 10901 for (a=0 ; a < trs.length ; a++) { 10902 var tr = trs.eq(a); 10903 10904 if (!tr.hasClass('ignore-export')) { 10905 if (tr.parent().is('thead')) { 10906 var css = 'text-align: center; font-weight: bold; background-color: rgb(180,200,255);'; 10907 } else if (tr.parent().is('tfoot')) { 10908 var css = 'background-color: rgb(200,200,200);'; 10909 } else { 10910 if (rowCount % 2 === 1) { 10911 var css = 'background-color: rgb(250,250,250);'; 10912 } else { 10913 var css = ''; 10914 } 10915 10916 ++rowCount; 10917 } 10918 10919 htm += '<tr style="' + css + '">'; 10920 var tds = trs.eq(a).find('th,td'); 10921 10922 for (var b=0; b < tds.length; b++) { 10923 var td = tds.eq(b); 10924 10925 if (!td.hasClass('ignore-export')) { 10926 td = td.clone(); 10927 td.find('.btnAdd, .btnSave').remove(); 10928 10929 if (td.find('input').length) { 10930 var jinput = td.find('input'); 10931 td.append(jinput.val()); 10932 jinput.remove(); 10933 } 10934 10935 htm += td.outerHTML(); 10936 } 10937 } 10938 10939 htm += '</tr>'; 10940 } 10941 } 10942 10943 htm += '</table>'; 10944 htm = htm.replace(/<A[^>]*>|<\/A>/g, ''); //remove if u want links in your table 10945 htm = htm.replace(/<img[^>]*>/gi, ''); //remove if u want images in your table 10946 //htm = htm.replace(/<input[^>]*>|<\/input>/gi, ''); //removes input params 10947 10948 var ua = window.navigator.userAgent; 10949 var msie = ua.indexOf("MSIE "); 10950 10951 if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) { // If Internet Explorer 10952 txtArea1.document.open("txt/html","replace"); 10953 txtArea1.document.write(htm); 10954 txtArea1.document.close(); 10955 txtArea1.focus(); 10956 sa = txtArea1.document.execCommand('SaveAs', true, fileName); 10957 } else { 10958 //sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(htm)); 10959 10960 var downloadLink = $('#btnExportLink')[0]; 10961 downloadLink.href = 'data:application/vnd.ms-excel,' + encodeURIComponent(htm); 10962 downloadLink.download = fileName; 10963 downloadLink.click(); 10964 } 10965 10966 //return (sa); 10967 } 10968 10969 _conRptPayroll.openDailyPrintSettings = function() { 10970 var header = 'Daily Payroll Print which sections?'; 10971 var msg = '<p>What sections would you like to print?</p>'; 10972 var list = '<ul>' 10973 + '<li style="margin-bottom: 8px;"> <input type="checkbox" id="Payroll_Daily_Print_cd10" value="M"> <label for="Payroll_Daily_Print_cd10">Main Daily summary</lable> </li>' 10974 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd20" value="C"> <label for="Payroll_Daily_Print_cd20">Cash Drawer</lable> </li>' 10975 10976 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd110" value="D"> <label for="Payroll_Daily_Print_cd110">Discount</lable> </li>' 10977 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd120" value="P"> <label for="Payroll_Daily_Print_cd120">Payment Type</lable> </li>' 10978 + '<li style="margin-bottom: 8px;"> <input type="checkbox" id="Payroll_Daily_Print_cd130" value="T"> <label for="Payroll_Daily_Print_cd130">Tip</lable> </li>' 10979 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd140" value="S"> <label for="Payroll_Daily_Print_cd140">Early/Normal Service Commission</lable> </li>' 10980 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd150" value="F"> <label for="Payroll_Daily_Print_cd150">Fee</lable> </li>' 10981 + '<li> <input type="checkbox" id="Payroll_Daily_Print_cd160" value="W"> <label for="Payroll_Daily_Print_cd160">Total Wage</lable> </li>' 10982 + "</ul>"; 10983 10984 var htm = '<div id="pop-daily-payroll-print">' + msg + list + '</div>'; 10985 var jpop = GLO.Popup.Custom.openSimple(htm, header, GLO.Report.Payroll.
10985saveDailyPrintSettings); 10986 var arr = $('#report-payroll-days-full-page').attr('payrollDailyPrint').split(','); 10987 var isAll = (arr.length === 0 || (arr.length === 1 && (arr[0] === '' || arr[0] === 'A'))); 10988 10989 if (isAll) { 10990 jpop.find(':checkbox').prop('checked', true); 10991 } else { 10992 for (var i=0; i < arr.length; i++) { 10993 jpop.find(':checkbox[value = "' + arr[i] + '"]').prop('checked', true); 10994 } 10995 } 10996 } 10997 _conRptPayroll.saveDailyPrintSettings = function() { 10998 var settings = '', jpop = $('#pop-daily-payroll-print').closest('.glopop'); 10999 var jbox = jpop.find(':checkbox:checked'); 11000 11001 for (var i=0; i < jbox.length; i++) { 11002 if (i > 0) { settings += ','; } 11003 11004 settings += jbox.eq(i).val(); 11005 } 11006 11007 var url = GLO.Link.WebsiteDomain + 'report/PayrollDailyPrint?settings=' + settings; 11008 11009 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 11010 11011 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 11012 .success(function(data, textStatus, jqXHR) { 11013 GLO.UI.Form.resetProcessing(); 11014 GLO.Popup.close(jpop); 11015 GLO.Popup.Processing.open('Reloading Print Settings...', 'Print Settings Saved'); 11016 11017 setTimeout(function() { 11018 location.reload(); 11019 }, 100); 11020 }) 11021 .error(function(jqXHR, textStatus, errorThrown) { 11022 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11023 }); 11024 } 11025 11026 _conRptPayroll.openDailyPayrollWarning = function() { 11027 var htmWarn = $($('#daily-payroll-report-header-help #payroll-history-diff-warning').outerHTML()).removeClass('hide').removeClass('hideX').outerHTML(); 11028 var htmFix = $($('#report-payroll-warning-fix').outerHTML()).removeClass('hide').removeClass('hideX').outerHTML(); 11029 var fixHeader = '<h4>Fix Differences</h4>'; 11030 var htm = '<div id="pop-warn-payroll-daily">' + htmWarn + fixHeader + htmFix + '</div>'; 11031 11032 var ojpop = GLO.Popup.Warning.open(htm, 'Current Payroll Report vs Payroll History'); 11033 var jpop = ojpop.getPopup(); 11034 11035 GLO.Popup.Custom.singleButton(jpop, 'Close'); 11036 } 11037 11038 _conRptPayroll.printToday = function() { 11039 GLO.Report.Payroll.setCustomPeriod(); 11040 var now = new Date().toSADate() + ', ' + new Date().getFullYear(); 11041 var jhead = $('#payroll-report-header'); 11042 11043 jhead.find('#report-start').val(now).change(); 11044 jhead.find('#report-end').val(now).change(); 11045 11046 GLO.Popup.closeIfExist( $('#pop-payroll-day-status').closest('.glopop') ); 11047 GLO.Report.Payroll.search(); //http://www.test3.com/report/payrollDays?start=8/23/2026&end=8/23/2026&sfilter=&period=other 11048 } 11049 11050 11051 _conRptPayroll.Adjust = (function() { 11052 function _cAdjust() {}; 11053 11054 _cAdjust.loadDisplayAdjustment = function(jtbl) { 11055 var hasAdjustment = false, isManager = (GLO.Info.roleType > 219); 11056 var columns = jtbl.find('tbody .adjust-column'); 11057 11058 if (isManager) { 11059 for (var i=0; i < columns.length; i++) { 11060 _colorAdjust(columns.eq(i)); 11061 } 11062 11063 columns.removeClass('hide-on-load'); 11064 } else { 11065 for (var i=0; i < columns.length; i++) { 11066 var amt = $.trim(columns.eq(i).text()).replace('$', ''); 11067 var amt = UTIL.coalesceMoney(amt); 11068 11069 if (amt !== 0) { 11070 hasAdjustment = true; 11071 } 11072 } 11073 11074 if (hasAdjustment) { 11075 columns.removeClass('hide-on-load'); 11076 } 11077 } 11078 } 11079 function _colorAdjust(td) { 11080 var amt = UTIL.coalesceMoney(td.find('input').val()); 11081 11082 if (amt > 0) { 11083 td.addClass('positive-amount').removeClass('negative-amount'); 11084 } else if (amt < 0) { 11085 td.addClass('negative-amount').removeClass('positive-amount'); 11086 } else { 11087 td.removeClass('negative-amount').removeClass('positive-amount'); 11088 } 11089 } 11090 _cAdjust.changeAmount = function(inputElement) { 11091 if (!GLO.Report.allowReportChange()) { return; } 11092 11093 var td = $(inputElement).closest('td').addClass('unsaved-update'); //.find('.btnSave').removeClass('hide'); 11094 _colorAdjust(td); 11095 } 11096 _cAdjust.openFromPopup = function(element) { 11097 var jpop = $('#pop-adjust-list'); //.closest('.glopop'); 11098 var staffId = jpop.attr('staff_id'); 11099 var staffName = jpop.find('.adjust-staff').text(); 11100 11101 var li = $(element).closest('li'); 11102 var payrollId = li.attr('id'), start = li.attr('start_d'), end = li.attr('end_d'); 11103 var amount = li.find('.adjust-amount').text().replace('$', ''); 11104 var note = li.find('.adjust-note').text(); 11105 11106 _cAdjust.openNote(payrollId, amount, note, start, end, staffId, staffName); 11107 } 11108 _cAdjust.openFromRow = function(element) { 11109 if (!GLO.Report.allowReportChange()) { return; } 11110 11111 var tr = $(element).closest('tr'); //$('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]'); 11112 var adjustCount = UTIL.coalesceInt(tr.attr('adjust_count_sr'));
11113 var staffName = tr.find('.staff-column').text(), staffId = tr.attr('staff_id'); 11114 11115 if (adjustCount > 1) { 11116 _getAdjustments(staffId, staffName); 11117 } else { 11118 var amount = tr.find('.adjust-column').find('input').val(); 11119 var note = tr.find('.payroll-adjust-note').text(); 11120 var payrollId = tr.attr('adjust_id'); 11121 var start = tr.attr('adjust_start_d'), end = tr.attr('adjust_end_d'); 11122 11123 _cAdjust.openNote(payrollId, amount, note, start, end, staffId, staffName); 11124 } 11125 } 11126 _cAdjust.openNote = function(payrollId, amount, note, start, end, staffId, staffName) { 11127 var tbl = $('#report-payroll-summary'); 11128 var dt1 = UTIL.coalesceDate(start, tbl.attr('start_d')).toGloDate(), dt2 = UTIL.coalesceDate(end, tbl.attr('end_d')).toGloDate(); 11129 var id = UTIL.cleanString(payrollId); 11130 var h1 = 'Payroll Adjust Amount / Note' 11131 11132 var msg = '<p id="pop-payroll-adjust-message">' + staffName + ': ' + new Date(dt1).toSADate(true) + ' - ' + new Date(dt2).toSADate(true) + '</p>'; 11133 msg += '<div id="pop-display-hourly">Hourly: <b></b>/hour</div>'; 11134 msg += '<div id="pop-display-total" > Total: <b></b></div>'; 11135 11136 var labelAmount = '<label for="Adjustment_mn" style="margin: 0;">Adjust <b class="dollar-sign">$</b></label>'; 11137 var inputAmount = '<input id="Adjustment_mn" type="text" maxlength="7" value="' + UTIL.displayMoney(amount, true) + '" onkeypress="UI.numberOnly(event, true)" onkeyup="GLO.Report.Payroll.Adjust.keyupAmount()">'; 11138 var htmAmount = '<div>' + labelAmount + inputAmount + '</div>'; 11139 11140 var textarea = '<div><textarea id="Note_vcl" maxlength="4000" placeholder="Note">' + note + '</textarea></div>'; 11141 11142 var htm = '<div id="pop-edit-adjust" payroll_id="' + id + '" staff_id="' + staffId + '" start_d="' + dt1 + '" end_d="' + dt2 + '">' + msg + htmAmount + textarea + '</div>'; 11143 var jpop = GLO.Popup.Custom.open(htm, h1, GLO.Report.Payroll.Adjust.saveAdjust).getPopup().addClass('no-persist'); 11144 var jsave = jpop.find('.pop-buttons').addClass('pop-buttons2').find('.btnSave'); 11145 11146 jsave.after('<span class="btnDelete" style="position: absolute; right: 4px; margin: 0;"><a onclick="GLO.Report.Payroll.Adjust.deleteAsk()">Delete</a></span>'); 11147 jsave.css({ "position": "relative", "right": "inherit", "margin": "0" }); 11148 _cAdjust.keyupAmount(); 11149 } 11150 _cAdjust.keyupAmount = function() { 11151 var jpop = $('#pop-edit-adjust'); //.closest('.glopop') 11152 var sid = jpop.attr('staff_id'); 11153 var newAdjust = UTIL.coalesceMoney(jpop.find('#Adjustment_mn').val()); 11154 11155 var tr = $('#report-payroll-summary').find('tr.row-commission[staff_id=' + sid + ']'); 11156 var total = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', '')); 11157 var currAdjust = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn')); 11158 var hrs = Math.round(parseInt(tr.find('.hours-worked-column').attr('minutes_worked_sr'))/60, 2); 11159 11160 var newTotal = UTIL.coalesceMoney(total - currAdjust + newAdjust); 11161 var newHourly = UTIL.displayMoney(newTotal/hrs); 11162 11163 var jtotal = jpop.find('#pop-display-total b').removeClass('is-negative'), jhr = jpop.find('#pop-display-hourly b').removeClass('is-negative'); 11164 11165 if (newTotal < 0) { 11166 jtotal.addClass('is-negative'); 11167 jhr.addClass('is-negative'); 11168 } 11169 11170 jtotal.text(UTIL.displayMoney(newTotal, false, false, true)); 11171 jhr.text(newHourly); 11172 } 11173 function _getAdjustments(staffId, staffName) { 11174 var tbl = $('#report-payroll-summary'); 11175 var start = tbl.attr('start_d'), end = tbl.attr('end_d'); 11176 var url = GLO.Link.WebsiteDomain + 'report/GetPayrollAdjustment?staffid=' + staffId + '&start=' + start + '&end=' + end; 11177 11178 var msg = 'Payroll Adjustments and Notes for <b class="adjust-staff">' + staffName + '</b> between ' + new Date(start).toSADate(true) + ' - ' + new Date(end).toSADate(true); 11179 var jprocessing = GLO.Popup.Processing.open('Loading ' + msg + '...', 'Payroll Adjustments & Notes'); 11180
11181 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 11182 .success(function(data, textStatus, jqXHR) { 11183 var ul = '<ul>'; 11184 var jdata = $(data); 11185 var lis = jdata.find('#payroll-adjust-list li'); 11186 11187 for (var i=0; i < lis.length; i++) { 11188 var li = lis.eq(i), amtColor = ''; 11189 var amt = UTIL.displayMoney(li.attr('adjustment_mn'), true), id = li.attr('staff_payroll_id'); 11190 var dt1 = li.attr('start_d'), dt2 = li.attr('end_d') 11191 var note = li.text(); 11192 11193 if (amt > 0) { 11194 amtColor = 'green'; 11195 } else if (amt < 0) { 11196 amtColor = 'rgb(240,0,0)'; 11197 } 11198 11199 var adjustRange = '<span class="date-range">' + new Date(dt1).toSADate(true) + ' - ' + new Date(dt2).toSADate(true) + '</span>'; 11200 var money = '<b class="adjust-amount" style="color: ' + amtColor + ';">' + UTIL.displayMoney(amt) + '</b>'; 11201 var noteHtm = '<i class="adjust-note">' + note + '</i>'; 11202 11203 ul += '<li onclick="GLO.Report.Payroll.Adjust.openFromPopup(this)" id="' + id + '" start_d="' + dt1 + '" end_d="' + dt2 + '">' + adjustRange + money + noteHtm + '</li>'; 11204 } 11205 11206 jprocessing.close(); 11207 msg = '<p style="padding-left: 8px; padding-right: 4px;">' + msg + '</p>'; 11208 var msgSmall = '<p style="text-align: center;"><small style="color: #666;">Press any row below to edit the note or amount</small></p>'; 11209 var htm = '<div id="pop-adjust-list" staff_id="' + staffId + '">' + msg + msgSmall + ul + '</ul> </div>'; 11210 var jpop = GLO.Popup.Custom.openSimple(htm, staffName + ' Adjust Amount / Notes'); 11211 GLO.Popup.Custom.singleButton(jpop, 'Close'); 11212 }) 11213 .error(function(jqXHR, textStatus, errorThrown) { 11214 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11215 }); 11216 } 11217 11218 _cAdjust.deleteAsk = function() { 11219 //var jpop = $('#pop-edit-adjust').closest('.glopop'); 11220 11221 var msg = 'Are you sure you want to delete?'; 11222 var jpop = GLO.Popup.Confirm.open(msg, 'Confirm Delete', GLO.Report.Payroll.Adjust.deleteConfirmed).getPopup(); 11223 } 11224 _cAdjust.deleteConfirmed = function() { 11225 var jadjust = $('#pop-edit-adjust'); 11226 var jpop = jadjust.closest('.glopop'); 11227 var id = UTIL.cleanString(jadjust.attr('payroll_id')), staffid = jadjust.attr('staff_id'); 11228 11229 var url = GLO.Link.WebsiteDomain + 'report/RemovePayrollAdjustment?staffid=' + staffid + '&id=' + id; 11230 var tr = $('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]'); 11231 11232 GLO.UI.Form.beginProcessing(jpop.find('.btnDelete')); 11233 11234 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 11235 .success(function(data, textStatus, jqXHR) { 11236 var cnt = parseInt(tr.attr('adjust_count_sr')) - 1; 11237 var prevAdjust = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn')); 11238 tr.attr('adjust_count_sr', cnt); 11239 11240 if (cnt === 0 && prevAdjust == 0) { 11241 tr.attr('adjust_count_sr', '0').removeAttr('adjust_id'); 11242 tr.find('.adjust-column').find('input').val(''); 11243 tr.find('.adjust-note').html('<span class="btnAdjust btnAdd"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">add</a></span>'); 11244 } else { 11245 setTimeout(function() { location.reload(); }, 400); 11246 } 11247 11248 GLO.UI.Form.resetProcessing(); 11249 GLO.Popup.close(jpop); 11250 GLO.Popup.Success.open('Adjustment Amount and Note Deleted for ' + tr.find('.staff-column').text(), 'Delete Completed'); 11251 11252 var tdAdjust = tr.find('.adjust-column').removeClass('unsaved-update'); 11253 _colorAdjust(tdAdjust); 11254 }) 11255 .error(function(jqXHR, textStatus, errorThrown) { 11256 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11257 }); 11258 } 11259 11260 _cAdjust.saveAdjust = function() { 11261 var jadjust = $('#pop-edit-adjust'); 11262 var jpop = jadjust.closest('.glopop'); 11263 var amount = UTIL.coalesceMoney(jadjust.find('#Adjustment_mn').val(), true); 11264 var id = UTIL.cleanString(jadjust.attr('payroll_id')), staffid = jadjust.attr('staff_id'), start = jadjust.attr('start_d'), end = j
11264adjust.attr('end_d'); 11265 var note = UTIL.htmlEncode(jadjust.find('#Note_vcl').val()); 11266 11267 var url = GLO.Link.WebsiteDomain + 'report/SavePayrollAdjustment?staffid=' + staffid + '&amount=' + amount + '&start=' + start + '&end=' + end + '&id=' + id; 11268 var tr = $('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]'); 11269 11270 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 11271 GLO.UI.Form.beginProcessing(tr.find('.btnSave')); 11272 11273 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": { "note": note } }) 11274 .success(function(data, textStatus, jqXHR) { 11275 var cnt = UTIL.coalesceInt(tr.attr('adjust_count_sr'), 0); 11276 var adjustId = $(data).attr('staff_payroll_id'); 11277 11278 var prevAmount = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn')); 11279 var msg = 'Adjustment Saved for ' + tr.find('.staff-column').text(); 11280 11281 if (cnt < 2) { 11282 if (!UTIL.isEmpty(note)) { 11283 var htmNote = '<span class="payroll-adjust-note"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">' + note + '</a></span>'; 11284 } else { 11285 var htmNote = '<span class="btnAdjust btnAdd"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">add</a></span>'; 11286 } 11287 11288 tr.attr('adjust_count_sr', '1').attr('adjust_id', adjustId); 11289 tr.find('.adjust-column').find('input').val(amount); 11290 tr.find('.adjust-note').html(htmNote); 11291 } 11292 11293 GLO.UI.Form.resetProcessing(); 11294 GLO.Popup.close(jpop); 11295 GLO.Popup.close($('#pop-adjust-list').closest('.glopop')); 11296 11297 if (cnt > 1 || prevAmount != amount) { 11298 setTimeout(function() { location.reload(); }, 400); 11299 11300 msg += '<br/><br/>Re-Loading Payroll Report with new amount...'; 11301 } 11302 11303 GLO.Popup.Success.open(msg, 'Save Successful'); 11304 11305 var tdAdjust = tr.find('.adjust-column').removeClass('unsaved-update'); 11306 _colorAdjust(tdAdjust); 11307 }) 11308 .error(function(jqXHR, textStatus, errorThrown) { 11309 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11310 }); 11311 } 11312 11313 return _cAdjust; 11314 })(); 11315 11316 return _conRptPayroll; 11317})(); 11318 11319 11320GLO.Report.Timesheet = (function() { 11321 function _conRptTimesheet() { } 11322 var _timeoutUpdateInProgress = null, _bonusCount = 0; 11323 11324 _conRptTimesheet.init = function() { 11325 GLO.Info.init(); 11326 GLO.Report.portalName = 'timesheet'; 11327 GLO.Report.init(); 11328 GLO.Report.Sales.initStaffFilter(); 11329 GLO.Report.isInit = true; 11330 GLO.Report.setupFastClick(); 11331 11332 var j = $('.appt-list-search'); 11333 j.find('#report-header-search').click(GLO.Report.Timesheet.search); 11334 11335 j.find('#Week_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 11336 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 11337 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.Timesheet.datePickerOnSelect }); 11338 11339 var jbegin = $('#timesheet-header').find('.Begin_dt'); 11340 var dt = new Date(jbegin.val()); 11341 var firstDayOfWeek = jbegin.datepicker('option', 'firstDay'); //= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1) 11342 _setWeekDateRange(dt, firstDayOfWeek); 11343 11344 _initView(j); 11345 GLO.Report.isInit = false; 11346 11347 if (GLO.Info.roleType === undefined) { GLO.Info.init(); } 11348 11349 if (GLO.Info.roleType > 199 && GLO.Info.roleType < 220 && GLO.Data.Staff.role_report_cd == 0) { //= receptionists can only see their own data. 11350 $('#top-staffName').remove(); 11351 } else if (GLO.Info.roleType > 219) { 11352 _initSFilter();
11352 //$('#top-staffName #staff-filter').val(GLO.Info.StaffId); 11353 _initClockInIcon(); 11354 } 11355 11356 _loadApprovalType(); 11357 _loadDayTable(true); 11358 _initUriTimesheet(); 11359 } 11360 function _initUriTimesheet() { 11361 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 11362 11363 if (!UTIL.isEmpty(open)) { 11364 if (open === 'approve') { 11365 GLO.Report.Timesheet.openApproveSetting(); 11366 } else if (open === 'more') { 11367 GLO.Report.Timesheet.displayMoreHelp(true); 11368 UI.highlight($('#report-header-help'), 100, 4500); 11369 } 11370 } 11371 } 11372 function _postSearchSetHeader() { 11373 var jheader = $('#bd #timesheet-report-header.report-header').find('.report-header-text'); 11374 var jrpt = $('#bd #report-main').find('table.tablesorter'); 11375 var staffName = jrpt.find('tbody').find('td.staff-column:first').text(); 11376 11377 jheader.find('.display-on-print').remove(); 11378 11379 if (!UTIL.parseBool(jheader.attr('hasMultipleStaffFilter')) && !UTIL.isEmpty(staffName)) { 11380 jheader.html('<b class="display-on-print">' + staffName + '</b> ' + jheader.text()); 11381 } 11382 } 11383 11384 function _loadApprovalType() { 11385 var jtbl = $('#report-timesheet-day'); 11386 var approveType = jtbl.attr('timesheet_type_cd'); 11387 11388 if (approveType == 2 || approveType == 10) { 11389 jtbl.find('.approve_fl').removeClass('hideX'); 11390 } 11391 } 11392 11393 function _loadWeekTable() { 11394 var jtbl = $('#report-timsheet-week'); 11395 GLO.Report.CellSummary.initReport(jtbl, true, true); 11396 } 11397 11398 function _loadDayTable(isInit) { 11399 if (GLO.Info.isMobile()) { 11400 if (isInit) { 11401 $('#header-icon-container').remove(); 11402 } 11403 11404 setTimeout(function() { 11405 var jtbl = $('#report-timesheet-day'); 11406 var tr1 = jtbl.find('#report-timesheet-day-top-header'); 11407 11408 if (!$('body').hasClass('report-full-page')) { 11409 jtbl.find('.column-schedule-3').attr('colspan', '1'); 11410 jtbl.find('.column-actual-3').attr('colspan', '1'); 11411 jtbl.find('.column-update').attr('colspan', '1'); 11412 11413 tr1.addClass('adjust-for-phone'); 11414 } 11415 }, 1200); 11416 } 11417 11418 var jtbl = $('#report-timesheet-day'); 11419 var jbonus = jtbl.find('input.bonus_mn'); 11420 11421 GLO.Report.CellSummary.initReport(jtbl, true, true); 11422 _checkApproveAllStatus(); 11423 _bonusCount = 0; 11424 11425 for (var i=0; i < jbonus.length; i++) { 11426 if (UTIL.coalesceMoney(jbonus.val(), 0) !== 0) { 11427 ++_bonusCount; 11428 } 11429 } 11430 11431 var btnUnApproveAll = $('#report-timesheet-day-save .btnUnApproveAll'); 11432 11433 if (btnUnApproveAll.length > 0) { 11434 jtbl.find('.btnApproveAll').replaceWith(btnUnApproveAll.outerHTML()); 11435 } else { 11436 jtbl.find('.btnApproveAll').removeClass('hide'); 11437 } 11438 } 11439 11440 function _initClockInIcon() { 11441 if (!GLO.Info.isMobile()) { 11442 var jsearch = $('#top-searchBox').addClass('include-clock-out-icon'); 11443 jsearch.after('<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.open(this)" title="Clock In and Out"> <a style="color: rgb(255, 255, 255);"></a> </span>'); 11444 } 11445 } 11446 11447 function _initSFilter() { 11448 var sids = UserPortal.getStaffWhoDoInternalService(); 11449 11450 var sfilter = $('#staff-filter'); 11451 var sfilterOptions = sfilter.find('#staff-filter-s option'); 11452 11453 sfilter.find('#staff-filter-sg').remove(); 11454 sfilter.find('#staff-filter-custom-group option[value!="all"]').remove(); 11455 11456 for (var i=1; i < sfilterOptions.length; i++) { //i=1 --> do NOT remove 'All' 11457 if (!sids.has(sfilterOptions.eq(i).attr('value'))) { 11458 sfilterOptions.eq(i).remove(); 11459 } 11460 } 11461 11462 GLO.Report.initStaffFilter(); 11463 11464 /* 11465 if (GLO.Info.isMobile()) { 11466 var sfilter = GLO.Uri.url('sfilter'); 11467 if (sfilter.indexOf(',') > -1) { sfilter = ''; } 11468 11469 sfilterOptions.parent().prepend('<option value="all">All</option>'); 11470 sfilterOptions.parent().val(sfilter); 11471 } 11472 */ 11473 } 11474 11475 function _initView(j) { 11476 j.find('#timesheet-view-options input:radio').change(GLO.Report.setViewType); 11477 11478 var view = String(GLO.Uri.query('view')).toLowerCase(); 11479 11480 if (view === 'week') { 11481 j.find('#timesheet-weekly').click(); 11482 } else if (view === 'month') { 11483 j.find('#timesheet-monthly').click(); 11484 } else if (view === 'avg-week') { 11485 j.find('#timesheet-avg-week').click(); 11486 } else { // if (view === 'day') {
11487 j.find('#timesheet-daily').click(); 11488 _approveAll(); 11489 } 11490 } 11491 11492 _conRptTimesheet.clickSelectWeek = function(element) { 11493 $('#Week_dt').datepicker('show'); 11494 } 11495 11496 _conRptTimesheet.datePickerOnSelect = function(dateText, inst) { 11497 var jInput = $(inst.input); 11498 var dt = new Date(dateText); 11499 11500 _conRptTimesheet.datePickerOnSelect2(dt); 11501 } 11502 11503 _conRptTimesheet.datePickerOnSelect2 = function(dt) { 11504 var jhead = $('#timesheet-header'); 11505 var jbegin = jhead.find('.Begin_dt'), jend = jhead.find('.End_dt'); 11506 var firstDayOfWeek = jbegin.datepicker('option', 'firstDay'); //= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1) 11507 var dts = _setWeekDateRange(dt, firstDayOfWeek); 11508 11509 jbegin.val(dts.begin_dt.toGloDate(GLO.Info.isMobile())); 11510 jend.val(dts.end_dt.toGloDate(GLO.Info.isMobile())); 11511 11512 GLO.UI.Form.beginProcessing( $('.timesheet-search-week .btnAdd') ); 11513 _conRptTimesheet.search(); 11514 } 11515 11516 _conRptTimesheet.print = function() { 11517 var jrpt = $('table#report-timesheet-day'); 11518 11519 GLO.Report.Template.hideEmptyColumn(jrpt, 'time-column-bonus', true, 'hidePrint'); 11520 GLO.Report.Template.hideEmptyColumn(jrpt, 'total_mn', false, 'hidePrint'); 11521 11522 UI.Print.simplePrint(GLO.Report.Timesheet.printOnComplete); 11523 } 11524 _conRptTimesheet.printOnComplete = function() { 11525 var jrpt = $('table#report-timesheet-day'); 11526 jrpt.find('.hidePrint').removeClass('hidePrint'); 11527 } 11528 11529 function _setWeekDateRange(dt, firstDayOfWeek) { 11530 var dtStart = GLO.Report.firstDayOfWeek(dt, firstDayOfWeek); 11531 var dtEnd = new Date(dtStart).addDays(6); 11532 var dtRange = _conRptTimesheet.getWeekDateRange(dtStart, dtEnd); 11533 11534 $('.timesheet-search-week #week-date-range').text(dtRange); 11535 return { "begin_dt": dtStart, "end_dt": dtEnd }; 11536 } 11537 11538 _conRptTimesheet.getWeekDateRange = function(dt1, dt2) { 11539 if (dt1.getMonth() === dt2.getMonth()) { 11540 var dtRange = dt1.getMonthString(true) + ' ' + dt1.getDate() + ' - ' + dt2.getDate(); 11541 } else { 11542 var dtRange = dt1.getMonthString(true) + ' ' + dt1.getDate() + ' - ' + dt2.getMonthString(true) + ' ' + dt2.getDate(); 11543 } 11544 11545 if (dt2.getFullYear() !== new Date().getFullYear()) { dtRange += ', ' + dt2.getFullYear(); } 11546 return dtRange; 11547 } 11548 11549 function _approveAll() { 11550 var jrpt = $('#report-timesheet-day'); 11551 var boxes = jrpt.find('tbody').find('.approve_fl input[type="checkbox"]'); 11552 var allApproved = true; 11553 11554 for (var i=0; i < boxes.length; i++) { 11555 if (!boxes.eq(i).prop('checked')) { 11556 allApproved = false; 11557 break; 11558 } 11559 } 11560 11561 jrpt.find('#Approve_All').prop('checked', allApproved); 11562 } 11563 11564 _conRptTimesheet.search = function() { 11565 clearTimeout(_timeoutUpdateInProgress); 11566 11567 var jd = {}, fieldset = $('fieldset.appt-list-search'); 11568 var url = GLO.Link.WebsiteDomain + 'report/timesheet?'; 11569 11570 var start = fieldset.find('.Begin_dt').val(); 11571 var end = fieldset.find('.End_dt').val(); 11572 11573 if (!UTIL.isDate(start)) { 11574 GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .Begin_dt'); }); 11575 } else if (!UTIL.isDate(end)) { 11576 GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .End_dt'); }); 11577 } else if (new Date(start) > new Date(end)) { 11578 GLO.Popup.Warning(SA.Resource.BeginDateWarning2); 11579 return; 11580 } else if (!GLO.Report.hasTimesheetAccess(jd)) { 11581 return; 11582 } 11583 11584 var sfilter = GLO.Uri.query('sfilter'); 11585 var vw = fieldset.find('input[name=timesheet-view]:checked').val(); 11586 11587 url += 'sfilter=' + sfilter + '&view=' + vw + '&start=' + start + '&end=' + end; 11588
11589 var svcId = fieldset.find('.Service_Filter').val(); 11590 if (!UTIL.isEmpty(svcId)) { url += '&service=' + svcId; } 11591 11592 try { 11593 window.history.pushState("", "Report Portal", url); 11594 } catch (e) { } 11595 11596 if (this.toString().indexOf('_conRptTimesheet') === -1) { 11597 GLO.UI.Form.beginProcessing( $(this) ); 11598 } 11599 11600 url += '&ispartial=1'; 11601 11602 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jd }) 11603 .success(function(data, textStatus, jqXHR) { 11604 GLO.UI.Form.resetProcessing(); 11605 var jrpt = $('#report-main .report-container'); 11606 11607 if ($(data).hasClass('no-results')) { 11608 var jhead = $('#timesheet-header'); 11609 11610 var dt1 = UTIL.replaceAll(jhead.find('.Begin_dt').val(), '-', '/'); //= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone). 11611 dt1 = new Date(dt1).toGloDateString(true, true, true, true); 11612 11613 var dt2 = UTIL.replaceAll(jhead.find('.End_dt').val(), '-', '/'); //= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone). 11614 dt2 = new Date(dt2).toGloDateString(true, true, true, true); 11615 11616 if (GLO.Info.isMobile()) { 11617 var msg = '<div style="width: 96%; margin: 10px auto; padding-bottom: 20px; line-height: 200%; text-align: center; color: black;">' + SA.Resource.NoResultsFoundForDateRange + '<br/>' + dt1 + ' - ' + dt2 + '</div>'; 11618 } else { 11619 var msg = '<div style="width: 600px; margin: 32px auto; padding-bottom: 16px; color: black; line-height: 1.4;">' + SA.Resource.NoResultsFoundForDateRange + ' ' + dt1 + ' - ' + dt2 + '</div>'; 11620 } 11621 11622 jrpt.html(msg); 11623 _postSearchSetHeader(); 11624 } else { // if (!UTIL.isEmpty(data)) { 11625 jrpt.html(data); 11626 UI.initTableSorter( $('table.tablesorter:visible') ); 11627 11628 if (vw === 'day') { 11629 _approveAll(); 11630 _loadDayTable(false); 11631 } else if (vw === 'week') { 11632 _loadWeekTable(); 11633 } 11634 } 11635 11636 GLO.Report.enableFullPageCheck(); 11637 _postSearchSetHeader(); 11638 }) 11639 .error(function(jqXHR, textStatus, errorThrown) { 11640 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11641 GLO.UI.Form.resetProcessing(); 11642 }); 11643 } 11644 11645 _conRptTimesheet.openMoreHelp = function(header, helpPath) { 11646 var htm = '<div class="reset-list">' + $('#timesheet-report').find(helpPath).html() + '</div>'; 11647 GLO.Popup.Info.open(htm, header); 11648 } 11649 11650 _conRptTimesheet.displayMoreHelp = function(isDisplay) { 11651 var j = $('#report-header-help'); 11652 var jhelp = j.find('.more-help'); 11653 var jmore = j.find('#timesheet-help-display-more'); 11654 var jless = j.find('#timesheet-help-display-less'); 11655 11656 if (isDisplay) { 11657 jhelp.removeClass('hide'); 11658 jmore.addClass('hide'); 11659 jless.removeClass('hide'); 11660 } else { 11661 jhelp.addClass('hide'); 11662 jmore.removeClass('hide'); 11663 jless.addClass('hide'); 11664 } 11665 } 11666 11667 function _saveTimesheetComplete(tr, isApproved, isUnApproved, totalWage, sTimeId) { 11668 _resetRowCSS(tr, isApproved, isUnApproved, totalWage); 11669 11670 if (isApproved == 0) { 11671 totalWage = ''; 11672 } else if (UTIL.coalesceMoney(totalWage) > 0) { 11673 totalWage = '<span title="' + SA.Resource.Saved + '">' + UTIL.displayMoney(totalWage, false, true) + '</span>'; 11674 } else if (isApproved == 1) { 11675 totalWage = '<img src="' + GLO.Data.cdnDirectory + 'image/icon/green-checkbox.png" alt="saved" title="' + SA.Resource.SavedNoHourlyWageSpecified + '" style="height: 25px;"/>'; 11676 } 11677 11678 tr.attr('schedule_timesheet_id', sTimeId); 11679 tr.find('.total_mn').html(totalWage); 11680 11681 _calculateTotalRow(); 11682 _approveAll(); 11683 _checkApproveAllStatus();
11684 } 11685 11686 function _resetRowCSS(tr, isApproved, isUnApproved, totalWage) { 11687 var css = _getRowCSS(tr, isApproved, isUnApproved, totalWage); 11688 11689 tr.removeClass('timecard-un-approved').removeClass('timecard-good').removeClass('timecard-good-no-wage').removeClass('timecard-no-clock-out').removeClass('timecard-future').removeClass('timecard-no-clock-in'); 11690 tr.addClass(css); 11691 11692 var jcheck = tr.find('td.approve_fl').find('input').parent().removeClass('approve-container').removeClass('un-approve-container'); 11693 11694 if (UTIL.parseBool(isApproved)) { 11695 jcheck.addClass('approve-container'); 11696 } else if (UTIL.parseBool(isUnApproved)) { 11697 jcheck.addClass('un-approve-container'); 11698 } 11699 11700 var htmRefresh = '<span class="refresh-icon"><b onclick="GLO.Report.Timesheet.refresh()">↻</b></span>'; 11701 $('#timesheet-summary').find('ul').replaceWith(htmRefresh); 11702 } 11703 11704 function _getRowCSS(tr, isApproved, isUnApproved, totalWage) { 11705 if (isUnApproved) { 11706 return "timecard-un-approved"; 11707 } 11708 11709 var isAutoApproval = ($('#report-timesheet-day').attr('timesheet_type_cd') != 2); 11710 var hasActual = (UTIL.coalesceInt(UTIL.cleanString(tr.find('.clock-actual-hours').text()).replace(' hours', ''), 0) > 0); 11711 var hasSchedule = (UTIL.coalesceInt(UTIL.cleanString(tr.find('td.notify-cell-right.clock-scheduled').text()).replace(' hours', ''), 0) > 0); 11712 11713 if ((hasActual && (isApproved || isAutoApproval)) || (isApproved && hasSchedule)) { 11714 if (totalWage > 0) { 11715 return "timecard-good"; 11716 } else { 11717 return "timecard-good-no-wage"; 11718 } 11719 } 11720 11721 var day = tr.find('.day-column').text(); 11722 var scheduleStart = tr.find('td.notify-cell-left.clock-scheduled').text(); 11723 var clockIn = tr.find('.column-actual-start').text(); 11724 var clockOut = tr.find('.column-actual-end').text(); 11725 11726 var isFutureTimecard = (UTIL.isEmpty(clockIn) && !UTIL.isEmpty(scheduleStart) && new Date(day + ' ' + scheduleStart) > new Date()); 11727 11728 if (!UTIL.isEmpty(clockIn) && UTIL.isEmpty(clockOut)) { 11729 return "timecard-no-clock-out"; 11730 } else if (isFutureTimecard) { 11731 return "timecard-future"; 11732 } else if (UTIL.isEmpty(clockIn)) { 11733 return "timecard-no-clock-in"; 11734 } 11735 } 11736 11737 function _calculateTotalRow() { 11738 var trs = $('#report-timesheet-day tbody tr'); 11739 var bonus = 0, total = 0; 11740 11741 for (var i=0; i < trs.length; i++) { 11742 bonus += UTIL.coalesceMoney(trs.eq(i).find('.bonus_mn').val()); 11743 total += UTIL.coalesceMoney(trs.eq(i).find('.total_mn').text().replace('$', '').replace(' ', '')); 11744 } 11745 11746 bonus = UTIL.displayMoney(bonus, false, true); 11747 total = UTIL.displayMoney(total, false, true); 11748 11749 var tfoot = $('#report-timesheet-day tfoot'); 11750 tfoot.find('#total_bonus_mn').text(bonus); 11751 tfoot.find('.total_mn').text(total); 11752 } 11753 11754 _conRptTimesheet.approve = function(checkbox) { 11755 clearTimeout(_timeoutUpdateInProgress); 11756 checkbox = $(checkbox); 11757 11758 if (checkbox.prop('checked')) { 11759 var updStatus = 20; 11760 var orderBy = '1'; 11761 } else { 11762 var updStatus = 22; 11763 var orderBy = '0'; 11764 } 11765 11766 var tr = checkbox.closest('tr'); 11767 var timesheetId = tr.attr('schedule_timesheet_id'); 11768 var scheduleId = tr.attr('schedule_id'); 11769 var bonus = tr.find('.bonus_mn').val(); 11770 var fnUncheck = function No() { 11771 checkbox.prop('checked', !checkbox.prop('checked')); 11772 }; 11773 11774 if (orderBy == '1' && UTIL.isEmpty(tr.find('.clock-actual-hours').text())) { 11775 if (!UTIL.isEmpty(tr.find('.clock-scheduled').text())) { 11776 var msg = '<div>' + SA.Resource.NoActualHoursExist + '</div>'; 11777 11778 GLO.Popup.Confirm(msg, function Yes() { 11779 _conRptTimesheet.approveConfirmed(tr, timesheetId, scheduleId, bonus, updStatus, orderBy); 11780 }, fnUncheck); 11781 } else { 11782 var msg = 'Please Clock Out ' + tr.find('.staff-column').text(); 11783 fnUncheck(); 11784 GLO.Popup.Warning.open(msg, 'No Hours To Approve'); 11785 } 11786 } else { 11787 GLO.Report.Timesheet.approveConfirmed(tr, timesheetId, scheduleId, bonus, updStatus, orderBy); 11788 } 11789 } 11790 11791 _conRptTimesheet.approveConfirmed = function(tr, timesheetId, scheduleId, bonus, updStatus, isApproved) { 11792 clearTimeout(_timeoutUpdateInProgress); 11793 11794 var url = GLO.Link.WebsiteDomain + 'report/ApproveClockInOut'; 11795 GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') ); 11796
11797 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { schedule_timesheet_id: timesheetId, schedule_id: scheduleId, update_status_cd: updStatus, bonus_mn: bonus } }) 11798 .success(function(data, textStatus, jqXHR) { 11799 GLO.UI.Form.resetProcessing(); 11800 tr.find('.approve_fl').attr('order_by', isApproved); 11801 11802 var totalWage = $(data).attr('total_wage_mn'); 11803 var sTimeId = $(data).attr('schedule_timesheet_id'); 11804 11805 isApproved = UTIL.parseBool(isApproved); 11806 _saveTimesheetComplete(tr, isApproved, !isApproved, totalWage, sTimeId); 11807 11808 $("table.tablesorter:visible").trigger("update"); 11809 }) 11810 .error(function(jqXHR, textStatus, errorThrown) { 11811 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 11812 }); 11813 } 11814 11815 _conRptTimesheet.refresh = function() { 11816 var j = $('#timesheet-report'); 11817 j.find('.btnSearch > a').click(); 11818 GLO.UI.Form.beginProcessing(j.find('.refresh-icon')); 11819 } 11820 11821 _conRptTimesheet.approveAll = function(isApproveAll) { 11822 var cnt = $('#report-timesheet-day').find('tbody > tr').length; 11823 11824 if (isApproveAll) { 11825 var h1 = 'Approve All'; 11826 var bgcolor = 'rgba(20,255,40, .8)'; 11827 } else { 11828 var h1 = 'Un-Approve All'; 11829 var bgcolor = 'rgba(255,20,40, .8)'; 11830 } 11831 11832 var msg = '<div style="margin-top: 12px; font-size: 24px; font-weight: bold; color: black;">' + h1 + ' ' + cnt + ' Timecards?</div>'; 11833 var fn = function() { GLO.Report.Timesheet.approveAllConfirmed(isApproveAll); } 11834 var jpop = GLO.Popup.Confirm.open(msg, h1, fn).getPopup(); 11835 11836 jpop.css({ "background-color": bgcolor }); 11837 jpop.find('.btnNo > a').css({ "padding": "4px 8px", "border": "2px solid black", "border-radius": "20px", "font-weight": "bold", "font-size": "large", "color": "black" }); 11838 } 11839 11840 _conRptTimesheet.approveAllConfirmed = function(isApproveAll) { 11841 clearTimeout(_timeoutUpdateInProgress); 11842 11843 if (isApproveAll) { 11844 var updStatus = 20; 11845 var orderBy = '1'; 11846 var isChecked = true; 11847 } else { 11848 var updStatus = 22; 11849 var orderBy = '0'; 11850 var isChecked = false; 11851 } 11852 11853 var trs = $('#timesheet-report .tablesorter tbody tr'); 11854 var warnCount = 0, errorCount = 0; 11855 11856 if (isChecked) { 11857 for (var i=0; i < trs.length; i++) { 11858 if (UTIL.isEmpty(trs.eq(i).find('.clock-actual-hours').text())) { 11859 if (!UTIL.isEmpty(trs.eq(i).find('.clock-scheduled').text())) { 11860 ++warnCount; 11861 trs.eq(i).addClass('highlightWarning2'); 11862 } else { 11863 ++errorCount; 11864 trs.eq(i).addClass('highlightWarningRed'); 11865 } 11866 } 11867 } 11868 } 11869 11870 if (errorCount > 0) { 11871 var msg = 'Cannot Approve All Timecards because ' + UTIL.pluralLabel(errorCount, 'timecard') + ' has No Scheduled or Actual hours'; 11872 GLO.Popup.Error.open(msg, 'Approve Cancelled'); 11873 11874 //$('#timesheet-report .tablesorter tbody tr.highlightWarning2').removeClass('highlightWarning2'); 11875 return; 11876 } else { 11877 //$('#timesheet-report .tablesorter tbody tr.highlightWarningRed').removeClass('highlightWarningRed'); 11878 } 11879 11880 for (var i=0; i < trs.length; i++) { 11881 trs.eq(i).find(':checkbox').prop('checked', isChecked).parent().attr('order_by', orderBy); 11882 } 11883 11884 if (warnCount > 0) { 11885 if (warnCount === 1) { 11886 var msg = '<div>' + SA.Resource.ApproveScheduleHoursQuestion2 + '</div>'; 11887 } else { 11888 var msg = '<div>' + SA.Resource.NoActualHoursExistFor + ' ' + warnCount + ' ' + SA.Resource.Rows.toLowerCase() + '. ' + SA.Resource.ApproveScheduleHoursQuestion + '?</div>'; 11889 } 11890 11891 GLO.Popup.Confirm(msg, function Yes() { 11892 $('#timesheet-report .tablesorter tr.highlightWarning2').removeClass('highlightWarning2'); 11893 $("table.tablesorter:visible").trigger("update"); 11894 11895 GLO.Report.Timesheet.save(true); 11896 }, function No() { 11897 var jrpt = $('#timesheet-report'); 11898 var trs = jrpt.find('.tablesorter tr.highlightWarning2'); 11899 11900 for (var i=0; i < trs.length; i++) { 11901 trs.eq(i).removeClass('highlightWarning2') 11902 trs.eq(i).find(':checkbox').prop('checked', false); 11903 } 11904 11905 jrpt.find("table.tablesorter:visible").trigger("update"); 11906 _conRptTimesheet.save(true); 11907 }); 11908 } else { 11909 $("table.tablesorter:visible").trigger("update"); 11910 _conRptTimesheet.save(true); 11911 } 11912 } 11913 11914 _conRptTimesheet.updateInProgress = function(element, event) { 11915 var jinput = $(element); 11916 11917 if (UTIL.coalesceMoney(element.value, 0) === UTIL.coalesceMoney(jinput.attr('startvalue'), 0)) { 11918 if (jinput.hasClass('unsaved-change')) { 11919 jinput.removeClass('unsaved-change'); 11920 clearTimeout(_timeoutUpdateInProgress); 11921 } 11922 11923 return; 11924 } 11925 11926 clearTimeout(_timeoutUpdateInProgress); 11927 _timeoutUpdateInProgress = setTimeout(GLO.Report.Timesheet.saveStart, 4800); 11928 11929 var jrpt = $('#timesheet-report'); 11930 jrpt.find('.btnApproveAll').addClass('hide'); 11931 jrpt.find('.btnSaveBonus').removeClass('hide'); 11932 11933 jinput.addClass('unsaved-change'); 11934 } 11935 11936 function _checkApproveAllStatus() { 11937 var jrpt = $('#timesheet-report'); 11938 11939 if (jrpt.find('#Approve_All').prop('checked')) { 11940 jrpt.find('.btnApproveAll').addClass('btnUnApprove').find('a').text('Un-Approve All'); 11941 } else { 11942 jrpt.find('.btnApproveAll').removeClass('btnUnApprove').find('a').text('Approve All'); 11943 } 11944 } 11945 11946 _conRptTimesheet.saveStart = function(isApproveAll) { 11947 clearTimeout(_timeoutUpdateInProgress); 11948 11949 if ($('.glopop').length > 0) { return; } 11950 11951 if (isApproveAll) {
11952 $('#timesheet-report #Approve_All').click(); 11953 } else { 11954 var bonusChangeCount = $('#timesheet-report').find('.bonus_mn.unsaved-change').length; 11955 11956 if (bonusChangeCount === 0) { 11957 if (_bonusCount === 0) { 11958 return; 11959 } else if (_bonusCount === 1) { 11960 var msg = 'Remove Bonus?'; 11961 } else { 11962 var msg = 'Remove Bonuses?'; 11963 } 11964 } else if (bonusChangeCount === 1) { 11965 var msg = 'Do you want to Save Bonus?'; 11966 } else { 11967 var msg = 'Do you want to Save Bonuses?'; 11968 } 11969 11970 GLO.Popup.Confirm.open(msg, 'Save Bonus?', GLO.Report.Timesheet.save); 11971 } 11972 } 11973 11974 _conRptTimesheet.save = function() { 11975 clearTimeout(_timeoutUpdateInProgress); 11976 11977 var tbl = $('#timesheet-report .tablesorter tbody'); 11978 var trs = tbl.find('tr'); 11979 var sTimeId, bonus, updStatus, xml = ''; 11980 11981 for (var i=0; i < trs.length; i++) { 11982 scheduleId = trs.eq(i).attr('schedule_id'); 11983 sTimeId = trs.eq(i).attr('schedule_timesheet_id'); 11984 bonus = trs.eq(i).find('.bonus_mn').val(); 11985 11986 if (trs.eq(i).find(':checkbox').prop('checked')) { 11987 updStatus = 20; 11988 } else { 11989 updStatus = 22; 11990 } 11991 11992 xml += "<li schedule_id='" + scheduleId + "' schedule_timesheet_id='" + sTimeId + "' update_status_cd='" + updStatus + "' bonus_mn='" + bonus + "'/>"; 11993 } 11994 11995 xml = UTIL.htmlEncode("<ul>" + xml + "</ul>"); 11996 var url = GLO.Link.WebsiteDomain + 'report/SaveTimesheet'; 11997 GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') ); 11998 11999 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "timesheet_xml": xml } }) 12000 .success(function(data, textStatus, jqXHR) { 12001 GLO.UI.Form.resetProcessing(); 12002 var tr, isApproved, totalWage, sTimeId; 12003 var list = $(data).find('li'); 12004 12005 for (var i=0; i < list.length; i++) { 12006 tr = tbl.find('tr[schedule_id="' + list.eq(i).attr('schedule_id') + '"]'); 12007 isApproved = list.eq(i).attr('approved_fl'); 12008 totalWage = list.eq(i).attr('total_wage_mn'); 12009 sTimeId = list.eq(i).attr('schedule_timesheet_id'); 12010 12011 _saveTimesheetComplete(tr, isApproved, null, totalWage, sTimeId); 12012 12013 var jTimeHeader = $('#timesheet-header'); 12014 var jDailySearch = jTimeHeader.find('#report-header-search:visible'); 12015 12016 if (jDailySearch.length > 0) { 12017 jDailySearch.click(); 12018 } else { 12019 //could lookup date in range + call _conRptTimesheet.datePickerOnSelect2(dt), but don't really need to because update button only on daily timesheet. 12020 } 12021 } 12022 }) 12023 .error(function(jqXHR, textStatus, errorThrown) { 12024 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 12025 }); 12026 } 12027 12028 _conRptTimesheet.openApproveSetting = function() { 12029 var htm1 = '<h4>Change how timecards are approved</h4>' + '<p style="text-align: center;">When a timecard is approved it is included in the payroll report</p>'; 12030 var l1 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="1"/>Timecards automatically approved when clocked out</label> </li>'; 12031 var l2 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="10"/>Timecards automatically approved when clocked-out; can also un-approve timecards after clock-out or approve scheduled timecards (even if no actual hours, no clock-in/out)</label> </li>'; 12032 var l3 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="2"/>Timecards must be approved by manage or admin</label> </li>'; 12033 12034 var ul = '<ul class="reset-list" style="margin: 0;">' + l1 + l2 + l3 + '</ul>' 12035 var htm = '<div id="pop-timecard-approve-setting">' + htm1 + ul + '</div>'; 12036 var jpop = GLO.Popup.Custom.openSimple(htm, 'Change Approval Setting', GLO.Report.Timesheet.saveApproveSetting); 12037
12038 var tt = $('#report-timesheet-day').attr('timesheet_type_cd'); 12039 12040 jpop.find('ul input[value="' + tt + '"]').prop('checked', true).closest('label').css({ "font-weight": "bold" }).closest('li').css({ "background-color": "rgba(20,255,80, .4)" }); 12041 } 12042 12043 _conRptTimesheet.saveApproveSetting = function() { 12044 var jpop = $('#pop-timecard-approve-setting').closest('.glopop'); 12045 var value = jpop.find('input[name="Timesheet_Type_cd"]:checked').val(); 12046 12047 var url = GLO.Link.WebsiteDomain + 'report/SaveTimesheetSetting'; 12048 //GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') ); 12049 12050 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "approve": value } }) 12051 .success(function(data, textStatus, jqXHR) { 12052 GLO.Popup.close(jpop); 12053 $('#timesheet-header .timesheet-search-day .btnSearch > a').click(); 12054 12055 var msg = '<div>Re-loading Timesheet with new approval setting...</div>'; 12056 var ojProcessing = GLO.Popup.Processing.open(msg, 'Timesheet Approve Setting Saved'); 12057 12058 setTimeout(function() { 12059 ojProcessing.close(); 12060 }, 3200); 12061 }) 12062 .error(function(jqXHR, textStatus, errorThrown) { 12063 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 12064 }); 12065 } 12066 12067 return _conRptTimesheet; 12068})(); 12069 12070 12071GLO.Report.Totalsales = (function() { 12072 function _conRptTotalsales() { } 12073 12074 _conRptTotalsales.init = function() { 12075 //$('#report-header-search').click(GLO.Report.Totalsales.search); 12076 } 12077 12078 _conRptTotalsales.search = function() { 12079 var fieldset = $('fieldset.appt-list-search'); 12080 var url = GLO.Link.WebsiteDomain + 'report/totalsales?'; 12081 var start = fieldset.find('.Begin_dt').val(); 12082 var end = fieldset.find('.End_dt').val(); 12083 12084 if (!UTIL.isDate(start)) { 12085 GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .Begin_dt'); }); 12086 } else if (!UTIL.isDate(end)) { 12087 GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .End_dt'); }); 12088 } else if (new Date(start) > new Date(end)) { 12089 GLO.Popup.Warning(SA.Resource.BeginDateWarning2); 12090 return; 12091 } 12092 12093 /* 12094 if (GLO.Report.staffFilter !== null) { 12095 var sfilter = GLO.Report.staffFilter; 12096 GLO.Report.staffFilter = null; 12097 } else { 12098 var sfilter = GLO.Uri.query('sfilter'); 12099 } 12100 */ 12101 12102 var sfilter = GLO.Uri.query('sfilter'); 12103 url += 'sfilter=' + sfilter; 12104 //url += '&view=' + fieldset.find('input[name=timesheet-view]:checked').val(); 12105 url += '&start=' + start; 12106 url += '&end=' + end; 12107 12108 var svcId = fieldset.find('#Service_Filter').val(); 12109 if (!UTIL.isEmpty(svcId)) { url += '&service=' + svcId; } 12110 12111 try { 12112 window.history.pushState("", "Report Portal", url); 12113 } catch (e) { } 12114 12115 var jBtn = $(this).parent(); 12116 GLO.UI.Form.beginProcessing(jBtn); 12117 url += '&ispartial=1'; 12118 12119 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 12120 .success(function(data, textStatus, jqXHR) { 12121 GLO.UI.Form.resetProcessing(); 12122 if (!UTIL.isEmpty(data)) { 12123 $('#report-main').html(data); 12124 UI.initTableSorter( $('table.tablesorter:visible') ); 12125 } else { 12126 GLO.Popup.Info(SA.Resource.NoResultsFound); 12127 } 12128 }) 12129 .error(function(jqXHR, textStatus, errorThrown) { 12130 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 12131 GLO.UI.Form.resetProcessing(); 12132 }); 12133 } 12134 12135 return _conRptTotalsales; 12136})(); 12137 12138 12139GLO.Report.Cash = (function() { 12140 function _conRptCash() { } 12141 12142 _conRptCash.init = function() { 12143 GLO.Info.init(); 12144 12145 var jtbl = $('table.tablesorter:visible'); 12146 UI.initTableSorter(jtbl); 12147 12148 $('#report-cash-history').find('.ui-icon-circle-close').click(GLO.Report.Cash.deleteRow); 12149 12150 GLO.Report.enableFullPageCheck(); 12151 GLO.Report.CellSummary.initReport(jtbl, true); 12152 GLO.Report.initIcons(jtbl); 12153 _initUrlCashReport(); 12154 $('#doc3').addClass('is-payment-report'); 12155 } 12156 function _initUrlCashReport() { 12157 var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase(); 12158 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 12159 var jreport = $('#report-cash-history'); 12160 12161 if (popup === 'new') { 12162 GLO.Report.Cash.newEvent() 12163 } else if (popup === 'change' || popup === 'set-level') { 12164 jreport.find('#cash-level').click(); 12165 } else if (popup === 'house-only-help') { 12166 GLO.Report.Cash.helpHouseOnly(); 12167 } else if (popup === 'open') { 12168 GLO.Report.Cash.openDrawerSetting(); 12169 } else if (popup === 'printer' || popup === 'printer-utility') { 12170 GLO.Report.Cash.openHelpPrinterSelect(); 12171 } 12172 12173 if (!UTIL.isEmpty(highlight)) { 12174 var jhighlight = jreport.find('#' + highlight + ', .' + highlight); 12175 12176 if (jhighlight.length > 0) { 12177 UI.highlight(jhighlight, 800, 6400, true); 12178 } 12179 } 12180 } 12181 12182 _conRptCash.changeCashDrawerSetting = function (event) { 12183 var cashDrawerSettingCode = $(event.target).val(); 12184 if (cashDrawerSettingCode == '5') { 12185 GLO.Report.Cash.displayLocalPrinters(); 12186 } 12187 else { 12188 $('#local-printer-selection-container').addClass('hide'); 12189 12190 } 12191 } 12192 12193 _conRptCash.search = function() { 12194 var jrpt = $('#report-cash-history'); 12195 var rows = jrpt.find('#Rows_sr').val(); 12196 12197 var url = GLO.Link.WebsiteDomain + 'report/cash?search=1&rows=' + rows; 12198 var jbtn = jrpt.find('.btnSearch'); 12199 var jd = {}; 12200 12201 if (!GLO.Report.hasReportPassword(jd)) { 12202 return; 12203 } 12204 12205 GLO.UI.Form.beginProcessing(jbtn); 12206
12207 var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd }) 12208 .success(function(data, textStatus, jqXHR) { 12209 GLO.UI.Form.resetProcessing(); 12210 12211 if (!UTIL.isEmpty(data)) { 12212 var cash = UTIL.displayMoney($(data).attr('drawer_amount_mn'), false, false, true); 12213 var jrpt = $('#report-cash-history'); 12214 12215 jrpt.find('#cash-level').text(cash); 12216 jrpt.find('.report-container').html(data); 12217 12218 GLO.Report.Cash.init(); //UI.initTableSorter( jrpt.find('table.tablesorter:visible') ); 12219 } else { 12220 GLO.Popup.Info(SA.Resource.NoResultsFound); 12221 } 12222 }) 12223 .error(function(jqXHR, textStatus, errorThrown) { 12224 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 12225 GLO.UI.Form.resetProcessing(); 12226 }); 12227 } 12228 12229 _conRptCash.openDrawerSetting = function() { 12230 var cd = $('#advanced-setting-open-cash-drawer').attr('cash_drawer_setting_cd'); 12231 var htm = '<div id="pop-advanced-setting-cash-drawer">' 12232 + '<label for="Cash_Drawer_Setting_cd" class="hide">Open Cash Drawer</label>' 12233 + '<select id="Cash_Drawer_Setting_cd" name="Cash_Drawer_Setting_cd" style="width: 90%; max-width: 480px; margin: 12px auto; letter-spacing: 1px;" onChange="GLO.Report.Cash.changeCashDrawerSetting(event)">' 12234 + '<option value="0">Never Open</option>' 12235 + '<option value="1">When Print Receipt</option>' 12236 + '<option value="2">Display Open Cash Drawer Button at Top of Calendar</option>' 12237 + '<option value="3">Display Open Cash Drawer Button + Require PIN</option>' 12238 + '<option value="4">Display Open Cash Drawer Button + Require PIN | Print Receipt on Cash Payment</option>' 12239 + '<option value="5">Display Open Cash Drawer Button + Select Receipt Printer</option>' 12240 + '</select>' 12241 + '<div id="local-printer-selection-container" class="hide">' 12242 + '</div>' 12243 + '<div id="cash-drawer-setting-info">' 12244 + '<p style="text-align: center;">Requires connecting Cash Drawer to Printer</p>' 12245 + '<p><b>Windows/Mac</b> connect your cash drawer to your receipt printer <small>(most receipt printers + cash drawers are compatible)</small></p>' 12246 + '<p><b>iPad</b> Connect your Star printer to your Star cash drawer <small>(or a cash drawer that supports the Star emulation)</small></p>' 12247 + '</div>' 12248 + '</div>'; 12249 12250 if ($('#pop-advanced-setting-cash-drawer').closest('.glopop').length) { return; } 12251 12252 var jpop = GLO.Popup.Custom.openSimple(htm, 'Open Cash Drawer Setting', GLO.Report.Cash.saveDrawerSetting); 12253 //GLO.Popup.Custom.singleButton(jpop, 'Close'); 12254 jpop.find('.pop-buttons').css({ "max-width": "560px" }); 12255 jpop.find('#Cash_Drawer_Setting_cd').val(cd); 12256 //load local printers if setting is open cash drawer + select printer setting 12257 if (cd == '5') { 12258 GLO.Report.Cash.displayLocalPrinters(); 12259 } 12260 else { 12261 $('#local-printer-selection-container').addClass('hide'); 12262 12263 } 12264 } 12265 _conRptCash.saveDrawerSetting = function() { 12266 var jpop = $('#pop-advanced-setting-cash-drawer').closest('.glopop'); 12267 var jcd = jpop.find('#Cash_Drawer_Setting_cd'); 12268 var htmSaveSuccess = 'Open Cash Drawer: ' + jcd.find(':selected').text(); 12269 12270 GLO.Provider.Advanced.saveField(jcd[0], event, htmSaveSuccess); 12271 if (jcd.val() == '5') { 12272 var selectedPrinterName = $('#printerSelect').val(); 12273 UTIL.setCookie('_sa_receiptprinter', selectedPrinterName); 12274 } 12275 else { 12276 document.cookie = '_sa_receiptprinter=; Max-Age=0; path=/; domain=' + location.host; 12277 } 12278 GLO.Popup.close(jpop); 12279 $('#advanced-setting-open-cash-drawer').attr('cash_drawer_setting_cd', jcd.val()); 12280 } 12281 12282 function _getEventPopup(header, cashid, smid, cash, note, includeNote, saveFunction) { 12283 var numberInputType = "text"; 12284 if (GLO.Info.isAndroid) { numberInputType = "number"; } 12285 12286 var htm = '<div>'; 12287 htm += '<div style="width: 200px; margin: 20px auto;"> <label for="Event_Amount_mn">' + SA.Resource.Amount + '</label>' 12288 + '$<input id="Event_Amount_mn" type="' + numberInputType + '" maxlength="9" onkeypress="UI.numberOnly(event, true, false)" value="' + UTIL.cleanString(cash) + '"/>' 12289 + '</div>'; 12290 12291 if (UTIL.isNumber(cash, true) || note || includeNote) { 12292 var textareaNote = '<textarea id="Event_Note_vc" placeholder="' + SA.Resource.AddRemoveCashReason + '" maxlength="500">' + UTIL.cleanString(note) + '</textarea>'; 12293 htm += '<div id="cash-event-note">' + textareaNote + '</div>'; // <label for="Event_Note_vc">Note</label> 12294 } 12295 12296 htm += '</div>'; 12297 htm = $('<div id="cash-event-popup" cash_id="' + UTIL.cleanString(cashid) + '" schedule_multi_id="' + UTIL.cleanString(smid) + '">' + header + htm + '</div>'); 12298 12299 smid = UTIL.coalesce(smid, 'null'); 12300 12301 var oj = new GLO.Popup.Custom(htm, saveFunction); 12302 var jpop = oj.getPopup().addClass('no-persist').attr('id', 'pop-add-remove-cash'); 12303 12304 if (!UTIL.isEmpty(cashid)) { 12305 jpop.find('textarea').css({ "width": "350px", "margin-left": "20px" }); 12306 12307 var jbtn = jpop.find('.pop-buttons'); 12308 jbtn.find('.btnSave').css({ "margin-left": "40px" }); 12309 jbtn.append('<span class="btnDelete" style="float: right; width: 100px; font-size: 85%;"> <a onclick="GLO.Report.Cash.deleteEvent(' + cashid + ', ' + smid + ')">' + SA.Resource.Delete + '</a> </span>'); 12310 } else if (!GLO.Info.isMobile()) { 12311 var jbtn = jpop.find('.pop-buttons').addClass('pop-buttons2'); //.css({ "width": "300px" }); 12312 jbtn.append('<span class="btnRemoveCash btnAdd btn">
12312<a onclick="GLO.Report.Cash.removeCash()">Remove Cash</a></span>'); 12313 12314 jbtn.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "margin": "0" }).find('> a').css({ "letter-spacing": "1px" }); //"margin-left": "25px" 12315 jbtn.find('.btnSave').addClass('btnAddCash').find('> a').text('Add Cash'); //"margin-left": "50px" 12316 } 12317 12318 jpop.find('h1').css({ "letter-spacing": "1px" }); 12319 //UI.initAutoComplete(jpop.find('#Event_Amount_mn'), GLO.Report.Cash.saveEvent); 12320 return jpop; 12321 } 12322 12323 _conRptCash.removeCash = function() { 12324 var jpop = $('#cash-event-popup').closest('.glopop'); 12325 var cash = UTIL.coalesceMoney(jpop.find('#Event_Amount_mn').val()); 12326 12327 if (cash > 0) { 12328 jpop.find('#Event_Amount_mn').val('-' + cash); 12329 } 12330 12331 jpop.find('.btnSave > a').click(); 12332 } 12333 12334 _conRptCash.setLevel = function(element) { 12335 var header = '<h1 class="change-cash-level">' + SA.Resource.ChangeCashLevel + '</h1>'; 12336 var cash = UTIL.displayMoney($(element).text().replace('$', ''), true); 12337 var jpop = _getEventPopup(header, null, null, cash, null, false, GLO.Report.Cash.save); 12338 } 12339 12340 _conRptCash.newEvent = function() { 12341 var header = '<h1 class="new-event">' + SA.Resource.AddRemoveCash + '</h1>'; 12342 var jpop = _getEventPopup(header, null, '', null, '', true, GLO.Report.Cash.saveEvent); 12343 } 12344 12345 _conRptCash.openEvent = function(element, cashid, smid) { 12346 var tr = $(element).closest('tr'); 12347 var cash = tr.find('.payment').text().replace('$', ''); 12348 var note = tr.find('.payment-note').text(); 12349 12350 var header = '<h1 class="edit-cash-event">' + SA.Resource.EditCashTransaction + '</h1>'; 12351 var jpop = _getEventPopup(header, cashid, smid, cash, note, true, GLO.Report.Cash.saveEvent); 12352 } 12353 12354 _conRptCash.deleteEvent = function(cashid, smid, label) { 12355 var label = UTIL.coalesceString(label, SA.Resource.DeleteCashTransactionConfirm); 12356 var css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;'; 12357 var pcss = 'letter-spacing: 1px; line-height: 1.8; font-size: larger; font-weight: bold; color: Red;'; 12358 12359 var htm = '<form cash_id="' + UTIL.cleanString(cashid) + '" schedule_multi_id="' + UTIL.cleanString(smid) + '"><p style="' + pcss + '">' + label + '</p>' 12360 + '<textarea id="Delete_Reason_vc" name="Delete_Reason_vc" class="defaultText" maxlength="2000" rows="2" title="' + SA.Resource.IncludeNoteHelp + '" style="' + css + '"> </textarea>' 12361 + '</form>'; 12362 12363 GLO.Popup.Confirm('<div id="cash-event-popup">' + htm + '</div>', GLO.Report.Cash.deleteEventConfirmed); 12364 } 12365 12366 _conRptCash.deleteRow = function() { 12367 var icon = $(this); 12368 var label = icon.attr('title'); 12369 var tr = icon.closest('tr'); 12370 var cashId = tr.attr('cash_id'), smid = tr.attr('schedule_multi_id'); 12371 var jPayDate = tr.find('.rpt-cash-pay-date'), jPayAmount = tr.find('.payment'); 12372 12373 if (jPayDate.length > 0 && jPayAmount.length > 0) { 12374 if (jPayDate.find('a').length > 0) { jPayDate = jPayDate.find('a'); } 12375 12376 label += '<div style="margin-top: 12px; text-align: center;"> <b style="padding-right: 4px;">' + jPayDate.text() + '</b> <b>' + jPayAmount.text() + '</b></div>'; 12377 } 12378 12379 _conRptCash.deleteEvent(cashId, smid, label); 12380 } 12381 12382 _conRptCash.deleteEventConfirmed = function(jform) { 12383 var url = GLO.Link.WebsiteDomain + 'report/CashDeleteEvent'; 12384 var cashid = jform.attr('cash_id'); 12385 var smid = jform.attr('schedule_multi_id'); 12386 var reason = UTIL.htmlEncode(jform.find('#Delete_Reason_vc').val()); 12387 var jd = { "cash_id": cashid, "schedule_multi_id": smid, "delete_reason_vc": reason }; 12388 12389 if (!GLO.Report.hasReportPassword(jd)) { 12390 return false; 12391 } 12392 12393 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 12394 .success(function(data, textStatus, jqXHR) { 12395 if (GLO.Report.hasReportPasswordWarning(data)) { 12396 return false; 12397 } 12398 12399 var cash = $('#cash-event-popup #Event_Amount_mn').val(); 12400 UserPortal.Price.Receipt.openCashDrawer(cash, ' (delete)'); 12401 12402 GLO.Report.Cash.search(); 12403 GLO.Popup.close(); 12404 new GLO.Popup.Success(SA.Resource.CashTransactionSuccessfullyDeleted); 12405 }) 12406 .error(function(jqXHR, textStatus, errorThrown) { 12407 new GLO.Popup.Error('Unable to delete. Please try again'); 12408 }); 12409 } 12410 12411 _conRptCash.saveEvent = function() { 12412 var jpop = $('#cash-event-popup').closest('.glopop'); 12413 var url = GLO.Link.WebsiteDomain + 'report/CashEditEvent'; 12414 12415 var cashid = jpop.find('#cash-event-popup').attr('cash_id'); 12416 var smid = jpop.find('#cash-event-popup').attr('schedule_multi_id'); 12417 var note = UTIL.htmlEncode(UTIL.cleanString(jpop.find('#Event_Note_vc').val())); 12418 var cash = String(jpop.find('#Event_Amount_mn').val()).replace(',', ''); 12419 12420 if (cash.indexOf('(') !== -1 && cash.indexOf(')') !== -1) { 12421 cash = '-' + cash.replace('(', '').replace(')', ''); 12422 } 12423 12424 var jd = { "payment_mn": cash, "payment_note_vc": note, "schedule_multi_id": smid, "cash_id": cashid }; 12425 12426 if (!UTIL.isNumber(cash, true)) { 12427 if (cash.indexOf('(') > -1 && (cash.indexOf(')') + 1) === cash.length) { //= user entered parentheses to indicate negative number. 12428 cash = cash.replace('(', '').replace(')', ''); 12429 12430 if (UTIL.coalesceMoney(cash) > 0) { cash = -cash; } 12431 } 12432 12433 if (!UTIL.isNumber(cash, true)) { 12434 var style = 'style="margin-bottom: 0; padding-top: 6px; letter-spacing: 2px;"'; 12435 var msg = '<div> <h1 ' + style + '>Invalid Amount</h1> <div ' + style + '>Cash Amount Must Be A Number</div></div>'; 12436 new GLO.Popup.Warning(msg, function() { $('#cash-event-popup #Event_Amount_mn').focus(); }); 12437 return; 12438 } 12439 } 12440 12441 if (!GLO.Report.hasReportPassword(jd)) { 12442 return; 12443 } 12444 12445 var jsave = jpop.find('.btnSave'); 12446 GLO.UI.Form.beginProcessing(jsave); 12447
12448 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 12449 .success(function(data, textStatus, jqXHR) { 12450 if (GLO.Report.hasReportPasswordWarning(data)) { 12451 return; 12452 } 12453 12454 UserPortal.Price.Receipt.openCashDrawer(cash); 12455 12456 GLO.Report.Cash.search(); 12457 GLO.Popup.close(); 12458 new GLO.Popup.Success(SA.Resource.CashTransactionSuccessfullySaved); 12459 }) 12460 .error(function(jqXHR, textStatus, errorThrown) { 12461 GLO.UI.Form.resetProcessing(); 12462 new GLO.Popup.Error('Unable to save. Please try again'); 12463 }); 12464 } 12465 12466 _conRptCash.save = function() { 12467 var jpop = $('#cash-event-popup').closest('.glopop'); 12468 var url = GLO.Link.WebsiteDomain + 'report/CashSave'; 12469 var note = UTIL.htmlEncode(UTIL.cleanString(jpop.find('#Event_Note_vc').val())); 12470 12471 var newCashLevel = jpop.find('#Event_Amount_mn').val(); 12472 12473 if (newCashLevel.indexOf('(') !== -1 && newCashLevel.indexOf(')') !== -1) { 12474 newCashLevel = '-' + newCashLevel.replace('(', '').replace(')', ''); 12475 } 12476 12477 newCashLevel = UTIL.coalesceMoney(newCashLevel.replace(',', ''), 0); 12478 12479 var currentCashLevel = UTIL.coalesceMoney($('#report-cash-header #cash-level').text().replace('$', ''), 0); 12480 var cash = UTIL.coalesceMoney(newCashLevel - currentCashLevel); 12481 12482 var jd = { "cash_mn": cash, "update_note_vc": note }; 12483 12484 if (!GLO.Report.hasReportPassword(jd)) { 12485 return; 12486 } 12487 12488 if (jpop.find('#drawer-config').length === 1) { 12489 jd.all_product_fl = jpop.find('#all_product_fl').prop('checked'); 12490 jd.all_service_fl= jpop.find('#all_service_fl').prop('checked'); 12491 jd.all_tip_fl = jpop.find('#all_tip_fl').prop('checked'); 12492 } 12493 12494 var jsave = jpop.find('.btnSave'); 12495 GLO.UI.Form.beginProcessing(jsave); 12496 12497 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 12498 .success(function(data, textStatus, jqXHR) { 12499 UserPortal.Price.Receipt.openCashDrawer(cash, ' (' + SA.Resource.Update.toLowerCase() + ')'); 12500 12501 GLO.Popup.close(); 12502 GLO.Report.Cash.search(); 12503 new GLO.Popup.Success(SA.Resource.CashLevelSuccessfullyChanged); 12504 }) 12505 .error(function(jqXHR, textStatus, errorThrown) { 12506 GLO.UI.Form.resetProcessing(); 12507 new GLO.Popup.Error('Unable to change the cash level at this time. Please try again'); 12508 }); 12509 } 12510 12511 function _getHouseOnlyInfo(useHeader) { 12512 var msg1 = 'When Enabled: Only cash payments for products and staff using your house merchant account are included in the cash drawer'; 12513 var msg2 = 'This feature is useful if only some of your staff use the house account and some are independent contractors who collect payment independently'; 12514 var htm = '<p>' + msg1 + '</p> <p style="letter-spacing: 0; line-height: 1.4; font-size: smaller;">' + msg2 + '</p>'; 12515 12516 if (useHeader) { 12517 htm = '<h3>House Only Cash Drawer</h3>' + htm; 12518 } 12519 12520 return htm; 12521 } 12522 _conRptCash.helpHouseOnly = function() { 12523 var htm = _getHouseOnlyInfo(false); 12524 GLO.Popup.Info.open(htm, 'House Only Cash Drawer'); 12525 } 12526 _conRptCash.changeHouseOnly = function() { 12527 var jHouseOnly = $('#advanced-payment-cash-house-only #Cash_House_Only_fl'); 12528 var isHouseOnly = jHouseOnly.prop('checked'); 12529 var url = GLO.Link.WebsiteDomain + 'provider/manage/CashHouseOnly?ishouse=' + isHouseOnly; 12530 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 12531 12532 if (mt > 79) { 12533 var msg1 = '<p style="line-height: 1.2; padding-bottom: 0; font-weight: bold; color: red;">Merchant Account Required for this feature</p>'; 12534 var msg2 = '<p style="padding-left: 2px; line-height: 1.4; font-size: smaller;">
12534This is how ' + GLO.Info.getScheduleAnyoneHtm() + ' knows which staff are using the house account</p>'; 12535 12536 var msg3 = '<p>' + _getHouseOnlyInfo(true) + '</p>'; 12537 var htm = msg1 + msg2 + msg3; 12538 12539 GLO.Popup.Warning.open(htm, 'House Only Cash Drawer'); 12540 12541 jHouseOnly.prop('checked', false); 12542 return; 12543 } else if (mt < 10 && isHouseOnly) { 12544 var msg1 = '<p style="margin-top: 12px; padding-bottom: 0; line-height: 1.2; font-weight: bold; color: red;">Enabling Multi-Merchant Required for this feature</p>'; 12545 var msg2 = '<p style="padding-left: 2px; letter-spacing: 0; line-height: 1.4;">This is how ' + GLO.Info.getScheduleAnyoneHtm() + ' knows which staff are using the house account</p>'; 12546 12547 var msg3 = '<p>' + _getHouseOnlyInfo(true) + '</p>'; 12548 var msg4 = '<p style="margin-top: 24px; padding-bottom: 0; line-height: 1; font-size: larger; font-weight: bold; color: green;">Would you like us to enable multi-merchant?</p>'; 12549 var msg5 = '<p style="letter-spacing: 0; line-height: 1.4; font-size: smaller; color: green;">This is free, after we enable you just must set which staff use the house account</p>'; 12550 var htm = msg1 + msg2 + msg3 + msg4 + msg5; 12551 12552 var jpop = GLO.Popup.Confirm.open(htm, 'House Only Cash Drawer', GLO.Report.Cash.enableMultiMerchant).getPopup(); 12553 jpop.find('.btnYes').find('>a').text('Yes, Enable Multi-Merchant'); 12554 12555 jHouseOnly.prop('checked', false); 12556 return; 12557 } 12558 12559 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 12560 .success(function(data, textStatus, jqXHR) { 12561 GLO.Popup.Success.open('House Account Only changed to: ' + isHouseOnly, 'House Only Cash Drawer'); 12562 }) 12563 .error(function(jqXHR, textStatus, errorThrown) { }); 12564 } 12565 _conRptCash.enableMultiMerchant = function() { 12566 var url = GLO.Link.WebsiteDomain + 'provider/manage/CashHouseOnly?ishouse=1'; 12567 $('#advanced-payment-cash-house-only #Cash_House_Only_fl').prop('checked', true); 12568 12569 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 12570 .success(function(data, textStatus, jqXHR) { 12571 var msg1 = '<p>House Account Only changed to: true</p>'; 12572 var msg2 = '<p style="color: green;">We will contact you to confirm as soon as Multi-Merchant is Enabled</p>'; 12573 12574 GLO.Popup.Success.open(msg1 + msg2, 'House Only Cash Drawer'); 12575 }) 12576 .error(function(jqXHR, textStatus, errorThrown) { }); 12577 } 12578 12579 _conRptCash.openHelpPrinterSelect = function() { 12580 var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;'; 12581 var title = '<p style="' + css1 + '">Setup Cash drawer to open only when <b class="narrow-text">Open Cash Drawer</b> button is clicked or <b class="narrow-text">Cash</b> payment method is selected on a ticket</p>'; 12582 var sa = GLO.Info.getScheduleAnyoneHtm(); 12583 12584 var pctCustom = '<i class="narrow-text">(currently <b class="narrow-text">only MUNBYN</b> receipt printers are supported on Windows PC)</i>'; 12585 12586 var hPct = '<h3>Receipt Printer Settings - Windows</h3>'; 12587 var msgPct = '<p> Configure receipt printer settings for cash drawer open' + pctCustom + '</p>'; 12588 var videoPct = '<video controls controlsList="nodownload" muted width="800"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/munbyn-cashbox-none.mp4" type="video/mp4">Your browser does not support the video tag</video>'; 12589 12590 var hDollar = '<h3>Download & Install ' + sa + ' Printer Utility - Windows</h3>'; 12591 var msgDollar = '<p>Our Printer Utility is a lightweight app that runs on your Windows PC and allows ' + sa + ' to directly communicate with your receipt printer</p>'; 12592 var downloadSAPrintUtility = '<a style="margin-bottom:20px;font-weight:bold;" href="' + GLO.Data.cdnDirectory + 'image/faq/printer/SetupSAClientServer.msi"">Download SA Print Utility</a>'; 12593 var videoDollar = '<video controls controlsList="nodownload" muted width="800" style="margin-top:20px;"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/install-sa-print-utility.mp4" type="video/mp4">Your browser does not support the video tag.</video>'; 12594 12595 var hDollar2 = '<h3>Launch ' + sa + ' Printer Utility after reboot - Windows</h3>'; 12596 var msgDollar2 = '<p>Use these instructions to setup SA Printer Utility to launch automatically after computer reboots</p>'; 12597 var videoDollar2 = '<video controls controlsList="nodownload" muted width="800" style="margin-top:20px;"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/launch-sa-utility-at-startup.mp4" type="video/mp4">Your browser does not support the video tag</video>'; 12598 12599 var htm = '<div id="pop-help-tip-percent-or-dollar">' + title + hDollar + msgDollar + downloadSAPrintUtility + videoDollar + hPct + msgPct + videoPct + hDollar2 + msgDollar2 + videoDollar2 + '</div>'; 12600 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Configure Cash Drawer open settings', null, null, true); 12601 var jpop = ojpop.getPopup(); 12602 12603 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 12604 GLO.Popup.Custom.singleButton(jpop); 12605 ojpop.realign(); 12606 12607 if (GLO.Info.isMobile(true)) { 12608 setTimeout(function() { ojpop.realign(); }, 900); 12609 } else { 12610 jpop.css({ "top": "40px" }); 12611 } 12612 } 12613 12614 _conRptCash.displayLocalPrinters = function() { 12615 var $printSelectHelpIcon = '<b class="help-icon4" onclick="GLO.Report.Cash.openHelpPrinterSelect()" title="Open cash drawer only for cash payments">?</b>'; 12616 //CHECK IF COOKIE EXISTS 12617 var selectedReceiptPrinterFromCookie = SA.ClientServer.getReceiptPrinterFromCookie(); 12618 12619 SA.ClientServer.checkApiStatus() 12620 .then(isRunning => { 12621 if (isRunning) { 12622 console.log('Web application can use API'); 12623 SA.ClientServer.getLocalPrinters() 12624 .then(printersArray => { 12625 if (printersArray.length > 0) { 12626 console.log('display local printers'); 12627 $('#local-printer-selection-container').removeClass('hide'); 12628 var $printerSelectLabel = $('<label for="printerSelect">Select Receipt Printer: </label>') 12629 var $printerSelect = $("<select id='printerSelect'></select>"); 12630 printersArray.forEach(item=> { 12631 $printerSelect.append($('<option>', { 12632 value: item.name, 12633 text : item.name 12634 })); 12635 });
12636 $('#local-printer-selection-container').empty(); 12637 $('#local-printer-selection-container').append($printerSelectLabel); 12638 $('#local-printer-selection-container').append($printerSelect); 12639 $('#local-printer-selection-container').append($printSelectHelpIcon); 12640 if (selectedReceiptPrinterFromCookie) { 12641 $printerSelect.val(selectedReceiptPrinterFromCookie); 12642 } 12643 12644 } 12645 else { 12646 console.log('Cannot display local printers'); 12647 $('#local-printer-selection-container').removeClass('hide'); 12648 var $printerNotFound = $('<span style="color:red">No printers found</span>'); 12649 $('#local-printer-selection-container').empty(); 12650 $('#local-printer-selection-container').append($printerNotFound); 12651 $('#local-printer-selection-container').append($printSelectHelpIcon); 12652 } 12653 }) 12654 } 12655 else { 12656 console.log('Cash drawer option disabled, API unavailable'); 12657 var $printerNotFound = $('<span style="color:red">No printers found. Check if Printer Utility is installed.</span>'); 12658 $('#local-printer-selection-container').removeClass('hide'); 12659 $('#local-printer-selection-container').empty(); 12660 $('#local-printer-selection-container').append($printerNotFound); 12661 $('#local-printer-selection-container').append($printSelectHelpIcon); 12662 } 12663 }) 12664 } 12665 12666 _conRptCash.openDrawer = function() { 12667 12668 //CHECK IF COOKIE EXISTS 12669 var selectedReceiptPrinterFromCookie = SA.ClientServer.getReceiptPrinterFromCookie(); 12670 12671 SA.ClientServer.checkApiStatus() 12672 .then(isRunning => { 12673 if (isRunning) { 12674 console.log('Web application can use API'); 12675 SA.ClientServer.postOpenDrawer(selectedReceiptPrinterFromCookie) 12676 .then(response => { 12677 if (response == 'success') { 12678 console.log('open drawer success'); 12679 } 12680 else { 12681 console.log('could not open drawer'); 12682 } 12683 }) 12684 } 12685 else { 12686 console.log('Cash drawer option disabled, API unavailable'); 12687 } 12688 }) 12689 } 12690 12691 return _conRptCash; 12692})(); 12693 12694 12695GLO.Report.TicketHistory = (function() { 12696 function _conRptTicket() { } 12697 12698 _conRptTicket.init = function() { 12699 var jtbl = $('table.tablesorter:visible'); 12700 var jhead = $('.report-search-header'); 12701 12702 UI.initTableSorter(jtbl); 12703 12704 for (var i=0; i < jhead.length; i++) { 12705 jhead.eq(i).find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 }); 12706 jhead.eq(i).find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths() }); 12707 } 12708 12709 var ifilter = UTIL.coalesceString(GLO.Uri.query('inventoryfilter'), GLO.Uri.query('ifilter')); 12710 var by = _initGroupBy(); 12711 12712 jhead.find('.Inventory_Filter').val(ifilter).find('option[value="-1"]').remove(); 12713 12714 _displayHeaderInfo(by); 12715 _setHeading(jhead, ifilter); 12716 12717 if (!GLO.Report.Sales.initStaffFilter()) { 12718 GLO.Report.Template.initStaffFilter(); 12719 } 12720 12721 GLO.Staff.Filter.isReportPortal = true; 12722 GLO.Report.portalName = 'ticket'; 12723 GLO.Report.CellSummary.initReport(jtbl, true, true); 12724 GLO.Report.initIcons(jtbl); 12725 GLO.Report.setupFastClick(); 12726 12727 _initSingleClient(); 12728 _conRptTicket.loadColumns(jtbl); 12729 GLO.Report.initUrlAction(); 12730 } 12731 12732 _conRptTicket.loadColumns = function(jtbl) { 12733 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-staff'); 12734 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-service'); 12735 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-product'); 12736 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-price'); 12737 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-payment'); 12738 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-note'); 12739 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-checkin'); 12740 GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-checkout'); 12741 12742 var colCount = jtbl.find('tbody > tr:first td:not(.hideX)').length; 12743 var jrpt = jtbl.closest('.report-container').addClass('column-count-' + colCount); 12744 12745 if (colCount > 11) { 12746 jrpt.addClass('ticket-history-very-wide'); 12747 } else if (colCount > 9) { 12748 jrpt.addClass('ticket-history-wide'); 12749 } 12750 } 12751 12752 function _initSingleClient() { 12753 var j = $('#report-ticket-history'); 12754 var jclient = j.find('#Client_Filter_id'); 12755 12756 if (jclient.length > 0) { 12757 UI.initAutoComplete(jclient, GLO.Link.Object.Provider.ClientSearch); 12758 12759 var cname = j.find('#ticket-history-report tbody > tr:first').find('.ticket-column-buyer > a').text(); 12760 12761 if (!UTIL.isEmpty(cname)) { 12762 jclient.val(cname).attr('autoId', GLO.Uri.query('client')); 12763 } else { 12764 new GLO.Popup.Info.openSimple('No tickets found for client that match the search parameters', 'No Tickets Found'); 12765 } 12766 } 12767 } 12768 12769 function _initGroupBy() { 12770 var j = $('#group-by'); 12771 12772 var pm = GLO.Uri.query('pay-method'); 12773 if (!UTIL.isEmpty(pm)) { j.val('pm' + pm); return 'pm'; } 12774 12775 var as = GLO.Uri.query('appt-status'); 12776 if (!UTIL.isEmpty(as)) { j.val('as' + as); return 'as'; } 12777
12778 var ct = GLO.Uri.query('client-type'); 12779 if (!UTIL.isEmpty(ct)) { j.val('ct' + ct); return 'ct'; } 12780 12781 var tw = GLO.Uri.query('ticket-with'); 12782 if (!UTIL.isEmpty(tw)) { j.val('tw' + tw); return 'tw'; } 12783 12784 var pr = GLO.Uri.query('referral'); 12785 if (!UTIL.isEmpty(pr)) { j.val('pr' + pr); return 'pr'; } 12786 12787 var pd = GLO.Uri.query('discount'); 12788 if (!UTIL.isEmpty(pd)) { j.val('pd' + pd); return 'pd'; } 12789 12790 var ad = GLO.Uri.query('addon'); 12791 if (!UTIL.isEmpty(ad)) { j.val('ad' + ad); return 'ad'; } 12792 12793 var sg = GLO.Uri.query('service-group'); 12794 if (!UTIL.isEmpty(sg)) { j.val('sg' + sg); return 'sg'; } 12795 12796 var iv = GLO.Uri.query('vendor'); 12797 if (!UTIL.isEmpty(iv)) { j.val('iv' + iv); return 'iv'; } 12798 12799 var ic = GLO.Uri.query('product-category'); 12800 if (!UTIL.isEmpty(ic)) { j.val('ic' + ic); return 'ic'; } 12801 12802 var it = GLO.Uri.query('product-type'); 12803 if (!UTIL.isEmpty(it)) { j.val('it' + it); return 'it'; } 12804 } 12805 12806 function _displayHeaderInfo(by) { 12807 $('#ticket-header-referral-info, #ticket-header-discount-info, #ticket-header-addon-info').addClass('hide'); 12808 12809 if (by === 'pr') { 12810 $('#ticket-header-referral-info').removeClass('hide'); 12811 } else if (by === 'pd') { 12812 $('#ticket-header-discount-info').removeClass('hide'); 12813 } else if (by === 'ad') { 12814 $('#ticket-header-addon-info').removeClass('hide'); 12815 } 12816 } 12817 12818 function _setHeading(jhead, ifilter) { 12819 var lbl = $('#group-by :selected').text(); 12820 12821 if (UTIL.isEmpty(lbl) && !UTIL.isEmpty(ifilter)) { 12822 lbl = $.trim(jhead.find('.Inventory_Filter').find('option:selected').text()); 12823 } 12824 12825 $('#ticket-history-title-span').text(lbl + ' ' + SA.Resource.TicketHistory); 12826 12827 _addOtherParameterToHelp(); 12828 GLO.Report.enableFullPageCheck(); 12829 } 12830 12831 function _getGroupBy(gby) { 12832 var dos = gby.substring(0, 2); 12833 gby = gby.substring(2); 12834 12835 _displayHeaderInfo(gby); 12836 12837 if (dos === 'pm') { 12838 return '&pay-method=' + gby; 12839 } else if (dos === 'as') { 12840 return '&appt-status=' + gby; 12841 } else if (dos === 'ct') { 12842 return '&client-type=' + gby; 12843 } else if (dos === 'tw') { 12844 return '&ticket-with=' + gby; 12845 } else if (dos === 'pr') { 12846 return '&referral=' + gby; 12847 } else if (dos === 'pd') { 12848 return '&discount=' + gby; 12849 } else if (dos === 'ad') { 12850 return '&addon=' + gby; 12851 } else if (dos === 'sg') { 12852 return '&service-group=' + gby; 12853 } else if (dos === 'iv') { 12854 return '&vendor=' + gby; 12855 } else if (dos === 'ic') { 12856 return '&product-category=' + gby; 12857 } else if (dos === 'it') { 12858 return '&product-type=' + gby; 12859 } else { 12860 return ''; 12861 } 12862 } 12863 12864 function _getOtherParameters() { 12865 var minstaff = GLO.Uri.query('minstaff'); 12866 var minservice = GLO.Uri.query('minservice'); 12867 var minproduct = GLO.Uri.query('minproduct'); 12868 var mindiscount = GLO.Uri.query('mindiscount'); 12869 var minservicediscount = GLO.Uri.query('minservicediscount'); 12870 12871 return { "minstaff": minstaff, "minservice": minservice, "minproduct": minproduct, "mindiscount": mindiscount, "minservicediscount": minservicediscount }; 12872 } 12873 12874 function _keepOtherParameters() { 12875 var json = _getOtherParameters(); 12876 var qs = ''; 12877 12878 if (!UTIL.isEmpty(json.minstaff)) { qs += '&minstaff=' + json.minstaff; } 12879 if (!UTIL.isEmpty(json.minservice)) { qs += '&minservice=' + json.minservice; } 12880 if (!UTIL.isEmpty(json.minproduct)) { qs += '&minproduct=' + json.minproduct; } 12881 if (!UTIL.isEmpty(json.mindiscount)) { qs += '&mindiscount=' + json.mindiscount; } 12882 if (!UTIL.isEmpty(json.minservicediscount)) { qs += '&minservicediscount=' + json.minservicediscount; } 12883 12884 return qs; 12885 } 12886 12887 function _addOtherParameterToHelp() { 12888 var json = _getOtherParameters(); 12889 var msg = ''; 12890 12891 if (!UTIL.isEmpty(json.minstaff)) { msg += _addOtherParameterItemToHelp('staff', json.minstaff, false); } 12892 if (!UTIL.isEmpty(json.minservice)) { msg += _addOtherParameterItemToHelp('Service', json.minservice, true); } 12893 if (!UTIL.isEmpty(json.minproduct)) { msg += _addOtherParameterItemToHelp('Product', json.minproduct, true); } 12894 if (!UTIL.isEmpty(json.mindiscount)) { msg += _addOtherParameterItemToHelp('Discount', json.mindiscount, true); } 12895 if (!UTIL.isEmpty(json.minservicediscount)) { msg += _addOtherParameterItemToHelp('Service Discount', json.minservicediscount, true); } 12896 12897 if (msg !== '') { 12898 var msg = '<ul id="report-header-help-other-param">' + msg + '</ul>'; 12899 $('#report-header-help-text').append(msg); 12900 } 12901 } 12902 12903 function _addOtherParameterItemToHelp(minLabel, minValue, allowPlural) { 12904 if (allowPlural) { 12905 minLabel = UTIL.pluralLabel(minValue, minLabel); 12906 } 12907 12908 var queryKey = 'min' + minLabel.toLowerCase().replace(' ', ''); 12909 var iconRemove = '<span class="report-header-help-remove" onclick="GLO.Report.TicketHistory.removeOtherParam(this, \'' + queryKey + '\')">✖</span>'; 12910 12911 return '<li>' + iconRemove + '<i>and ticket has at least ' + minValue + ' ' + minLabel + '</i></li>'; 12912 } 12913 12914 _conRptTicket.removeOtherParam = function(icon, queryKey) { 12915 GLO.Uri.removeQueryKey(queryKey); 12916 $(icon).closest('li').remove(); 12917 12918 GLO.Report.TicketHistory.search(); 12919 } 12920 12921 _conRptTicket.changeUrl = function(qs, title) { 12922 if (window.history.pushState) { 12923 //var htm = $('body').outerHTML(); 12924 var url = window.location.origin + window.location.pathname + '?' + qs; 12925 12926 //window.history.pushState({"html": htm, "pageTitle": "Ticket History" } , "", url); 12927 window.history.pushState({ "pageTitle": title } , "", url); 12928 } 12929 } 12930 12931 _conRptTicket.gotoReport = function(event, url, element) { 12932 if (event && event.target && element === undefined) { 12933 element = event.target; 12934 } 12935 12936 GLO.Uri.gotoReport(url, element, null, null, null, event); 12937 return; 12938 12939 var sfilter = GLO.Uri.query('sfilter'); 12940 12941 if (!UTIL.isEmpty(sfilter)) { url += '&sfilter=' + sfilter; } 12942 12943 if (SA.Menu.isRequirePIN(url, null, event)) { 12944 return false; 12945 } 12946 12947 if (event.ctrlKey) { 12948 url = document.location.protocol + '//' + document.location.host + url; 12949 var childWindow = UI.openChildWindow(url, '', true); 12950 } else { 12951 setTimeout(function() { 12952 document.location = url; 12953 }, 100); 12954 } 12955 } 12956 12957 _conRptTicket.search = function(isExportToExcel) { 12958 var jrpt = $('#report-ticket-history'); 12959 var begin = jrpt.find('.Begin_dt').val(); 12960 var end = jrpt.find('.End_dt').val(); 12961 12962 var gby = jrpt.find('#group-by').val(); 12963 var ifilter = jrpt.find('.Inventory_Filter').val(); 12964 var other = _keepOtherParameters(); 12965 var jd = {}, qs = 'start=' + begin + '&end=' + end + other; 12966 12967 if (!GLO.Report.hasReportPassword(jd)) { 12968 return; 12969 } 12970 12971 if (!UTIL.isEmpty(gby)) { 12972 qs += _getGroupBy(gby); 12973 } else if (!UTIL.isEmpty(ifilter)) { 12974 qs += '&ifilter=' + ifilter; 12975 } 12976 12977 var sfilter = GLO.Uri.query('sfilter'); 12978 if (!UTIL.isEmpty(sfilter)) { qs += '&sfilter=' + sfilter; } 12979 12980 var jclient = jrpt.find('#Client_Filter_id'); 12981 if (!UTIL.isEmpty(jclient.val())) { qs += '&client=' + jclient.attr('autoId'); } 12982 12983 qs += GLO.Message.Bulk.getTagQueryString(jrpt); 12984 12985 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?search=1&' + qs; 12986 setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs, SA.Resource.TicketHistory); }, 50); 12987 12988 if (isExportToExcel) { 12989 var btnExport = jrpt.parent().find('.btnExportToExcel'); 12990 GLO.UI.Form.beginProcessing(btnExport); 12991 12992 window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 4500); 12993 12994 url += '&ExportToExcel=1'; 12995 var childWindow = UI.openChildWindow(url, '', true); 12996 12997 return; 12998 } else { 12999 var jbtn = jrpt.find('.btnSearch'); 13000 GLO.UI.Form.beginProcessing(jbtn); 13001 } 13002
13003 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jd }) 13004 .success(function(data, textStatus, jqXHR) { 13005 GLO.UI.Form.resetProcessing(); 13006 13007 if (!UTIL.isEmpty(data)) { 13008 jrpt.find('.report-container').html(data); 13009 var jtbl = jrpt.find('table.tablesorter:visible'); 13010 13011 UI.initTableSorter(jtbl); 13012 GLO.Report.CellSummary.initReport(jtbl, true, true); 13013 GLO.Report.initIcons(jtbl); 13014 _conRptTicket.loadColumns(jtbl); 13015 } else { 13016 GLO.Popup.Info(SA.Resource.NoResultsFound); 13017 } 13018 13019 var jhead = $('.report-search-header'); 13020 _setHeading(jhead, ifilter); 13021 }) 13022 .error(function(jqXHR, textStatus, errorThrown) { 13023 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 13024 GLO.UI.Form.resetProcessing(); 13025 }); 13026 } 13027 13028 function _helpColorMessage(label) { 13029 return '<p>The color indicates the ' + label + ' status</p>'; 13030 } 13031 function _openHelpColorPopup(htm, h1) { 13032 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 13033 GLO.Popup.Custom.singleButton(jpop, 'Close'); 13034 return jpop; 13035 } 13036 _conRptTicket.helpDateColor = function() { 13037 var msg = _helpColorMessage('Appointment Status'); 13038 13039 var aOnclick = 'GLO.FAQ.gotoQuestion(\'calendar-appt-icons\', \'tips\', this, event)'; 13040 var aIcon = '<a onclick="' + aOnclick + '" style="font-weight: bold" title="What do the icons on appointments mean?">FAQ: Appointment Icons</a>'; 13041 var labelIcon = '<span class="narrow-text">Information about the different icons</span>'; 13042 var htmIconInfo = '<div style="margin-bottom: 24px; padding: 6px;">' + labelIcon + ' <b class="arrow-right">➜</b> ' + aIcon + '</div>'; 13043 13044 var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>' 13045 + '<li class="ticket-column-date-checkin">Appointment Status = Checked-In</li>' 13046 + '<li class="ticket-column-date-checkout">Appointment Status = Checked-Out</li>' 13047 + '<li class="ticket-column-date-noshow">Appointment Status = No Show</li>' 13048 + '<li class="ticket-column-date-latecancel">Appointment Status = Late Cancelation</li>' 13049 + '</ul>' + htmIconInfo + '</div>'; 13050 13051 _openHelpColorPopup(htm, 'Appointment Status Color'); 13052 } 13053 _conRptTicket.helpPaymentColor = function() { 13054 var msg = _helpColorMessage('Payment'); 13055 var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>' 13056 + '<li class="ticket-column-price-paid">Ticket Fully Paid</li>' 13057 + '<li class="ticket-column-price-partial-paid">Ticket Partially Paid</li>' 13058 + '<li class="ticket-column-unpaid">Ticket Un-Paid</li>' 13059 + '</ul></div>'; 13060 _openHelpColorPopup(htm, 'Payment Color'); 13061 } 13062 _conRptTicket.helpApptStatusColor = function(isCheckout) { 13063 if (isCheckout) { 13064 var word = 'Check-Out'; 13065 } else { 13066 var word = 'Check-In'; 13067 } 13068 13069 var msg = _helpColorMessage(word); 13070 var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>' 13071 + '<li class="checkin-ontime">' + word + ' On Time <small></small></li>' 13072 + '<li class="checkin-barely-late">' + word + ' Barely Late <small>(less than 5 minutes late)</small></li>' 13073 + '<li class="checkin-slightly-late">' + word + ' Slightly Late <small>(more than 5 minutes late)</small></li>' 13074 + '<li class="checkin-late">' + word + ' Late <small>(more than 15 minutes late)</small></li>' 13075 + '<li class="checkin-very-late">' + word + ' Very Late <small>(more than 1 hour late)</small></li>' 13076 + '<li class="checkin-extremely-late">' + word + ' Extremely Late <small>(more than 2 hours late)</small></li>'; 13077 + '</ul></div>'; 13078 _openHelpColorPopup(htm, word + ' Color'); 13079 } 13080 13081 return _conRptTicket; 13082})(); 13083 13084 13085GLO.Report.Other = (function() { 13086 function _conRptOther() { } 13087 13088 _conRptOther.init = function() { 13089 GLO.Staff.Filter.isReportPortal = true; 13090 GLO.Info.init(); 13091 GLO.Report.Template.initStaffFilter(); 13092 13093 var jtbls = $('.tablesorter'); 13094 13095 for (var i=0; i < jtbls.length; i++) { 13096 UI.initTableSorter( jtbls.eq(i) ); //$('#report-main .tablesorter') 13097 } 13098 13099 GLO.Report.setupFastClick(); 13100 _conRptOther.initWithSearch(); 13101 _initData(jtbls); 13102 _initHelloBar(); 13103 _initInventoryFilter(); 13104 GLO.Report.enableFullPageCheck(); 13105 13106 _initPaymentIncorrect(); 13107 _conRptOther.initUrl(); 13108 } 13109 _conRptOther.initIncorrect = function() { 13110 _conRptOther.init(); 13111 13112 if (GLO.Info.isMobile() && GLO.Info.roleType > 209) { 13113 var jstaff = $('#hd-mobile #staff-filter'); 13114 13115 if (jstaff.find('option[value="all"]').length === 0) { 13116 jstaff.prepend('<option value="all" title="All staff members">ALL</option>'); 13117 13118 if (UTIL.isEmpty(GLO.Uri.url('highlight'))) { 13119 jstaff.find('option[value="all"]').prop('selected', true); 13120 } 13121 } 13122 } 13123 } 13124 _conRptOther.initUrl = function() { 13125 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 13126 13127 if (!UTIL.isEmpty(highlight)) { 13128 var jhighlight = $('#' + highlight + ', .' + highlight); 13129 13130 if (jhighlight.length > 0) { 13131 UI.highlight(jhighlight, 800, 6400, true); 13132 } 13133 } 13134 } 13135 function _initInventoryFilter() { 13136 var ifilter = GLO.Uri.query('inventoryfilter'); 13137 13138 if (!UTIL.isEmpty(ifilter)) { 13139 $('.report-search-header .inventory-filter').val(ifilter); 13140 } 13141 } 13142 13143 function _initHelloBar() { 13144 var sfilter = GLO.Uri.query('sfilter'); 13145 13146 if (UTIL.coalesce(sfilter, 'all') != 'all') { 13147 GLO.Report.setStaffHelloBar(sfilter); 13148 } 13149 } 13150 13151 _conRptOther.initWithSearch = function() { 13152 GLO.Staff.Filter.isReportPortal = true; 13153 var jhead = $('.report-search-header'); 13154 13155 for (var i=0; i < jhead.length; i++) { 13156 jhead.eq(i).find('input[type=text].Report_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 }); 13157 jhead.eq(i).find('input[type=text].Report_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths() }); 13158 } 13159 13160 //$('#report-portal-header').removeClass('hide'); 13161 //_conRptTemplate.initStaffFilter(); 13162 } 13163 13164 function _initData(jtbls) { 13165 for (var i=0; i < jtbls.length; i++) { 13166 GLO.Report.CellSummary.initReport(jtbls.eq(i), true, true); 13167 GLO.Report.initIcons(jtbls.eq(i)); 13168 } 13169 } 13170 13171 function _initPaymentIncorrect() { 13172 if ($('#report-header-help-incorrect-payment').length === 0) { return; } 13173 13174 GLO.Report.portalName = 'incorrect-payment'; 13175 13176 setTimeout(function() { 13177 $('.shadow-content0 h1 .fa-refresh').click(); 13178 }, 900); 13179 } 13180 13181 function _setUrl(uri, title) { 13182 window.history.pushState('', '', uri); 13183 13184 if (title) { 13185 document.title = title; 13186 } 13187 } 13188 13189 _conRptOther.search = function(button, isExportToExcel) { 13190 var jd = {}, jrpt = $('#report-main'); 13191 var uri = location.origin + location.pathname + '?'; 13192 button = $(button); 13193 13194 if (button.hasClass('fa-spin')) { 13195 return; 13196 } else if (!GLO.Report.hasReportPassword(jd)) { 13197 return; 13198 } 13199 13200 if (button.hasClass('fa')) { 13201 button.addClass('fa-spin'); 13202 } else { 13203 GLO.UI.Form.beginProcessing(button.parent()); 13204 } 13205 13206 var jRptHeader = $('.report-search-header:visible'); 13207 var qstring = '', sfilter = GLO.Uri.query('sfilter'), days =
13207UTIL.cleanString(GLO.Uri.query('days')), ifilter = UTIL.cleanString($('.report-search-header .inventory-filter').val()); 13208 13209 if (GLO.Report.portalName === 'incorrect-payment') { 13210 if (!UTIL.isEmpty(days)) { uri += '&days=' + days; } 13211 } else { 13212 jrpt.css({ "text-align": "center" }).html( $('#imgThrobber').outerHTML() ); 13213 jrpt.find('#imgThrobber').css({ "margin": "30px" }); 13214 } 13215 13216 if (jRptHeader.length > 0) { 13217 var start = jRptHeader.find('.Report_Begin_dt').val(); 13218 if (UTIL.isDate(start)) { qstring += '&start=' + new Date(start).toGloDate(true); } 13219 13220 var end = jRptHeader.find('.Report_End_dt').val(); 13221 if (UTIL.isDate(end)) { qstring += '&end=' + new Date(end).toGloDate(true); } 13222 } 13223 13224 if (!UTIL.isEmpty(sfilter)) { 13225 qstring += '&sfilter=' + sfilter; 13226 } 13227 13228 if (!UTIL.isEmpty(ifilter)) { 13229 qstring += '&inventoryfilter=' + ifilter; 13230 } 13231 13232 if (isExportToExcel) { 13233 qstring += '&ExportToExcel=1'; 13234 } 13235 13236 var jqxhr = $.ajax({ type: "POST", url: uri + qstring + '&ispartial=1', "cache": false, "data": jd }) 13237 .success(function(data, textStatus, jqXHR) { 13238 button.removeClass('fa-spin'); 13239 GLO.UI.Form.resetProcessing(); 13240 13241 var jdata = $(data); 13242 jrpt.html( jdata.html() ); 13243 13244 var tbl = jrpt.find('.tablesorter'); 13245 if (tbl.length > 0) { UI.initTableSorter(tbl); } 13246 13247 _initData(tbl); 13248 _setUrl(uri + qstring); 13249 GLO.Report.enableFullPageCheck(); 13250 }) 13251 .error(function(jqXHR, textStatus, errorThrown) { 13252 button.removeClass('fa-spin'); 13253 GLO.UI.Form.resetProcessing(); 13254 13255 if (jrpt.find('.incorrect-payment-report').length) { 13256 button.remove(); 13257 } else { 13258 var htm = '<div style="padding: 20px 0; text-align: center; line-height: 200%; letter-spacing: 1px;">Unable to load report</br>Please try again</div>'; 13259 jrpt.html(htm); 13260 } 13261 }); 13262 } 13263 13264 return _conRptOther; 13265})(); 13266 13267 13268GLO.Report.StaffSummary = (function() { 13269 function _conStaffSum() {} 13270 13271 _conStaffSum.init = function(startDay, endDay) { 13272 GLO.Report.Template2.init('staff-summary', startDay, endDay); 13273 $('#report-main').find('.btnSearch > a').click(); 13274 } 13275 13276 _conStaffSum.searchComplete = function(jrpt, data) { 13277 GLO.Report.Template2.searchCompleteFade(jrpt, data); 13278 GLO.Report.CellSummary.initReport(jrpt, true, true); 13279 13280 setTimeout(function() { 13281 $('#report-staff-summary.report-container .tablesorter thead tr:last-child .column-staff').click(); //sort by staff name 13282 }, 150); 13283 13284 _hideClientRequestColumn(); 13285 } 13286 13287 function _hideClientRequestColumn() { 13288 if (!GLO.Data.displayClientRequest) { 13289 var jrpt = $('#report-staff-summary'); 13290 var jtrHead = jrpt.find('thead > tr'); 13291 jrpt.find('.column-client-request').addClass('hide'); 13292 13293 _changeColumnSpan(jtrHead.eq(0).find('.column-client-top'), -1); 13294 _changeColumnSpan(jtrHead.eq(1).find('.column-client-top'), -1); 13295 } 13296 } 13297 13298 function _changeColumnSpan(jtd, diff) { 13299 var colspan = parseInt(jtd.attr('colspan')); 13300 jtd.attr('colspan', colspan + diff); 13301 } 13302 13303 _conStaffSum.openClientRequestHelp = function() { 13304 var h1 = 'When is Appointment marked as a Client Request?'; 13305 13306 var roleList = 'The staff roles <i>Limited-Receptionist</i>, <i>Receptionist</i>, <i>Manager</i>, and <i>Admin</i>'; 13307 var htmArrow = ' ➜ '; 13308 var seeHowLink = '<a onclick="GLO.Provider.Advanced.Help.Calendar.openDisplayClientRequest()">see how</a>'; 13309 var li1 = roleList + ' can assign whether the client requested the staff when creating or editing the appointment' + htmArrow + seeHowLink; 13310 13311 var li2 = 'If other staff roles create an appointment for themselves on a day in the future that appointment is set as a client request'; 13312 var li3 = 'When a client books online, if the client specifically searches for a specific staff member, then that staff is set as a client request'; 13313 13314 var ul = '<ul> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li> </ul>'; 13315 var htm = '<div id="pop-client-request-info">' + ul + '</div>'; 13316 13317 GLO.Popup.Info.open(htm, h1).getPopup().css({ "background-color": "rgba(230, 248, 255)" }); 13318 } 13319 13320 return _conStaffSum; 13321})(); 13322 13323 13324GLO.Report.StaffSummaryDetail = (function() { //= Staff Goal Report 13325 function _conStaffSumDetail() {} 13326 var _isInitComplete = false, _isInitialPageLoad = true; 13327 var _searchRequest = null; 13328 13329 _conStaffSumDetail.init = function() { 13330 GLO.Staff.Filter.isReportPortal = true; 13331 GLO.Report.portalName = 'staff-summary-detail'; 13332 13333 if (!GLO.Report.Sales.initStaffFilter()) { 13334 GLO.Report.Template.initStaffFilter(true); 13335 } 13336 13337 var jrpt = $('#report-staff-summary-detail'); 13338 var jhead = $('.report-search-header'); 13339 13340 jhead.find('#Start_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 13341 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 13342 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }); 13343 jhead.find('#End_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 13344 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 13345 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }); 13346 13347 jhead.find('#Start_Week_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 13348 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 13349 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }); 13350 jhead.find('#End_Week_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1) 13351 , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths() 13352 , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }); 13353 13354 jhead.find('#Start_Month_d').Monthpicker(); 13355 jhead.find('#End_Month_d').Monthpicker(); 13356 13357 var period = GLO.Uri.query('period'); 13358 _conStaffSumDetail.setPeriod(period); 13359 13360 _initDisplayEndDate(); 13361 _initOtherFilter(); 13362 13363 GLO.Report.setupFastClick(); 13364 GLO.Report.StaffSummaryDetail.search(); 13365 13366 $('#bd #report-main .open-help-arrow:visible').click(); 13367 } 13368 function _initOtherFilter() { 13369 if (UTIL.parseBool($.cookies.get('Only_Paid_fl'))) { 13370 $('#staff-goal-filter-other').find('#Only_Paid_fl').prop('checked', true); 13371 } 13372 13373 if (UTIL.parseBool($.cookies.get('Only_Clocked_In_Hours_fl'))) { 13374 $('#staff-goal-filter-other').find('#Only_Clocked_In_Hours_fl').prop('checked', true); 13375 } 13376 } 13377 function _initDisplayEndDate() { 13378 var dtEnd = GLO.Uri.query('end'); 13379 13380 if (UTIL.isDate(dtEnd)) { 13381 $('#staff-summary-detail-header').find('.date-cell.end-cell').removeClass('hide'); 13382 } 13383 } 13384 function _initGoals(jrpt) { 13385 var tfoot = jrpt.find('tfoot'); 13386 var goalId = tfoot.attr('staff_goal_id'); 13387 13388 if (GLO.Info.roleType > 219) { //= is manager 13389 var btnSave = '<span class="btnEditGoals btnSave"> <a onclick="GLO.Report.StaffSummaryDetail.editGoal(this)">Change</a></span>';
13390 tfoot.find('tr.report-goal-row').find('td.column-period, td.column-goal').append(btnSave); 13391 tfoot.find('input').on('change', function() { 13392 $(this).closest('tr').find('.btnEditGoals').addClass('btn-has-change'); 13393 }); 13394 13395 if (tfoot.find('.report-goal-row').length > 1) { 13396 tfoot.find('tr.report-goal-row').find('.column-staff').on('mousedown', GLO.Report.StaffSummaryDetail.enableSort); 13397 $('#report-staff-summary-detail').addClass('allow-sort'); 13398 } 13399 } else { 13400 tfoot.find(':text').prop('disabled', true); 13401 } 13402 } 13403 13404 function _initSortGoals(tfoot) { 13405 var jrpt = $('#report-staff-summary-detail').addClass('enable-sort-goal'); 13406 jrpt.find('tfoot tr.report-goal-row').find('.column-staff').off('mousedown', GLO.Report.StaffSummaryDetail.enableSort); 13407 13408 jrpt.find('tfoot').sortable({ 13409 handle: 'td.column-staff' 13410 , items: 'tr.report-goal-row' 13411 , change: function(event, ui) { 13412 var test = 123; 13413 } 13414 , update: function(event, ui) { 13415 var goalId = ui.item.attr('staff_goal_id'); 13416 var trs = $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row'); 13417 var xml = ''; 13418 13419 for (var i=0; i < trs.length; i++) { 13420 var goalId = trs.eq(i).attr('staff_goal_id'); 13421 xml += '<tr goal_id="' + goalId + '"></tr>'; 13422 13423 if (UTIL.isEmpty(goalId)) { 13424 var msg = '<div id="pop-warn-unsaved-goal-level">Please Save New Goal Level before sorting</div>'; 13425 var fn = function() { UI.highlight(trs.eq(i)); } 13426 13427 GLO.Popup.Warning.open(msg, 'Un-Saved New Goal Level', fn); 13428 return 13429 } 13430 } 13431 13432 _updateGoalOrder('<table>' + xml + '</table>'); 13433 } 13434 /* 13435 , start: function (event, ui) { 13436 //$('#report-staff-summary-detail-data').css({ "margin-left": 0 }); 13437 //$('#report-staff-summary-detail-data tr.report-goal-row-multi .ui-sortable-handle').css({ "position": "static" }); 13438 //$('#report-staff-summary-detail-data tr.report-goal-row-multi .btnEditGoals > a').css({ "visibility": "hidden", "display": "none" }); 13439 } 13440 , stop: function (event, ui) { 13441 //if (!_isValidOrderChange(ui)) { $(this).sortable('cancel'); } 13442 13443 //$('#report-staff-summary-detail-data').css({ "margin-left": "" }); 13444 //$('#report-staff-summary-detail-data tr.report-goal-row-multi .ui-sortable-handle').css({ "position": "" }); 13445 //$('#report-staff-summary-detail-data tr.report-goal-row-multi .btnEditGoals > a').css({ "visibility": "", "display": "" }); 13446 } 13447 */ 13448 }); 13449 } 13450 _conStaffSumDetail.helpOnlyClockedInHours = function() { 13451 var aHrs = '<a class="narrow-text" onclick="GLO.Report.StaffSummaryDetail.highlightHoursPerDay()" style="font-weight: bold; color: #139ad2;">Hours Per Day section</a>'; 13452 13453 var h1 = '<h4>Only Clocked-In Hours</h4>'; 13454 var msg1 = '<p>' + aHrs + ' only counts hours when staff is clocked-in</p>'; 13455 13456 var h2 = '<h4 style="margin-top: 36px;">Hour Available on Calendar</h4>'; 13457 var msg2 = '<p>' + aHrs + ' counts hours staff is available on the calendar</p>'; 13458 13459 var htm = '<div id="pop-help-clocked-in-only">' + h1 + msg1 + h2 + msg2 + '</div>'; 13460 GLO.Popup.Info.openSimple(htm, 'Hours Per Day', GLO.Report.StaffSummaryDetail.highlightHoursPerDay); 13461 } 13462 _conStaffSumDetail.highlightHoursPerDay = function() { 13463 var jhrs = $('#report-staff-summary-detail').find('.column-time'); 13464 UI.highlight(jhrs, 100, 9500); 13465 } 13466 _conStaffSumDetail.enableSort = function() { 13467 var jpop = GLO.Popup.Success.open('Drag the Goal Name up or down to change the sort order', 'Sort Goal Level Enabled').getPopup(); 13468 jpop.css({ "max-width": "400px", "min-width": "280px", "line-height": "1.4" }); 13469 jpop.find('.msg').css({ "padding-right": "8px" }); 13470 jpop.find('.friendly-responsive').css({ "line-height": "1.4" }); 13471 //GLO.Popup.Custom.singleButton(jpop, 'Close'); 13472 13473 _initSortGoals(); 13474 } 13475 function _isValidOrderChange(ui) { 13476 if (!ui.item.hasClass('report-goal-row')) { 13477 return false; 13478 } else { 13479 return true; 13480 } 13481 } 13482 13483 function _updateGoalOrder(xml) { 13484 var goalXml = UTIL.htmlEncode(xml); 13485 var url = GLO.Link.WebsiteDomain + 'report/StaffGoalOrder'; 13486
13487 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "goal_xml": goalXml } }) 13488 .success(function(data, textStatus, jqXHR) { 13489 var test = data; 13490 }) 13491 .error(function(jqXHR, textStatus, errorThrown) { 13492 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 13493 }); 13494 } 13495 13496 function _loadGoalCss(isReset) { 13497 var tbl = $('#report-staff-summary-detail-data'); 13498 tbl.find('.goal-met').removeClass('goal-met'); 13499 tbl.find('.goal-close').removeClass('goal-close'); 13500 tbl.find('.goal-far').removeClass('goal-far'); 13501 13502 _setColumnGoalStatus('column-count-client', tbl); 13503 _setColumnGoalStatus('column-count-service', tbl); 13504 _setColumnGoalStatus('column-count-product', tbl); 13505 13506 _setColumnGoalStatus('column-sales-total-service', tbl); 13507 _setColumnGoalStatus('column-sales-total-tip', tbl); 13508 _setColumnGoalStatus('column-sales-total-product', tbl); 13509 _setColumnGoalStatus('column-product-to-service', tbl); 13510 13511 _setColumnGoalStatus('column-service-request', tbl); 13512 _setColumnGoalStatus('column-existing', tbl); 13513 _setColumnGoalStatus('column-pre-book', tbl); 13514 13515 _setColumnGoalStatus('column-days-worked', tbl); 13516 _setColumnGoalStatus('column-hours-available', tbl); 13517 _setColumnGoalStatus('column-hours-worked', tbl); 13518 _setColumnGoalStatus('column-hours-worked-percent', tbl); 13519 13520 _setColumnGoalStatus('column-ticket-avg-total', tbl); 13521 _setColumnGoalStatus('column-ticket-avg-service', tbl); 13522 _setColumnGoalStatus('column-ticket-avg-product', tbl); 13523 13524 _setColumnGoalStatus('column-daily-avg-ticket-count', tbl); 13525 _setColumnGoalStatus('column-daily-avg-service-sales', tbl); 13526 _setColumnGoalStatus('column-daily-avg-product-sales', tbl); 13527 } 13528 13529 function _setColumnGoalStatus(columnClass, tbl) { 13530 var tds = tbl.find('tbody td.' + columnClass); 13531 var tfoot = tbl.find('tfoot'); 13532 var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl')); 13533 var goal = $.trim(tfoot.find('td.' + columnClass + ' input[type="text"]').val()).replace(',', ''); 13534 13535 for (var i=0; i < tds.length; i++) { 13536 var val = tds.eq(i).text().replace('$', '').replace(',', '').replace('%', ''); 13537 13538 if (!isSingleStaff) { 13539 var goalid = tds.eq(i).closest('tr').attr('staff_goal_id'); 13540 goal = $.trim(tfoot.find('tr[staff_goal_id="' + goalid + '"]').find('td.' + columnClass + ' input[type="text"]').val()).replace(',', ''); 13541 } 13542 13543 if (UTIL.isNumber(val) && UTIL.isNumber(goal)) { 13544 val = parseFloat(val); 13545 goal = parseFloat(goal); 13546 13547 if (val >= goal) { 13548 tds.eq(i).addClass('goal-met'); 13549 } else if (val >= goal * .9) { 13550 tds.eq(i).addClass('goal-close'); 13551 } else if (val < goal/2) { 13552 tds.eq(i).addClass('goal-far'); 13553 } 13554 } 13555 } 13556 } 13557 13558 function _loadPeriod() { 13559 var isDailyReport = $('.report-search-header #view-period-daily').prop('checked'); 13560 var isWeeklyReport = $('.report-search-header #view-period-weekly').prop('checked'); 13561 var isMonthlyReport = $('.report-search-header #view-period-monthly').prop('checked'); 13562 var trs = $('#report-staff-summary-detail tfoot tr.report-goal-row'); 13563 13564 for (var i=0; i < trs.length; i++) { 13565 var tr = trs.eq(i); 13566 13567 var isDailyGoal = UTIL.parseBool(tr.attr('period_vc') == 'day'); 13568 var isWeeklyGoal = UTIL.parseBool(tr.attr('period_vc') == 'week'); 13569 var isMonthlyGoal = UTIL.parseBool(tr.attr('period_vc') == 'month'); 13570 13571 if (isMonthlyReport && isWeeklyGoal) { //= change goals to monthly 13572 var adjust = 4.25; 13573 } else if (isMonthlyReport && isDailyGoal) { //= change goals to monthly 13574 var adjust = 4.25 * 7; 13575 } else if (isWeeklyReport && isMonthlyGoal) { //= change goals to weekly 13576 var adjust = 1/4.25; 13577 } else if (isWeeklyReport && isDailyGoal) { //= change goals to weekly 13578 var adjust = 7; 13579 } else if (isDailyReport && isWeeklyGoal) { //= change goals to daily 13580 var adjust = 1/7; 13581 } else if (isDailyReport && isMonthlyGoal) { //= change goals to daily 13582 var adjust = 1/(4.25 * 7); 13583 } else { 13584 var adjust = null; 13585 } 13586 13587 if (adjust > 0) { 13588 _loadPeriod2(tr, adjust); 13589 } 13590 } 13591 } 13592 13593 function _loadPeriod2(tr, ratio) { 13594 var jgoals = tr.find('input[type="text"]'); 13595 13596 for (var i=0; i < jgoals.length; i++) { 13597 var val = jgoals.eq(i).val().replace(',', ''); 13598 13599 if ((val >= 425 && ratio < 1) || (val >= 100 && ratio >
13599 1)) { 13600 val = Math.round(val * ratio); 13601 } else { 13602 val = Math.round(val * ratio, 1); 13603 } 13604 13605 if (val >= 1000) { 13606 val = UTIL.displayMoney(val, true, false, true); 13607 } 13608 13609 jgoals.eq(i).val(val); 13610 } 13611 } 13612 13613 _conStaffSumDetail.changeActiveStaffOnly = function(element) { 13614 UI.highlightStaffFilter(); 13615 $('#staff-summary-detail-header').find('.btnSearch > a').click(); 13616 } 13617 _conStaffSumDetail.setFilterOption = function(element) { //previously: changePaidOnly() 13618 if (element.type == 'checkbox') { 13619 if (element.checked) { 13620 UTIL.setCookie(element.id, '1'); 13621 } else { 13622 UTIL.setCookieWithExpire(element.id, null); 13623 } 13624 } 13625 13626 //$('#staff-summary-detail-header').find('.btnSearch > a').click(); 13627 } 13628 _conStaffSumDetail.setPer = function(element) { 13629 var j = $('#report-main'); 13630 var jhead = j.find('#staff-summary-detail-header'); 13631 var period = jhead.find('input[name="view-period"]:checked').val() 13632 13633 _conStaffSumDetail.setPeriod(period); 13634 UI.highlightStaffFilter(); 13635 } 13636 _conStaffSumDetail.setPeriod = function(period, isReload) { 13637 var j = $('#report-main'); 13638 var jhead = j.find('#staff-summary-detail-header'); 13639 var jPerLabel = j.find('#report-search-header-per-period').find('label'); 13640 13641 var isDisplayEndDate = (jhead.find('input[name="filter-per"]:checked').val() === 'period' || UTIL.parseBool(j.find('tfoot').attr('is_single_staff_fl'))); 13642 var jend = $('#staff-summary-detail-header').find('.date-cell.end-cell'); 13643 13644 if (period === 'day' || period === 'daily') { 13645 j.removeClass('month-view').removeClass('week-view').addClass('day-view'); 13646 jPerLabel.text('Day'); 13647 13648 jhead.find('#view-period-daily').prop('checked', true); 13649 //jhead.find('.monthpicker').addClass('hide'); //css 13650 //jhead.find('#Start_d, #End_d').removeClass('hide'); //css 13651 //jhead.find('#week-start-help').addClass('hide'); //css 13652 } else if (period === 'week' || period === 'weekly') { 13653 j.removeClass('month-view').removeClass('day-view').addClass('week-view'); 13654 jPerLabel.text('Week'); 13655 13656 jhead.find('#view-period-weekly').prop('checked', true); 13657 //jhead.find('.monthpicker').addClass('hide'); //#Start_Month_d, #End_Month_d 13658 //jhead.find('#Start_Week_d, #End_Week_d').removeClass('hide'); 13659 //jhead.find('#week-start-help').removeClass('hide'); 13660 } else { 13661 j.removeClass('day-view').removeClass('week-view').addClass('month-view'); 13662 jPerLabel.text('Month'); 13663 13664 jhead.find('#view-period-monthly').prop('checked', true); 13665 //jhead.find('#Start_Week_d, #End_Week_d').addClass('hide'); 13666 //jhead.find('.monthpicker').removeClass('hide'); 13667 //jhead.find('#week-start-help').addClass('hide'); 13668 } 13669 13670 if (isDisplayEndDate) { 13671 jend.removeClass('hide'); 13672 } else { 13673 jend.addClass('hide'); 13674 } 13675 13676 if (isReload) { 13677 jhead.find('.btnSearch > a').click(); 13678 } 13679 } 13680 13681 _conStaffSumDetail.addGoalLevel = function() { 13682 var msg = _getEditGoalName('', 'Save Goal Level'); 13683 var htm = '<div id="pop-confirm-save-goals">' + msg + '</div>'; 13684 var fnSave = function() { GLO.Report.StaffSummaryDetail.editGoalConfirmed(); }; 13685 var jpop = GLO.Popup.Custom.openSimple(htm, 'Add New Goal Level', fnSave); 13686 } 13687 _conStaffSumDetail.addGoalLevelRow = function(goalId, goalName) { 13688 var period = $('#report-main').find('input[name="view-period"]:checked').val(); 13689 var trCurr = $('#report-staff-summary-detail-data tfoot .report-goal-row:last'); 13690 var trNew = trCurr.clone().attr('staff_goal_id', goalId).attr('period_vc', peri
13690od); 13691 var inputs = trNew.find('input'); 13692 13693 for (var i=0; i < inputs.length; i++) { 13694 inputs.eq(i).val(''); 13695 } 13696 13697 _setGoalName(trNew, null, goalName); 13698 trCurr.after(trNew); 13699 13700 trCurr.next().find('input').on('change', function() { 13701 $(this).closest('tr').find('.btnEditGoals').addClass('btn-has-change'); 13702 }); 13703 } 13704 _conStaffSumDetail.editGoal = function(btn) { 13705 GLO.Popup.close($('#pop-confirm-save-goals').closest('.glopop')); 13706 13707 var jrpt = $('#report-staff-summary-detail-data'); 13708 var tfoot = jrpt.find('tfoot'); 13709 var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl')); 13710 13711 if (btn && $(btn).length) { 13712 var tr = $(btn).closest('tr'); 13713 } 13714 13715 if (tr.length === 0) { 13716 tr = tfoot.find('tr'); 13717 } 13718 13719 var goalId = tr.attr('staff_goal_id'); 13720 var goalName = _getGoalName(tr, isSingleStaff); 13721 var hasChange = tr.find('.btnEditGoals').hasClass('btn-has-change'); 13722 //var h1 = _editGoalHeader(goalId, goalName, isSingleStaff, isChangePreset, hasChange); 13723 13724 if (isSingleStaff) { 13725 var h1 = 'Update Goals'; 13726 var msg = _editGoalsForStaffHtm(tr, goalId, goalName, hasChange); 13727 } else { 13728 var h1 = 'Update Goal Level: ' + goalName; 13729 var msg = _editGoalLevelHtm(tr, goalId, goalName, hasChange); 13730 } 13731 13732 var htm = '<div id="pop-confirm-save-goals" staff_goal_id="' + UTIL.cleanString(goalId) + '">' + msg + '</div>'; 13733 var fnSave = function() { GLO.Report.StaffSummaryDetail.editGoalConfirmed(goalId); }; 13734 var jpop = GLO.Popup.Custom.openSimple(htm, h1, fnSave); 13735 13736 jpop.find('.btnCancel').addClass('btnCenter').find('a').css({ "letter-spacing": "1px" }); 13737 13738 if (!isSingleStaff && !UTIL.isEmpty(goalId)) { 13739 jpop.find('.pop-buttons').prepend('<span class="btnDelete btnLeft"><a onclick="GLO.Report.StaffSummaryDetail.deleteGoal(' + goalId + ')">Delete</a></span>'); 13740 } 13741 } 13742 13743 _conStaffSumDetail.changeNewGoalName = function(element) { 13744 if (!UTIL.isEmpty(element.value)) { 13745 $('#pop-confirm-save-goals').find('#Create_Goal_fl').prop('checked', true); 13746 } 13747 } 13748 13749 function _getGoalName(tr, isSingleStaff) { 13750 if (UTIL.isEmpty(isSingleStaff)) { 13751 return tr.find('.column-staff, .column-period').find('b').text(); 13752 } else if (isSingleStaff) { 13753 return tr.find('.column-period').find('b').text(); 13754 } else { 13755 return tr.find('.column-staff').find('b').text(); 13756 } 13757 } 13758 function _setGoalName(tr, isSingleStaff, goalName) { 13759 if (UTIL.isEmpty(isSingleStaff)) { 13760 tr.find('.column-staff, .column-period').find('b').text(goalName); 13761 } else if (isSingleStaff) { 13762 tr.find('.column-period').find('b').text(goalName); 13763 } else { 13764 tr.find('.column-staff').find('b').text(goalName); 13765 } 13766 } 13767 13768 function _editGoalLevelHtm(tr, goalId, goalName, hasChange) { 13769 return _getEditGoalName(goalName, 'Save Goal Level'); 13770 } 13771 function _editGoalsForStaffHtm(tr, goalId, goalName, hasChange) { 13772 var sname = $('#report-header-text').find('i').text(); 13773 var ddPreset = _getPresetGoalDropDown(goalId); 13774 var htm = '', hasPreset = (!UTIL.isEmpty(ddPreset)); 13775 13776 if (hasPreset) { 13777 if (!UTIL.isEmpty(goalId)) { 13778 var input1 = '<input type="radio" name="goal-option" id="Update_Goal_fl" value="update"/>'; 13779 var msg1 = 'Update Goal Level', msg1b = 'This will update the goals for all staff that use the goal level <b>' + goalName + '</b>'; 13780 htm += _getEditGoalName(goalName, msg1, input1, msg1b, 'Goal_Name_vc', 'Update_Goal_fl', null, true); 13781 } 13782 13783 var input2 = '<input type="radio" name="goal-option" id="Goal_Switch_fl" value="switch"/>'; 13784 htm += '<div class="goal-update-container"><label for="Goal_Switch_fl">' + input2 + 'Switch Goal Level to ' + ddPreset + '</label></div>'; 13785 13786 var input3 = '<input type="radio" name="goal-option" id="Create_Goal_fl" value="new"/>'; 13787 var msg3 = 'Create New Goal Level'; 13788 htm += _getEditGoalName('', msg3, input3, '', 'New_Goal_Name_vc', 'Create_Goal_fl', 'GLO.Report.StaffSummaryDetail.changeNewGoalName(this)'); 13789 } else { 13790 if (!UTIL.isEmpty(goalId)) { 13791 var inputRemove = '<input type="radio" name="goal-option" id="Goal_Remove_fl" value="remove"/>'; 13792 htm += '<div class="goal-update-container"><label for="Goal_Remove_fl">' + inputRemove + 'Remove ' + sname + ' from ' + goalName + '</label></div>'; 13793 } 13794 13795 htm += _getEditGoalName(goalName, 'Save Goal Level'); 13796 } 13797 13798 return '<div id="pop-confirm-save-goal-choice">' + htm + '</div>'; 13799 } 13800 function _getEditGoalName(goalName, msg, radioButton, msgSmall, textid, rdoid, textOnChange, isNoHelp) { 13801 textid = UTIL.coalesce(textid, 'Goal_Name_vc'); 13802 rdoid = UTIL.coalesce(rdoid, 'Goal_Name_vc'); 13803 13804 if (!UTIL.isEmpty(textOnChange)) { 13805 textOnChange = ' onchange="' + textOnChange + '"'; 13806 } 13807 13808 var label = '<label for="' + rdoid + '" style="white-space: inherit;">' + msg + '</label>'; 13809 var css = ' style="width: 280px; letter-spacing: 1px;"'; 13810 var input = '<input id="' + textid + '" type="text" value="' + UTIL.coalesceString(goalName) + '" maxlength="100" placeholder="Name of Goal Level"' + UTIL.cleanString(textOnChange) + css + '/>'; 13811 //var helpIcon = '<b id="help-goal-period" class="help-icon4" onclick="GLO.Report.StaffSummaryDetail.goalPeriodHelp(true)" title="Weekly or Monthly Goals?">?</b>'; 13812 13813 if (!UTIL.isEmpty(msgSmall)) { 13814 msgSmall = '<small>' + msgSmall + '</small>'; 13815 } 13816 13817 if (isNoHelp) { 13818 var htmPeriod = ''; 13819 } else { 13820 var htmPeriod = _conStaffSumDetail.goalPeriodHelp(false); 13821 } 13822 13823 return '<div><div class="goal-update-container">' + UTIL.coalesceString(radioButton) + label + input + UTIL.cleanString(msgSmall) + '</div>' + htmPeriod + '</div>'; 13824 } 13825 _conStaffSumDetail.goalPeriodHelp = function(isPopup) { 13826 var currentPeriod = 'Monthly'; 13827 13828 if ($('#view-period-weekly').prop('checked')) { currentPeriod = 'Weekly'; } 13829 13830 var htmPeriodCurrent = '<div id="pop-help-goal-period-current"><label>Current Period</label> <b>' + currentPeriod + '</b> <small>(so saving goals as ' + currentPeriod + ')</small></div>'; 13831 var h4 = '<h5>Can setup Weekly or Monthly Goals</h5>'; 13832 var msg1 = 'When change report period between weekly and monthly, the goals are automatically adjusted by a <b>1/4.25 ratio between week/month</b>'; 13833 var msg2 = 'When change report period between weekly and daily, the goals are automatically adjusted by a <b>1/7 ratio between day/week</b>'; 13834 var htm = '<div id="pop-help-goal-period">' + h4 + htmPeriodCurrent + '<p>' + msg1 + '</p><p>' + msg2 + '</p></div>'; 13835 13836 if (isPopup) { 13837 GLO.Popup.Info.open(htm, 'Setup Goals'); 13838 } else { 13839 return htm; 13840 } 13841 } 13842 function _getPresetGoalDropDown(goalId) { 13843 var dd = '<select id="Preset_Goal_id" onchange="GLO.Report.StaffSummaryDetail.selectPresetGoal(event, this)"> <option value="">(none)</option>'; 13844 var liPreset = $('#preset-goal-list').find('li'); 13845 13846 if (liPreset.length === 0) { return ''; } 13847 13848 for (var i=0; i < liPreset.length; i++) { 13849 var selected = '', id = liPreset.eq(i).attr('id'); 13850 13851 if (id == goalId) { selected = ' selected="selected"'; } 13852 13853 dd += '<option value="' + id + '"' + selected + '>
13853' + liPreset.eq(i).text() + '</option>'; 13854 } 13855 13856 return dd + '</select>'; 13857 } 13858 13859 _conStaffSumDetail.gotoGoalReport = function(element, event, staffid) { 13860 var uri = 'report/StaffGoal?sfilter=' + staffid; 13861 13862 if ($('#view-period-weekly').prop('checked')) { 13863 uri += '&period=week'; 13864 } 13865 13866 GLO.Uri.gotoUriWithSpinner(uri, element, event); 13867 } 13868 13869 _conStaffSumDetail.selectPresetGoal = function(event, element) { 13870 var jgoal = $(element).find('option:selected'); 13871 var goalId = jgoal.val(), goalName = jgoal.text(); 13872 13873 if (!UTIL.isEmpty(goalId)) { 13874 var msg = '<p>Use Goal Level ' + goalName + '?</p>'; 13875 var h1 = goalName; 13876 } else { 13877 var msg = 'Remove Goals for this Staff?'; 13878 var h1 = 'No Goals for Staff'; 13879 } 13880 13881 var fnYes = function() { //= use this wrapper because by default GLO.Popup.Confirm passes popup html to function. 13882 var jpop = $('#pop-confirm-save-goals').closest('.glopop'); 13883 jpop.find('#Goal_Switch_fl').prop('checked', true); 13884 _conStaffSumDetail.editGoalConfirmed(); 13885 }; 13886 13887 GLO.Popup.Confirm.open(msg, h1, fnYes); 13888 } 13889 13890 _conStaffSumDetail.deleteGoal = function(goalId) { 13891 var htm = '<div id="pop-confirm-delete-goal">Are you sure you want to delete this goal level?</div>'; 13892 var fnSave = function() { 13893 GLO.Report.StaffSummaryDetail.deleteGoalConfirmed(goalId); 13894 } 13895 13896 GLO.Popup.Confirm.open(htm, 'Confirm Delete Preset Goal Level', fnSave); 13897 } 13898 _conStaffSumDetail.deleteGoalConfirmed = function(goalId) { 13899 GLO.Popup.close($('#pop-confirm-delete-goal').closest('.glopop')); 13900 13901 var tfoot = $('#report-staff-summary-detail-data tfoot'); 13902 var tr = tfoot.find('tr[staff_goal_id="' + goalId + '"]'); 13903 var url = GLO.Link.WebsiteDomain + 'report/StaffGoalDelete?goalid=' + goalId; 13904 var jpop = $('#pop-confirm-save-goals').closest('.glopop'); 13905 var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl')); 13906 var goalName = _getGoalName(tr, isSingleStaff); 13907 13908 GLO.UI.Form.beginProcessing(tr.find('.btnEditGoals')); 13909 GLO.UI.Form.beginProcessing(jpop.find('.btnDelete')); 13910 13911 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 13912 .success(function(data, textStatus, jqXHR) { 13913 GLO.UI.Form.resetProcessing(); 13914 GLO.Popup.close(jpop); 13915 GLO.Popup.Success.open('Preset Goal Level ' + goalName + ' Deleted', 'Goal Level Delete'); 13916 13917 if (isSingleStaff) { 13918 _setGoalName(tr, isSingleStaff, 'Goals'); 13919 tr.attr('staff_goal_id', ''); 13920 } else { 13921 tr.remove(); 13922 } 13923 }) 13924 .error(function(jqXHR, textStatus, errorThrown) { 13925 GLO.UI.Form.resetProcessing(); 13926 GLO.Popup.Error.open('<div><p>Unable to delete staff goals</p><p>Please try again</p></div>', 'Delete Goals'); 13927 }); 13928 } 13929 13930 function _getGoalRow(goalId) { 13931 var tr = $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row'); 13932 13933 if (tr.length === 1) { 13934 return tr; 13935 } else { 13936 if (!UTIL.isEmpty(goalId)) { 13937 return $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row[staff_goal_id = "' + goalId + '"]'); 13938 } 13939 13940 for (var i=0; i < tr.length; i++) { 13941 if (tr.eq(i).find('.btnEditGoals.btnProcessing4').length) { 13942 return tr.eq(i); 13943 } 13944 } 13945 } 13946 } 13947 13948 function _removeAndResetStaffGoals(goalId) { 13949 var trRemove = _getGoalRow(goalId).removeAttr('staff_goal_id').attr('period_vc', 'week'); 13950 var jinput = trRemove.find('input'); 13951 13952 trRemove.find('.column-period b').text('Goals'); 13953 13954 for (var i=0; i < jinput.length; i++) { 13955 jinput.eq(i).val(''); 13956 } 13957 } 13958 13959 function _isValidGoalEdit(jpop, rdoList, rdoVal, goalName) { 13960 if (rdoList.length > 0) { 13961 if (UTIL.isEmpty(rdoVal)) { 13962 var htm = '<p>Please select the whether you want to update:</p><ul>' 13963 + '<li>The Goal Level: ' + goalName + '</li>' 13964 + '<li>Creat a New Goal Level</li>' 13965 + '<li>Switch Staff to Different Goal Level</li>' 13966 + '<li>Remove Goal Level from Staff</li>' 13967 + '</ul>'; 13968 13969 GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">' + htm + '</div>', 'How Update Staff Goals?'); 13970 return false; 13971 } else if (rdoVal == 'update' && UTIL.isEmpty(goalName)) { 13972 var fn = function() { jpop.find('#Goal_Name_vc').focus(); }; 13973 GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn); 13974 return false; 13975 } else if (rdoVal == 'new' && UTIL.isEmpty(jpop.find('#New_Goal_Name_vc').val())) { 13976 var fn = function() { jpop.find('#New_Goal_Name_vc').focus(); }; 13977 GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn); 13978 return false; 13979 } 13980 } else if (UTIL.isEmpty(goalName)) { 13981 var fn = function() { jpop.find('#Goal_Name_vc').focus(); }; 13982 GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn); 13983 return false; 13984 } 13985 13986 return true; 13987 } 13988 13989 _conStaffSumDetail.editGoalConfirmed = function(goalId) { 13990 var jrpt = $('#report-main'); 13991 var jRptData = jrpt.find('.report-container'); 13992 13993 var jpop = $('#pop-confirm-save-goals').closest('.glopop'); 13994 var rdoList = jpop.find('input[name="goal-option"]'), rdoVal = jpop.find('input[name="goal-option"]:checked').val(); 13995 var goalName = jpop.find('#Goal_Name_vc').val(); 13996 13997 if (!_isValidGoalEdit(jpop, rdoList, rdoVal, goalName)) { return; } 13998 13999 if (rdoList.length === 0 && UTIL.isEmpty(goalId)) { //= simple create 14000 var tr = null, jd = { "goal_name_vc": goalName, "updatetype": "create-simple" }; 14001 } else if ((rdoList.length === 0 && !UTIL.isEmpty(goalId)) || rdoVal === 'update') { //= update 14002 var tr = _getGoalRow(goalId); 14003 var jd = _getGoals(tr, goalId, goalName, "update"); 14004 } else if (rdoVal === 'new') { //= copy existing + create 14005 goalName = jpop.find('#New_Goal_Name_vc').val(); 14006 var tr = _getGoalRow(goalId); 14007 goalId = ''; 14008 var jd = _getGoals(tr, goalId, goalName, 'create-copy'); 14009 } else if (rdoVal === 'switch') { //= switch staff to different (existing) goal level/ 14010 goalId = jpop.find('#Preset_Goal_id').val(); 14011 goalName = jpop.find('#Preset_Goal_id option:selected').text(); 14012 14013 var tr = _getGoalRow(goalId); 14014 var jd = { "goal_id": goalId, "updatetype": "switch" }; 14015 } else if (rdoVal === 'remove') { //= remove 14016 goalName = goalId = ''; 14017 _removeAndResetStaffGoals(goalId); 14018 var tr = null, jd = { "goal_name_vc": goalName, "updatetype": "remove" }; 14019 } else { //= error 14020 GLO.Log.insertSimple('Update Goal Level Error', 'goal id = ' + goalId + '; ' + goalName, 'error'); 14021 GLO.Popup.Warning('Error Updating Staff Level', 'Update Staff Level'); 14022 return; 14023 } 14024 14025 var period = jrpt.find('input[name="view-period"]:checked').val(); 14026 14027 if (!GLO.Report.hasReportPassword(jd)) { 14028 return; 14029 } else if (tr && tr.length) {
14030 GLO.UI.Form.beginProcessing(tr.find('.btnEditGoals')); 14031 tr.attr('period_vc', period); 14032 } 14033 14034 var jdts = _getDateRange(jrpt); 14035 var start = UTIL.fromSADate(jdts.start, true, true), end = UTIL.fromSADate(jdts.end, true, true); 14036 var url = _getGoalSearchUrl(jrpt, period, start, end, true) + '&ispartial=1'; 14037 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 14038 14039 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 14040 .success(function(data, textStatus, jqXHR) { 14041 GLO.UI.Form.resetProcessing(); 14042 GLO.Popup.closeIfExist($('#pop-warn-save-goal, #report-password-container').closest('.glopop')); 14043 14044 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 14045 var jpopPIN = GLO.Popup.Custom.openSimple('<div id="pop-warn-save-goal">' + data + '</div>', 'Enter PIN / Password'); 14046 jpopPIN.find('.pop-buttons-parent').remove(); 14047 return; 14048 } 14049 14050 GLO.Popup.close(jpop); 14051 GLO.Popup.Success.open('Goals Saved', 'Staff Goals'); 14052 14053 if (UTIL.parseBool(jd.updatetype === 'switch')) { 14054 _loadData(jRptData, data); 14055 } else { 14056 var gid = UTIL.coalesceInt($(data).attr('goal_id'), jd.goal_id); 14057 var gname = UTIL.coalesceString(goalName, 'Goals'); 14058 14059 if (tr && tr.length) { 14060 _setGoalName(tr, null, gname); 14061 tr.attr('staff_goal_id', gid); 14062 tr.find('.btnEditGoals').removeClass('btn-has-change'); 14063 } else if (jd.updatetype === "create-simple") { 14064 _conStaffSumDetail.addGoalLevelRow(gid, gname); 14065 } 14066 14067 _loadGoalCss(true); 14068 } 14069 }) 14070 .error(function(jqXHR, textStatus, errorThrown) { 14071 GLO.UI.Form.resetProcessing(); 14072 GLO.Popup.Error.open('<div><p>Unable to save staff goals</p><p>Please try again</p></div>', 'Save Goals'); 14073 }); 14074 } 14075 14076 function _getGoals(tr, goalId, goalName, updateType) { 14077 var jd = { "goal_id": goalId, "goal_name_vc": goalName, "updatetype": updateType 14078 , "client_nr": tr.find('.column-count-client input').val(), "service_nr": tr.find('.column-count-service input').val(), "product_nr": tr.find('.column-count-product input').val() 14079 , "service_mn": tr.find('.column-sales-total-service input').val(), "tip_mn": tr.find('.column-sales-total-tip input').val() 14080 , "product_mn": tr.find('.column-sales-total-product input').val(), "ps_ratio_pct": tr.find('.column-product-to-service input').val() 14081 14082 , "request_pct": tr.find('.column-service-request input').val(), "existing_pct": tr.find('.column-existing input').val() 14083 , "pre_book_pct": tr.find('.column-pre-book input').val() 14084 14085 , "day_worked_nr": tr.find('.column-days-worked input').val(), "available_per_day_nr": tr.find('.column-hours-available input').val() 14086 , "booked_per_day_nr": tr.find('.column-hours-worked input').val(), "booked_pct": tr.find('.column-hours-worked-percent input').val() 14087 14088 , "ticket_avg_mn": tr.find('.column-ticket-avg-total input').val() 14089 , "ticket_service_avg_mn": tr.find('.column-ticket-avg-service input').val(), "ticket_product_avg_mn": tr.find('.column-ticket-avg-product input').val() 14090 14091 , "ticket_per_day": tr.find('.column-daily-avg-ticket-count input').val() 14092 , "service_per_day": tr.find('.column-daily-avg-service-sales input').val(), "product_per_day": tr.find('.column-daily-avg-product-sales input').val() 14093 }; 14094 14095 return jd; 14096 } 14097 14098 _conStaffSumDetail.monthToDate = function(moyr, isStart) { 14099 var monthAndYear = moyr.split('/'); 14100 var mo = monthAndYear[0], yr = monthAndYear[1]; 14101 var dtStart = new Date(mo + '/1/' + yr); 14102 14103 if (isStart) { 14104 return dtStart; 14105 } else { 14106 return new Date(dtStart.setMonth(dtStart.getMonth() + 1)).addDays(-1); 14107 } 14108 } 14109 14110 function _getDateRange(jrpt) { 14111 var end = '', jend = jrpt.find('#report-search-header-dates .end-cell'); 14112 14113 if (jrpt.find('#view-period-daily').prop('checked')) { 14114 var period = 'day'; 14115 var start = jrpt.find('#Start_d').val(); 14116 14117 if (jend.is(':visible')) { 14118 end = jrpt.find('#End_d').val(); 14119 } else { 14120 end = start; 14121 } 14122 } else if (jrpt.find('#view-period-weekly').prop('checked')) { 14123 var period = 'week'; 14124 var start = jrpt.find('#Start_Week_d').val(); 14125 14126 if (jend.is(':visible')) { 14127 end = jrpt.find('#End_Week_d').val(); 14128 } else { 14129 end = new Date(start).addDays(7); 14130 } 14131 } else { 14132 var period = 'month'; 14133 var start = _conStaffSumDetail.monthToDate(jrpt.find('#Start_Month_d').val(), true); 14134 14135 if (jend.is(':visible')) {
14136 end = _conStaffSumDetail.monthToDate(jrpt.find('#End_Month_d').val(), false); 14137 } 14138 } 14139 14140 return { "start": start, "end": end, "period": period } 14141 } 14142 function _getCurrentChartArray(jRptData) { 14143 var arr = [], checkedList = jRptData.find('tr.display-chart-row').find(':checked'); 14144 14145 for (var i=0; i < checkedList.length; i++) { 14146 arr.push(checkedList.eq(i).closest('td').index()); 14147 } 14148 14149 return arr; 14150 } 14151 function _loadData(jRptData, data) { 14152 var arrChartList = _getCurrentChartArray(jRptData); 14153 14154 if (data) { 14155 jRptData.html(data); 14156 } 14157 14158 UI.initTableSorter2(jRptData.find('table.tablesorter'), [0,0]); 14159 _initHideEmptyColumns(); 14160 14161 jRptData.find('tbody tr:odd').addClass('EveryOtherRowQuiet'); 14162 GLO.Report.CellSummary.initReport(jRptData, true, true); 14163 14164 _initGoals(jRptData); 14165 _loadPeriod(); 14166 _displayEndDate(jRptData); 14167 14168 var cssThrobber = 'position: relative; height: 160px; z-index: 9;' 14169 var blueThrobber = '<div id="throbber-loading-report-charts" style="margin-top: 140px; height: 60px;">' + GLO.Report.Template2.getBlueThrobber(cssThrobber) + '</div>'; 14170 14171 $('.report-chart-container').html(blueThrobber); 14172 setTimeout(GLO.Report.StaffSummaryDetail.initComplete, 4900); //= in case there is an error later -> ensure blue throbber is removed 14173 14174 setTimeout(function() { 14175 _initChart0(arrChartList); 14176 }, 900); 14177 } 14178 function _initHideEmptyColumns() { 14179 var j = $('#report-staff-summary-detail-data'); 14180 var jtimeHeader = j.find('thead #staff-goal-header-hours-per-day'); 14181 14182 if (GLO.Report.Template.hideEmptyColumn(j, 'column-hours-sick')) { 14183 var colspan = parseInt(jtimeHeader.attr('colspan')) - 1; 14184 jtimeHeader.attr('colspan', colspan); 14185 14186 if (colspan < 3) { 14187 jtimeHeader.addClass('narrow-cell'); 14188 } 14189 } 14190 if (GLO.Report.Template.hideEmptyColumn(j, 'column-hours-vacation')) { 14191 var colspan = parseInt(jtimeHeader.attr('colspan')) - 1; 14192 jtimeHeader.attr('colspan', colspan); 14193 14194 if (colspan < 3) { 14195 jtimeHeader.addClass('narrow-cell'); 14196 } 14197 } 14198 14199 if (GLO.Report.Template.hideEmptyColumn(j, 'column-count-product')) { 14200 var jh = j.find('thead #staff-goal-header-count'); 14201 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14202 } 14203 14204 if (GLO.Report.Template.hideEmptyColumn(j, 'column-product-to-service')) { 14205 var jh = j.find('thead #staff-goal-header-sales'); 14206 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14207 } 14208 if (GLO.Report.Template.hideEmptyColumn(j, 'column-sales-total-product')) { 14209 var jh = j.find('thead #staff-goal-header-sales'); 14210 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14211 } 14212 if (GLO.Report.Template.hideEmptyColumn(j, 'column-sales-total-commission')) { 14213 var jh = j.find('thead #staff-goal-header-sales'); 14214 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14215 } 14216 14217 if (GLO.Report.Template.hideEmptyColumn(j, 'column-ticket-avg-product')) { 14218 var jh = j.find('thead #staff-goal-header-average-ticket'); 14219 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14220 } 14221 14222 if (GLO.Report.Template.hideEmptyColumn(j, 'column-daily-avg-product-sales')) { 14223 var jh = j.find('thead #staff-goal-header-average-daily'); 14224 jh.attr('colspan', parseInt(jh.attr('colspan')) - 1); 14225 } 14226 } 14227 14228 function _displayEndDate(jRptData) { 14229 var tfoot = jRptData.find('tfoot'); 14230 var isBizLevel = UTIL.parseBool(tfoot.attr('is_business_level')); 14231 var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl')); 14232 var jend = $('#staff-summary-detail-header').find('.date-cell.end-cell'); 14233 14234 if (!isBizLevel) { 14235 _loadGoalCss(); 14236 } 14237 14238 if (isSingleStaff || isBizLevel) { 14239 jend.removeClass('hide'); 14240 } else { 14241 jend.addClass('hide'); 14242 //$('#report-staff-summary-detail-data').find('thead th.column-staff').click(); 14243 } 14244 } 14245 function _initChart0(arrChartList) { 14246 google.charts.load('current', {'packages':['bar']}); 14247 google.charts.setOnLoadCallback(function() { GLO.Report.StaffSummaryDetail.initChart(arrChartList); }); 14248 } 14249 function _getLegendColors() { 14250 var arrColors = [], jcolors = $('.gchart:first svg g:first').find('rect'); 14251 14252 for (var i=1; i < jcolors.length - 1; i++) { 14253 arrColors.push(jcolors.eq(i).attr('fill')); 14254 } 14255 14256 return arrColors; 14257 } 14258 function _getLegend(jrpt) { 14259 var lastRowLabel = null, tfoot = jrpt.find('tfoot'); 14260 var isBizLevel = UTIL.parseBool(tfoot.attr('is_business_level'));
14261 var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl')); 14262 14263 if (isSingleStaff || isBizLevel) { 14264 if (isSingleStaff) { 14265 lastRowLabel = 'Goal'; 14266 } 14267 14268 var arrLegend = _legendArray(jrpt, 'column-period', lastRowLabel); 14269 } else { 14270 var arrLegend = _legendArray(jrpt, 'column-staff'); 14271 } 14272 14273 return arrLegend; 14274 } 14275 function _createChartsOnLoadAfterPageLoad(jrpt) { 14276 if (jrpt.find('#view-period-daily').prop('checked')) { return; } 14277 14278 var arrLegend = _getLegend(jrpt); 14279 var chartWidth = _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-service', 'Total Service Sales', 'Services Sales: Actual vs Goal', '', null, 'currency'); 14280 var chartCount = (innerWidth - 200) / (chartWidth + 120); 14281 14282 if (chartCount > 2) { 14283 setTimeout(function() { //= give first chart time to load so can re-used legend colors 14284 var arrColors = _getLegendColors(); 14285 _preLoadCharts(chartCount, arrLegend, jrpt, arrColors); 14286 }, 600); 14287 } 14288 14289 return chartCount; 14290 } 14291 function _preLoadCharts(chartCount, arrLegend, jrpt, arrColors) { 14292 // if (GLO.Data.provider.industry_cd == 8) { 14293 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-ticket-avg-total', 'Average Ticket', 'Average product and service', '', arrColors, 'currency'); 14294 14295 if (chartCount >= 3) { 14296 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-count-ticket', 'Ticket Count', 'Number of Tickets', '', arrColors, 'long'); 14297 } 14298 if (chartCount >= 4) { 14299 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-days-worked', 'Days Worked', 'Days Worked: Actual vs Goal', '', arrColors, 'long'); 14300 } 14301 if (chartCount >= 5) { 14302 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-hours-worked', '% Booked', 'Hours Booked / Hours Available', '', arrColors, 'percent'); 14303 } 14304 if (chartCount >= 6) { 14305 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-daily-avg-service-sales', 'Daily Services', 'Daily Average Service Sales', '', arrColors, 'currency'); 14306 } 14307 if (chartCount >= 7) { 14308 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-tip', 'Service Tips', 'Total Service Tips', '', arrColors, 'currency'); 14309 } 14310 if (chartCount >= 8) { 14311 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-product-to-service', 'Product:Service Sales', 'Ratio of Product to Service Sales', '', arrColors, 'currency'); 14312 } 14313 if (chartCount >= 9) { 14314 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-service-request', 'Client Request', 'Requested by Client', '', arrColors, 'currency'); 14315 } 14316 if (chartCount >= 10) { 14317 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-pre-book', 'Client Pre-Booked', 'appointment booked before/during last appointment', '', arrColors, 'currency'); 14318 } 14319 if (chartCount >= 11) { 14320 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-existing', 'Client Existing', '% of tickets with existing client', '', arrColors, 'currency'); 14321 } 14322 if (chartCount >= 12) { 14323 _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-product', 'Total Product Sales', 'Product Sales: Actual vs Goal', '', arrColors, 'currency'); 14324 } 14325 } 14326 function _createChartsOnLoadDataAfterSearch(arrChartList) { 14327 var tds = $('#report-staff-summary-detail-data').find('tr.display-chart-row').find('td'); 14328 14329 for (var i=0; i < arrChartList.length; i++) { 14330 var td = tds.eq(arrChartList[i]); 14331 var columnClass = _getColumnClass(td); 14332 14333 td.find(':checkbox').prop('checked', true); 14334 _drawChart0(td, columnClass); 14335 } 14336 14337 return arrChartList.length; 14338 } 14339 function _createChartsOnLoadFromUrl(displayCharts) { 14340 var chartCount = 0, arrChart = displayCharts.split(','); 14341 var tr = $('#report-staff-summary-detail-data').find('tr.display-chart-row'); 14342 14343 for (var i=0; i < arrChart.length; i++) { 14344 //tr.find('.column-' + arrChart[i]).find(':checkbox').prop('checked', true).change(); //change event not yet wired 14345 14346 var columnClass = 'column-' + arrChart[i]; 14347 var td = tr.find('.' + columnClass); 14348 14349 if (td.length) { 14350 td.find(':checkbox').prop('checked', true); 14351 _drawChart0(td, columnClass); 14352 ++chartCount; 14353 } 14354 } 14355 14356 return chartCount; 14357 } 14358 _conStaffSumDetail.initChart = function(arrChartList) { 14359 //var arrColors = _loadChartColors(jrpt); google charts does a better job of generating colors 14360 //var label = _getChartLabel(jrpt); chart looks better without label 14361 var jrpt = $('#report-main'); 14362 jrpt.find('thead input[type="checkbox"]').prop('checked', false); 14363 14364 if (jrpt.find('table#report-staff-summary-detail-data tbody > tr').length === 0) { return; } 14365 14366 if (_isInitComplete) { 14367 if (jrpt.find('#view-period-daily').prop('checked')) { 14368 var chartCount = 0; 14369 } else { 14370 var chartCount = _createChartsOnLoadDataAfterSearch(arrChartList); 14371 } 14372 } else { 14373 var displayCharts = UTIL.cleanString(GLO.Uri.url('chart')).toLowerCase(); 14374 14375 if (!UTIL.isEmpty(displayCharts)) { 14376 var chartCount = _createChartsOnLoadFromUrl(displayCharts); 14377 } else { 14378 var chartCount = _createChartsOnLoadAfterPageLoad(jrpt); 14379 } 14380 14381 _isInitComplete = true; 14382 } 14383 14384 if (chartCount > 0) { 14385 setTimeout(GLO.Report.StaffSummaryDetail.initComplete, 900); 14386 } else { 14387 _conStaffSumDetail.initComplete(); 14388 } 14389 } 14390 _conStaffSumDetail.initComplete = function() { 14391 var jrpt = $('#report-main'); 14392 jrpt.find('#throbber-loading-report-charts').remove();
14393 jrpt.find('thead tr.display-chart-row').find('input[type="checkbox"]').change(GLO.Report.StaffSummaryDetail.displayColumnChart); 14394 } 14395 function _getColumnClass(td) { 14396 var columnClass = td.attr('class').replace('sorter-false', '').replace('left-column', '').replace('right-column', ''); 14397 columnClass = columnClass.replace('column-count', '').replace('column-sales-total', '').replace('column-client', ''); 14398 columnClass = columnClass.replace('column-hours', '').replace('column-time', '').replace('column-ticket-avg', '').replace('column-daily-avg', ''); 14399 return $.trim(columnClass); 14400 } 14401 _conStaffSumDetail.displayColumnChart = function(event) { 14402 var isDisplayChart = $(this).prop('checked'); 14403 var td = $(this).closest('td'); 14404 var columnClass = _getColumnClass(td); 14405 14406 $('.report-chart-container').find('.gchart.' + columnClass).remove(); 14407 14408 if (isDisplayChart) { 14409 _drawChart0(td, columnClass); 14410 } 14411 } 14412 14413 function _getChartSubTitle(subtitle) { 14414 if ($('#staff-summary-detail-header #filter-per-period').prop('checked')) { 14415 if (subtitle.toLowerCase().indexOf('goal') !== -1) { 14416 return ''; 14417 } 14418 } 14419 14420 return subtitle; 14421 } 14422 function _drawChart0(td, columnClass) { 14423 var fmt = td.find(':checkbox').attr('chart_format'); 14424 var title = td.attr('title'); 14425 var subtitle = UTIL.coalesceString(td.attr('subtitle'), ''); 14426 14427 var jrpt = $('#report-main'); 14428 var arrLegend = _getLegend(jrpt); 14429 var arrColors = _getLegendColors(); 14430 14431 _conStaffSumDetail.drawChart(arrLegend, jrpt, columnClass, title, subtitle, '', arrColors, fmt); 14432 } 14433 _conStaffSumDetail.drawChart = function(legendArray, jrpt, columnClass, title, subtitle, label, colors, format) { 14434 jrpt.find('thead td.' + columnClass + ' input[type="checkbox"]').prop('checked', true); 14435 format = UTIL.coalesce(format, "decimal"); 14436 subtitle = _getChartSubTitle(subtitle); 14437 14438 var td = jrpt.find('tbody td.' + columnClass + ', tfoot tr.report-goal-row-single td.' + columnClass); 14439 var arr = [], height = 300, width = 100 + parseInt(td.length * 20), maxWidth = parseInt(innerWidth * .9); 14440 14441 if (maxWidth > 700) { height = 400; } 14442 14443 if (format === 'percent') { //Feb 2020 -> google charts appears to have a bug sometimes when display percents as bar chart values 14444 format = 'long' 14445 } 14446 14447 var options = { 14448 chart: { title: title, subtitle: subtitle }, 14449 bars: "vertical", 14450 vAxis: { format: format }, 14451 width: width, height: height 14452 //, colors: arrColors //, colors: ['#d95f02', '#6bee97', '#7570b3', '#1b9e77'] 14453 }; 14454 14455 if (legendArray.length > 10) { 14456 options.legend = { "position": "none" }; 14457 } else if (colors && colors.length > 0) { 14458 options.colors = colors; 14459 options.legend = { "position": "none" }; 14460 //options.legend = { "position": "top", "textStyle": { "fontSize": 11 }}; 14461 } else { 14462 options.width += 120; 14463 options.legend = { "position": "left" }; 14464 } 14465 14466 if (options.width > maxWidth) { options.width = maxWidth; } 14467 14468 arr.push(legendArray); 14469 _addChart(title, td, arr, format); 14470 var data = google.visualization.arrayToDataTable(arr); 14471 14472 var jcontainer = $('.report-chart-container'); 14473 var chartid = 'chart' + (jcontainer.find('.gchart').length + 1); 14474 jcontainer.append('<div id="' + chartid + '" class="gchart ' + columnClass + '"></div>'); 14475 14476 var chart = new google.charts.Bar(document.getElementById(chartid)); 14477 chart.draw(data, google.charts.Bar.convertOptions(options)); 14478 return width; 14479 } 14480 function _legendArray(jrpt, columnClass, extraLegendItem, label) { 14481 var arr = []; 14482 var td = jrpt.find('tbody td.' + columnClass + ', tfoot tr.report-goal-row-single td.' + columnClass); 14483 14484 arr.push(UTIL.coalesceString(label, '')); 14485 14486 for (var i=0; i < td.length - 1; i++) { 14487 if (td.eq(i).is(':visible')) { // && td.eq(i).closest('tr').attr('id') !== 'report-goal-total' 14488 arr.push(_getLegendLabel(td.eq(i))); 14489 } 14490 } 14491 14492 if (extraLegendItem) { 14493 arr.push(extraLegendItem); 14494 } else if (td.eq(i).is(':visible')) { 14495 arr.push(_getLegendLabel(td.eq(i))); 14496 } 14497 14498 return arr; 14499 } 14500 function _getLegendLabel(td) { 14501 var nm = UTIL.directTagOnly(td); 14502 14503 if (UTIL.isEmpty(nm)) { 14504 nm = UTIL.directTagOnly(td.find('small')); 14505 14506 if (UTIL.isEmpty(nm)) { 14507 nm = UTIL.directTagOnly(td.next()); 14508 } 14509 } 14510 14511 return nm; 14512 } 14513 function _loadChartColors(jrpt) {
14514 var tdPeriod = jrpt.find('td.column-period'); 14515 var arrColor = []; 14516 14517 for (var i=1; i < tdPeriod.length; i++) { 14518 arrColor.push(UI.getHexColor()); 14519 } 14520 14521 return arrColor; 14522 } 14523 function _addChart(label, td, arr, fmt) { 14524 var arr1 = []; 14525 arr1.push(' '); //arr1.push(label); 14526 14527 for (var i=0; i < td.length-1; i++) { 14528 if (td.eq(i).is(':visible')) { 14529 var amt = UTIL.coalesceMoney(td.eq(i).text().replace('$', '').replace(',', '').replace('%', '')); 14530 14531 if (UTIL.isNumber(amt) && amt > 1 && fmt == 'percent') { 14532 amt = UTIL.coalesceMoney(amt/100); 14533 } 14534 14535 arr1.push(amt); 14536 } 14537 } 14538 14539 if (td.eq(i).is(':visible')) { 14540 var jinput = td.eq(i).find('input'); 14541 14542 if (jinput.length) { 14543 var amt = UTIL.coalesceMoney(jinput.val().replace('$', '').replace(',', '').replace('%', '')); 14544 14545 if (UTIL.isNumber(amt) && amt > 1 && fmt == 'percent') { 14546 amt = UTIL.coalesceMoney(amt/100); 14547 } 14548 14549 arr1.push(amt); 14550 } else { 14551 arr1.push(UTIL.coalesceMoney(td.eq(i).text().replace('$', '').replace(',', '').replace('%', ''))); 14552 } 14553 } 14554 14555 arr.push(arr1); 14556 } 14557 function _getChartLabel(jrpt) { 14558 if ($('#view-period-weekly').prop('checked')) { 14559 var period = 'Week'; 14560 } else { 14561 var period = 'Month'; 14562 } 14563 14564 if (jrpt.find('.column-staff').length > 0) { //= is single staff 14565 var label = 'Staff'; 14566 } else { 14567 var label = period; 14568 } 14569 14570 return label; 14571 } 14572 _conStaffSumDetail.changeToSetupGoal = function() { 14573 var btn = $('#staff-goal-change-to-setup .btnEditGoals'); 14574 GLO.UI.Form.beginProcessing(btn); 14575 $('#staff-summary-detail-header #filter-per-staff').prop('checked', true); 14576 _conStaffSumDetail.search(); 14577 } 14578 function _getGoalSearchUrl(jrpt, period, start, end, isSave) { 14579 var qstring = 'sfilter=' + GLO.Uri.url('sfilter') + '&period=' + period; 14580 14581 if (UTIL.isDate(start)) { 14582 qstring += '&start=' + new Date(start).toGloDate(true); 14583 } 14584 14585 if (UTIL.isDate(end)) { 14586 qstring += '&end=' + new Date(end).toGloDate(true); 14587 } 14588 14589 var urlPage = 'StaffGoal'; 14590 14591 if (isSave) { 14592 urlPage = 'StaffGoalSave'; 14593 } 14594 14595 var url = GLO.Link.WebsiteDomain + 'report/' + urlPage + '?' + qstring; 14596 14597 var isPerStaff = (jrpt.find('input[name="filter-per"]:checked').val() === 'staff'); 14598 var isActiveStaffOnly = jrpt.find('#Only_Active_Staff_fl').prop('checked'); 14599 var isOnlyPaid = jrpt.find('#Only_Paid_fl').prop('checked'); 14600 var isOnlyClockedIn = jrpt.find('#Only_Clocked_In_Hours_fl').prop('checked'); 14601 14602 if (isPerStaff) { url += '&isPerStaff=1'; } 14603 if (isActiveStaffOnly) { url += '&isActiveStaffOnly=1'; } 14604 if (isOnlyPaid) { url += '&isOnlyPaid=1'; } 14605 if (isOnlyClockedIn) { url += '&isOnlyClockedIn=1'; } 14606 14607 if (jrpt.find('#filer-include-mon').prop('checked')) { url += '&mon=1'; } else { url += '&mon=0'; } 14608 if (jrpt.find('#filer-include-tue').prop('checked')) { url += '&tue=1'; } else { url += '&tue=0'; } 14609 if (jrpt.find('#filer-include-wed').prop('checked')) { url += '&wed=1'; } else { url += '&wed=0'; } 14610 if (jrpt.find('#filer-include-thu').prop('checked')) { url += '&thu=1'; } else { url += '&thu=0'; } 14611 if (jrpt.find('#filer-include-fri').prop('checked')) { url += '&fri=1'; } else { url += '&fri=0'; } 14612 if (jrpt.find('#filer-include-sat').prop('checked')) { url += '&sat=1'; } else { url += '&sat=0'; } 14613 if (jrpt.find('#filer-include-sun').prop('checked')) { url += '&sun=1'; } else { url += '&sun=0'; } 14614 14615 return url; 14616 } 14617 _conStaffSumDetail.cancelSearch = function() { 14618 UTIL.abortAjaxRequest(_searchRequest, true, true); 14619 } 14620 _conStaffSumDetail.search = function() { 14621 var jrpt = $('#report-main'); 14622 var btnSearch = jrpt.find('.btnSearch'); 14623 var jRptData = jrpt.find('.report-container'); 14624 var jd = _getDateRange(jrpt); 14625 14626 var start = UTIL.fromSADate(jd.start, true, true); 14627 var end = UTIL.fromSADate(jd.end, true, true); 14628 14629 if (GLO.Info.roleType > 219) { //= is manager, search could come from staff-filter change 14630 var sname = $('#staff-filter').find('option:selected').text(); 14631 $('#staff-summary-detail-report-header').find('i').text(sname); 14632 } else { 14633 var sname = UTIL.directTagOnly($('#staff-summary-detail-report-header').find('i')); 14634 } 14635 14636 var pageTitle = 'Goals ' + sname + ': ' + start + ' - ' + end; 14637 var url = _getGoalSearchUrl(jrpt, jd.period, start, end); 14638 14639 if (!GLO.Report.hasReportPassword(jd)) { 14640 return; 14641 } else if (btnSearch.hasClass('btnProcessing4')) { 14642 if (_searchRequest && _searchRequest.abort) { 14643 _searchRequest.abort(); 14644 } 14645 } else { 14646 GLO.UI.Form.beginProcessing(btnSearch); 14647 } 14648 14649 _searchRequest = $.ajax({ "type": "POST", "url": (url + '&ispartial=1'), "cache": false }) //, "data": jd 14650 .success(function(data, textStatus, jqXHR) { 14651 GLO.UI.Form.resetProcessing();
14652 _loadData(jRptData, data); 14653 14654 document.title = pageTitle; 14655 window.history.pushState('', '', url); 14656 14657 _completePageLoad(); 14658 }) 14659 .error(function(jqXHR, textStatus, errorThrown) { 14660 GLO.UI.Form.resetProcessing(); 14661 GLO.Popup.Error('Unable to lookup data at this time. Please try again.'); 14662 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 14663 }); 14664 } 14665 14666 function _completePageLoad() { 14667 if (!_isInitialPageLoad) { return; } 14668 14669 var hideIcon = $('#bd #report-main #report-header-help .close-icon:visible'); 14670 14671 if (hideIcon.length) { //= only auto-hide if help is visible, then still visible 1.5 seconds later (avoid auto-closing while opening which causes display icon to show back up) 14672 setTimeout(function() { 14673 $('#bd #report-main #report-header-help .close-icon:visible').click(); 14674 }, 1500); 14675 } 14676 14677 $('#report-staff-summary-detail #throbber-still-loading').remove(); 14678 _isInitialPageLoad = false; 14679 } 14680 14681 _conStaffSumDetail.exportReport = function() { 14682 //var tbody = document.getElementById('report-payroll-summary-container'); 14683 var j = $('#report-main'); 14684 var jrpt = j.find('#report-staff-summary-detail-data'); 14685 var trs = jrpt.find('tr'); 14686 var jsonDates = _getDateRange(j); 14687 14688 var fileName = 'Staff Goal Report ' + new Date(jsonDates.start).toGloDate(true) + ' - ' + new Date(jsonDates.end).toGloDate(true); 14689 GLO.Report.exportAsSpreadsheet(trs, fileName); //_exportExcel(trs, fileName); 14690 } 14691 14692 return _conStaffSumDetail; 14693})(); 14694 14695 14696GLO.ReminderPortal = (function() { 14697 function _constructor(name) { } 14698 _constructor.isReminderView = false; 14699 var isInitialized = false; 14700 14701 _constructor.init = function() { 14702 _constructor.isReminderView = true; 14703 14704 //Step I: Set Day 14705 $(window).hashchange(function() { GLO.ReminderPortal.hashNavigate(); }); 14706 14707 var dt = _constructor.getHashDate(true); 14708 _constructor.setHashDate(dt); 14709 14710 14711 //Step II: Datepicker Day Navigator 14712 $('.fc-header-title').click(function() { 14713 if ( $('#ui-datepicker-div:visible').length === 0 ) { 14714 $('#headerDatePicker').datepicker('show'); 14715 } else { 14716 $('#headerDatePicker').datepicker('hide'); 14717 } 14718 }); 14719 14720 var headerDatePicker = $('#headerDatePicker').datepicker({ 14721 buttonText: '', buttonImageOnly: true, showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showOn: 'both', showAnim: 'blind' 14722 , showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 14723 , numberOfMonths: UI.getDatepickerMonths() 14724 14725 , onSelect: function(dateText, inst) { 14726 //$('.fc-header-title .ui-datepicker-trigger').css('display', 'none'); 14727 GLO.ReminderPortal.gotoDay(dateText); 14728 } 14729 14730 , beforeShow: function(input, inst) { 14731 //$("#ui-datepicker-div").addClass('hide'); 14732 //$('.fc-header-title .ui-datepicker-trigger').css('display', 'inline'); 14733 14734 $(input).datepicker('setDate', GLO.Uri.getDate('dt')); 14735 } 14736 }); 14737 14738 $("#ui-datepicker-div").on('click', 'button.ui-datepicker-current', function() { //= click on datepicker's today button. 14739 headerDatePicker.datepicker("hide"); 14740 GLO.ReminderPortal.gotoDay(new Date().toGloDate()); 14741 }); 14742 14743 14744 //Step III: Add hover over button effects to header buttons 14745 _setupHeader(); 14746 14747 //Step IV: Shortcut Keys 14748 $(document).keydown(function(event) { 14749 if (event.ctrlKey) { 14750 switch (event.which) { 14751 case 37: //left arrow key. 14752 if (UI.hasNoPopup()) { GLO.ReminderPortal.gotoPrevDay(); } 14753 break; 14754 case 38: //up arrow key. 14755 if (UI.hasNoPopup()) { GLO.ReminderPortal.moveByDay(-
147557); } 14756 break; 14757 case 39: //right arrow key. 14758 if (UI.hasNoPopup()) { GLO.ReminderPortal.gotoNextDay(); } 14759 break; 14760 case 40: //down arrow key. 14761 if (UI.hasNoPopup()) { GLO.ReminderPortal.moveByDay(7); } 14762 break; 14763 } 14764 } 14765 14766 if (event.altKey) { 14767 if (event.which === 33) { //33: page up --> go back 1 week. 14768 var dt = GLO.ReminderPortal.getHashDate(); 14769 dt.setDate(dt.getDate() - 7); 14770 GLO.ReminderPortal.gotoDay(dt); 14771 } else if (event.which === 34) { //34: page down --> go forward 1 week. 14772 var dt = GLO.ReminderPortal.getHashDate(); 14773 dt.setDate(dt.getDate() + 7); 14774 GLO.ReminderPortal.gotoDay(dt); 14775 } else if (event.which === 77) { //M: switch to month view 14776 if ( $('.fc-button-month:visible').length === 1) { 14777 document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=month&dt=' + GLO.Uri.hash('dt'); 14778 UTIL.cancelEvent(event); 14779 } 14780 } else if (event.which === 68) { //D: switch to day view 14781 if ( $('.fc-button-agendaDay:visible').length === 1) { 14782 document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=agendaDay&dt=' + GLO.Uri.hash('dt'); 14783 UTIL.cancelEvent(event); 14784 } 14785 } else if (event.which === 80) { //P: Print 14786 window.print(); 14787 } else if (event.which === 82) { //R: refresh appts 14788 GLO.ReminderPortal.hashNavigate(); 14789 UTIL.cancelEvent(event); 14790 } else if (event.which === 84) { //T: switch to today (or moves focus to "Go To" drop down) 14791 GLO.ReminderPortal.gotoToday(); 14792 UTIL.cancelEvent(event); 14793 } else if (event.which === 87) { //W: switch to week view 14794 if ( $('.fc-button-agendaWeek:visible').length === 1) { 14795 document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=agendaWeek&dt=' + GLO.Uri.hash('dt'); 14796 UTIL.cancelEvent(event); 14797 } 14798 } 14799 } 14800 }); 14801 $(window).bind('keypress', function(e) { 14802 //if (e.ctrlKey) { if (e.which > 36 && e.which < 41) { e.preventDefault(); } } 14803 14804 if (e.altKey) { 14805 if (e.which === 33 || e.which === 34) { //33 = page up, 34 = page down. 14806 e.preventDefault(); 14807 } else if (e.which > 48 && e.which < 56) { //1-7: 14808 e.preventDefault(); 14809 } else if (e.which === 68) { //D: switch to day view 14810 e.preventDefault(); 14811 } else if (e.which === 77) { //M: switch to month view 14812 e.preventDefault(); 14813 } else if (e.which === 80) { //P: print 14814 e.preventDefault(); 14815 } else if (e.which === 82) { //R: refresh appts 14816 e.preventDefault(); 14817 } else if (e.which === 84) { //T: Switch to today (or go to drop down) 14818 e.preventDefault(); 14819 } else if (e.which === 87) { //W: switch to week view 14820 e.preventDefault(); 14821 } 14822 } 14823 }); 14824 14825 //Step V: If Mobile 14826 if (GLO.Info.isMobile(true)) { 14827 setTimeout( function() { //so overrides style set on _providerLayout.cshtml. 14828 $("#staff-portal-header").css({ "font-size": "108%" }); 14829 $("#apptPortal-cal-btns").css({ "font-size": "108%" }); 14830 $("#staff-filter").css({ "width": "165px" }); 14831 //$("#calList-button").not('.reminderview').css({ "margin-right": "25px" }); 14832 $('.fc-header-title').css({ 'margin-top': '1px' }); 14833 }, 50); 14834 14835 GLO.Info.setupFastClick($('#staff-portal-header')[0]); 14836 } else { 14837 //$('.fc-button-tomorrow').css({ "margin-left": "72px" }); 14838 //$('#calList-button').css({ "margin-right": "21px" }); 14839 } 14840 14841 //Step VI: Other 14842 GLO.WaitList.setupRefresh(null, true); 14843 GLO.Report.enableFullPageCheck(); 14844 14845 _initVerifySFilter(); 14846 _initUrlReminderView(); 14847 } 14848 14849 /* Solves 2 Use Cases 14850 * when change location it clears staff-filter in url, unless staff-filter is a number (i.e. a single staff), this verifies single-staff filter exists in provider 14851 * on phone and go to Schedule -> Reminders, defaults to current staff; but current staff does NOT perform client services 14852 */ 14853 function _initVerifySFilter() { 14854 var sfilter = GLO.Uri.query('sfilter'); 14855 14856 if (UTIL.isEmpty(sfilter) || sfilter.indexOf(',') !== -1 || !UTIL.isNumber(sfilter)) { return; } 14857 14858 var jstaff = $('#staff-filter'); 14859 14860 if (jstaff.length === 0) { return; } 14861 14862 var stdd = jstaff.find('option[value=' + sfilter + ']'); 14863 14864 if (stdd.length === 0) { 14865 GLO.Staff.Filter.gotoSchedule(); 14866 } 14867 } 14868 14869 function _initUrlReminderView() { 14870 //var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 14871 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 14872 14873 if (!UTIL.isEmpty(highlight)) { 14874 GLO.ReminderPortal.attemptHighlight(highlight, 1); 14875 } 14876 } 14877 function _highlightColumn() { 14878 var highlight = UTIL.cleanString(GLO.Uri.url('highlight-column')); 14879 14880 if (!UTIL.isEmpty(highlight)) { 14881 GLO.ReminderPortal.attemptHighlight(highlight, 1); 14882 } 14883 } 14884 _constructor.attemptHighlight = function(highlight, attemptCount) { 14885 var jhighlight = $('#' + highlight + ', .' + highlight); 14886 14887 if (jhighlight.length > 0) { 14888 UI.highlight(jhighlight, 800, 6400, true); 14889 } else if (attemptCount < 5) { 14890 ++attemptCount; 14891 14892 setTimeout(function() { 14893 GLO.ReminderPortal.attemptHighlight(highlight, attemptCount); 14894 }, 1900); 14895 } 14896 } 14897 14898 function _setupHeader() { 14899 //$('#easySearch_text').attr('title', 'Client search by name or phone'); 14900 14901 var jBtnHeader = $('#staff-portal-header'); 14902 UI.addButtonEffects( jBtnHeader.find('.fc-button-today').click(GLO.ReminderPortal.gotoToday) ); 14903 UI.addButtonEffects( jBtnHeader.find('.fc-button-tomorrow').click(GLO.ReminderPortal.gotoTomorrow) ); 14904 14905 UI.addButtonEffects( jBtnHeader.find('#calAll-button') ); 14906 UI.addButtonEffects( jBtnHeader.find('#calList-button') ); 14907 14908 UI.addButtonEffects( jBtnHeader.find('.fc-button-month') ); 14909 UI.addButtonEffects( jBtnHeader.find('.fc-button-agendaWeek') ); 14910 UI.addButtonEffects( jBtnHeader.find('.fc-button-agendaDay') ); 14911 14912 //jBtnHeader.find('.fc-button-prev').click(GLO.ReminderPortal.gotoPrevDay); 14913 //jBtnHeader.find('.fc-button-next').click(GLO.ReminderPortal.gotoNextDay); 14914 14915 jBtnHeader.find('#reminder-left-arrow > img').click(GLO.ReminderPortal.gotoPrevDay); 14916 jBtnHeader.find('#reminder-right-arrow > img').click(GLO.ReminderPortal.gotoNextDay); 14917 14918 if ($('#inactiveStaffBar:visible, .hello-bar-container').length > 0 && $('#staffFilter:visible').length > 0) { 14919 $('#inactiveStaffBar:visible, .hello-bar-container').css({ "top": "25px" }); 14920 $('#doc3').css({ "margin-top": "50px" }); 14921 } 14922 } 14923 14924 _constructor.setHashDate = function(dt) { 14925 var currHashDt = _constructor.getHashDate(); 14926 var newHashDtString; 14927 14928 if ( !_constructor.IsSameDay(dt, currHashDt)) {
14929 if ( _constructor.IsSameDay(dt, _constructor.getTomorrow()) ) { 14930 newHashDtString = 'tomorrow'; 14931 } else if ( _constructor.IsSameDay(dt, new Date(GLO.Data.provider.now_dt)) ) { 14932 newHashDtString = 'today'; 14933 } else { 14934 newHashDtString = (dt.getMonth() + 1) + '-' + dt.getDate() + '-' + dt.getFullYear() 14935 } 14936 14937 //GLO.Uri.hash('dt', newHashDtString); 14938 document.location.hash = "dt=" + newHashDtString; 14939 } else if (!isInitialized) { 14940 GLO.ReminderPortal.hashNavigate(); 14941 } 14942 } 14943 14944 _constructor.getHashDate = function(useTitle) { 14945 var dtHash = GLO.Uri.hash('dt'); 14946 var dt = dtHash.replace(/-/g, '/'); //= dtHash.replaceAll('-', '/') 14947 14948 if (useTitle && UTIL.isEmpty(dtHash)) { 14949 var dtTest = $('.fc-header-title h2').text(); 14950 14951 if (UTIL.isDate(dtTest)) { 14952 dt = dtHash = new Date(dtTest); 14953 14954 if (dt.getFullYear() == '2001') { 14955 dt.setFullYear(new Date().getFullYear()); 14956 } 14957 } 14958 } 14959 14960 if (UTIL.isEmpty(dtHash) || dtHash === 'today') { 14961 dt = new Date(GLO.Data.provider.now_dt); 14962 } else if (dtHash === 'tomorrow') { 14963 dt = new Date(GLO.Data.provider.now_dt).addDays(1); //dt = _constructor.getTomorrow(); 14964 } else { 14965 dt = new Date(dt); 14966 if (!UTIL.isDate(dt)) { dt = new Date(GLO.Data.provider.now_dt); } 14967 if (!UTIL.isDate(dt)) { dt = new Date(); } 14968 } 14969 14970 return dt; 14971 } 14972 14973 _constructor.IsSameDay = function(dt1, dt2) { 14974 if (dt1.getDate() === dt2.getDate() && dt1.getMonth() === dt2.getMonth() && dt1.getFullYear() === dt2.getFullYear()) { 14975 return true; 14976 } else { 14977 return false; 14978 } 14979 } 14980 14981 _constructor.getTomorrow = function() { //toDo (low priority): move to util.js 14982 var today = new Date(GLO.Data.provider.now_dt); 14983 //var dt = new Date(); 14984 today.setDate(today.getDate() + 1); 14985 return today; 14986 } 14987 14988 _constructor.setTitle = function() { 14989 var dtHash = GLO.Uri.hash('dt'); 14990 var newTitle; 14991 var newDate = _constructor.getHashDate(); 14992 14993 if (dtHash === 'today') { 14994 newTitle = 'Today'; 14995 } else if (dtHash === 'tomorrow') { 14996 newTitle = 'Tomorrow'; 14997 } else { 14998 newTitle = newDate.toGloDateString(true, true, true); 14999 } 15000 15001 document.title = 'Reminders - ' + newTitle; 15002 $('.fc-header-title h2').text(newDate.toGloDateString(true, false)); 15003 } 15004 15005 _constructor.hashNavigate = function() { 15006 var dtHash = GLO.Uri.hash('dt'); 15007 15008 if (UTIL.isEmpty(dtHash) && isInitialized) { 15009 history.back(); //history.go(-1); 15010 } else { 15011 //GLO.Log.insert('dtHash = ' + dtHash + '; isInitialized = ' + isInitialized, 'hashNavigate #1'); 15012 15013 if (!UTIL.isDate(dtHash)) { 15014 dtHash = _constructor.getHashDate(true); 15015 dtHash = dtHash.toGloDate(true); 15016 } else if (!isInitialized) { 15017 isInitialized = true; 15018 } 15019 15020 //GLO.Log.insert('dtHash = ' + dtHash + '; isInitialized = ' + isInitialized, 'hashNavigate #2'); 15021 15022 var processing = $('.loadingDiv').clone(); 15023 $('#reminder-day-view tbody').html('<tr><td colspan="11">' + processing.outerHTML() + '</td></tr>'); 15024 15025 _constructor.setTitle(); 15026 //$("#reminder-day-view table").tablesorter({ textExtraction: UI.tableSorterOrderBy }); 15027 var sfilter = GLO.Uri.query('sfilter'); 15028 15029 var url = location.protocol + '//' + location.host + '/provider/ReminderDay_ajax?dt=' + dtHash + '&sfilter=' + sfilter; 15030 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 15031 .success(function(data, textStatus, jqXHR) { 15032 var tbl = $('#reminder-day-view table.tablesorter'); 15033 var p = tbl.parent(); 15034 tbl.remove(); 15035 15036 tbl.find('tbody').html( $(data).html() ); 15037 p.append(tbl); 15038 tbl = p.find('.tablesorter'); 15039 15040 if (tbl.find('.noResults').length === 0) { 15041 UI.initTableSorter(tbl); 15042 _loadTags(data); 15043 _highlightColumn(); 15044 } 15045 }) 15046 .error(function(jqXHR, textStatus, errorThrown) { });
15047 } 15048 } 15049 15050 function _loadTags(data) { 15051 var jtags = $('<div>' + data + '</div>').find('#reminder-client-tag-list').find('.client-tag'); 15052 15053 if (jtags.length === 0) { return; } 15054 15055 var tbl = $('#reminder-day-view table.tablesorter'); 15056 15057 for (var i=0; i < jtags.length; i++) { 15058 var jtag = jtags.eq(i); 15059 var tdClient = tbl.find('tr[client_id=' + jtag.attr('client_id') + ']').addClass('row-has-tag').find('.reminder-client-name'); 15060 15061 _constructor.setTagNameAndTitle(jtag); 15062 tdClient.append(jtag); 15063 } 15064 15065 tbl.on('click.open-tag', '.client-tag', GLO.ReminderPortal.openTag); 15066 } 15067 15068 _constructor.setTagNameAndTitle = function(jtag) { 15069 var tag = jtag.text(), cid = jtag.attr('client_id'), rcid = jtag.attr('related_client_id'), note = UTIL.cleanString(jtag.attr('note_vc')); 15070 var maxLen = 20; 15071 15072 if (!UTIL.isEmpty(note) && (!UTIL.isEmpty(rcid) || tag.length > maxLen)) { 15073 note = 'note: ' + note; 15074 } 15075 15076 if (!UTIL.isEmpty(rcid)) { 15077 if (!UTIL.isEmpty(note)) { note = ' | ' + note; } 15078 15079 var relationshipName = UTIL.cleanString(jtag.attr('relationship_name_vc')), relateClientName = UTIL.cleanString(jtag.attr('related_client_vc')); 15080 15081 note = relationshipName + ' ' + relateClientName + note; 15082 } 15083 15084 if (tag.length > maxLen) { 15085 if (!UTIL.isEmpty(note)) { note = ' | ' + note; } 15086 15087 note = tag + note; 15088 jtag.text(UTIL.maxString(tag, maxLen - 3)); 15089 } 15090 15091 if (!UTIL.isEmpty(note)) { 15092 jtag.attr('title', note); 15093 } 15094 } 15095 15096 _constructor.openTag = function(event) { 15097 var jtag = $(this); 15098 var tr = jtag.closest('tr'); 15099 var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.reminder-client-name').find('a').text(); 15100 15101 GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName); 15102 } 15103 15104 _constructor.gotoToday = function() { 15105 _constructor.setHashDate(new Date()); 15106 } 15107 15108 _constructor.gotoTomorrow = function() { 15109 _constructor.setHashDate(_constructor.getTomorrow()); 15110 } 15111 15112 _constructor.gotoPrevDay = function() { 15113 _constructor.moveByDay(-1); 15114 } 15115 15116 _constructor.gotoNextDay = function() { 15117 _constructor.moveByDay(1); 15118 } 15119 15120 _constructor.moveByDay = function(days) { 15121 var currDt = _constructor.getHashDate(); 15122 var newDt = new Date(currDt); 15123 15124 newDt.setDate(currDt.getDate() + days); 15125 _constructor.setHashDate(newDt); 15126 } 15127 15128 _constructor.gotoDay = function(day) { 15129 var newDt = new Date(day); 15130 _constructor.setHashDate(newDt); 15131 } 15132 15133 function _savePhoneReminderToRow(row, status, note) { 15134 row.attr('phone_ms_cd', status); 15135 row.attr('phone_note_vc', note); 15136 } 15137 15138 function _setPhoneReminderSpan(jRow, status, title, callDate) { 15139 var jPhoneColumn = jRow.find('.reminder-phone-column').attr('title', title); 15140 var jPhoneSpan = jPhoneColumn.find('span'); 15141 15142 jPhoneSpan.text(callDate); 15143 jPhoneSpan.attr('dt', callDate); 15144 jPhoneSpan.removeClass('reminder-phone-confirmed').removeClass('reminder-phone-left-message').removeClass('reminder-phone-no-response').removeClass('reminder-phone-wrong-number'); 15145 15146 if (status == 900) { 15147 jPhoneSpan.addClass('reminder-phone-confirmed'); 15148 } else if (status == 901) { 15149 jPhoneSpan.addClass('reminder-phone-left-message'); 15150 } else if (status == 902) { 15151 jPhoneSpan.addClass('reminder-phone-no-response'); 15152 } else if (status == 903) { 15153 jPhoneSpan.addClass('reminder-phone-wrong-number'); 15154 } 15155 } 15156 15157 _constructor.savePhoneReminder = function() { //= called when click span (in reminder view) which opens Phone Reminder Popup. 15158 var jModal = $('#simplemodal-container'); 15159 UTIL.DefaultText.deInit(jModal); 15160 15161 var phoneReminderId = jModal.find('#Phone_Reminder_id').val(); 15162 var scheduleId = jModal.find('#Phone_Schedule_id').val(); 15163 var sMultiId = jModal.find('#Phone_Schedule_Multi_id').val(); 15164 var scid = jModal.find('#Phone_Schedule_Client_id').val(); 15165 var mStatus = jModal.find('#Phone_Message_Status_cd').val(); 15166 15167 var callDate = jModal.find('#Phone_Call_dt').val() + ' ' + UI.getTimeMaskValue(jModal.find('#Phone_Call_tm')); 15168 var note = jModal.find('#Phone_Note_vc').val().replace(/"/g, ''); 15169 15170 _constructor.editPhoneReminder(phoneReminderId, scheduleId, sMultiId, scid, mStatus, c
15170allDate, note, null); 15171 15172 if (!UTIL.isEmpty(scid)) { 15173 var jRow = $('#reminder-day-view tr[schedule_client_id="' + scid + '"]'); 15174 } else { 15175 var jRow = $('#reminder-day-view tr#' + scheduleId); 15176 } 15177 15178 _savePhoneReminderToRow(jRow, mStatus, note); 15179 15180 var title = jModal.find('#Phone_Message_Status_cd option:selected').text(); 15181 if (!UTIL.isEmpty(note)) { title += ": " + note; } 15182 15183 _setPhoneReminderSpan(jRow, status, title, callDate); 15184 _constructor.closePhoneReminder(); 15185 } 15186 15187 _constructor.setPhoneReminder = function(checkbox) { //= called when click checkbox (in reminder view). 15188 var jPhoneReminderField = $(checkbox).parent(); 15189 var jRow = jPhoneReminderField.parent(); 15190 15191 var dt = new Date(); 15192 var strDt = dt.toGloTime(); // dt.toGloDateString(true, false, true) + ' @ ' + 15193 15194 jPhoneReminderField.html('<span onclick="GLO.ReminderPortal.openPhoneReminder(this)" dt="' + dt + '">' + strDt + '</span>'); 15195 jRow.removeClass("reminder-row-missing"); 15196 15197 var scheduleId = jRow.attr('id'); 15198 var sMultiId = jRow.attr('schedule_multi_id'); 15199 var scid = jRow.attr('schedule_client_id'); 15200 15201 _constructor.editPhoneReminder('', scheduleId, sMultiId, scid, '', '', '', jPhoneReminderField); 15202 _savePhoneReminderToRow(jRow, 900, ''); 15203 } 15204 15205 _constructor.editPhoneReminder = function(phoneReminderId, scheduleId, scheduleMultiId, scid, mStatus, callDt, note, jPhoneReminderField) { 15206 var url = location.protocol + '//' + location.host + '/provider/ReminderPhoneEdit_ajax?scheduleid=' + scheduleId + '&smid=' + scheduleMultiId + '&scid=' + scid 15207 + '&phonereminderid=' + phoneReminderId + '&mstatus=' + mStatus + '&calldt=' + callDt; 15208 15209 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { note: note } }) 15210 .success(function(data, textStatus, jqXHR) { 15211 if (UTIL.isNumber(data) && jPhoneReminderField && jPhoneReminderField.length) { 15212 jPhoneReminderField.attr('id', data); 15213 } 15214 }) 15215 .error(function(jqXHR, textStatus, errorThrown) { 15216 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 15217 }); 15218 } 15219 15220 _constructor.removePhoneReminder = function(phoneReminderId, scheduleId) { 15221 //Step I: Get Values 15222 var jModal = $('#simplemodal-container'); 15223 var phoneReminderId = jModal.find('#Phone_Reminder_id').val(); 15224 var scheduleId = jModal.find('#Phone_Schedule_id').val(); 15225 var scid = jModal.find('#Phone_Schedule_Client_id').val(); 15226 var sMultiId = jModal.find('#Phone_Schedule_Multi_id').val(); 15227 15228 //Step II: Remove value from cell & close 15229 var jRow = $('#reminder-day-view tr#' + scheduleId); 15230 jRow.attr('phone_note_vc', ''); 15231 jRow.attr('phone_ms_cd', ''); 15232 15233 var jPhoneColumn = jRow.find('.reminder-phone-column').attr('title', ''); 15234 //jPhoneColumn.find('span').remove(); 15235 jPhoneColumn.html('<input type="checkbox" value="1" name="phone-reminder' + scheduleId + '" id="phone-reminder' + scheduleId + '" onchange="GLO.ReminderPortal.setPhoneReminder(this)" title="' + SA.Resource.ReminderCallHelp + '"/>') 15236 15237 _constructor.closePhoneReminder(); 15238 15239 //Step III: Send Ajax Request 15240 var url = location.protocol + '//' + location.host + '/provider/ReminderPhoneRemove_ajax?scheduleid=' + scheduleId + '&phonereminderid=' + phoneReminderId; 15241 15242 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 15243 .success(function(data, textStatus, jqXHR) { 15244 if (UTIL.isNumber(data) && jPhoneReminderField !== null) { jPhoneReminderField.attr('id', data); } 15245 }) 15246 .error(function(jqXHR, textStatus, errorThrown) { 15247 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 15248 }); 15249 } 15250 15251 _constructor.setAndOpenPhoneReminder = function(el) { 15252 var thisTD = $(el).parent(); 15253 var phoneTD = $(el).closest('tr').find('.reminder-phone-column'); 15254 var jcheckbox = phoneTD.find(':checkbox'); 15255 15256 if (jcheckbox.length === 1) { 15257 jcheckbox.click(); 15258 GLO.UI.Form.beginProcessing(thisTD); 15259 15260 setTimeout(function() { 15261 GLO.UI.Form.resetProcessing(thisTD); 15262 phoneTD.find('>span').click(); 15263 }, 800); 15264 } else { 15265 phoneTD.find('>span').click(); 15266 } 15267 } 15268 15269 _constructor.openPhoneReminder = function(el) {
15270 var jRow = $(el).closest('tr'); 15271 var jTd = jRow.find('.reminder-phone-column'); 15272 var el = jTd.find('>span'); 15273 15274 $('#pop-reminder-phone').modal(); 15275 var jModal = $('#simplemodal-container').draggable({ "handle": "h2" }); 15276 15277 jModal.find('#Phone_Reminder_id').val(jTd.attr('id')); 15278 jModal.find('#Phone_Schedule_id').val(jRow.attr('id')); 15279 jModal.find('#Phone_Schedule_Client_id').val(jRow.attr('schedule_client_id')); 15280 jModal.find('#Phone_Schedule_Multi_id').val(jRow.attr('schedule_multi_id')); 15281 15282 if (GLO.Info.isMobile()) { 15283 var h2text = jRow.attr('client_vc') + ' at ' + jRow.attr('time_vc'); 15284 } else { 15285 var h2text = SA.Resource.PhoneReminderFor + ' ' + jRow.attr('client_vc') + ' ' + SA.Resource.at_text + ' ' + jRow.attr('time_vc'); 15286 } 15287 15288 jModal.find('h2').text(UTIL.htmlDecode(h2text)); 15289 $.modal.setHeader(); 15290 15291 var dt = new Date(el.attr('dt')); 15292 jModal.find("#Phone_Call_dt").datepicker().val(dt.toGloDate()); 15293 UI.timeMask('#simplemodal-container #Phone_Call_tm'); 15294 UI.setTimeMaskValue(jModal.find("#Phone_Call_tm"), dt.toGloTime()); 15295 15296 jModal.find('#Phone_Message_Status_cd').val(jRow.attr('phone_ms_cd')); 15297 15298 var note = jRow.attr('phone_note_vc'); 15299 if (!UTIL.isEmpty(note)) { jModal.find('#Phone_Note_vc').val(note).removeClass('defaultTextActive'); } 15300 15301 if (jModal.width() < 10 || jModal.height() < 10) { 15302 $.modal.update(275, 500); 15303 } 15304 15305 jModal.find('input, select, textarea').change( function() { 15306 jModal.find('.btnSave a').css({ "border": "3px solid Red" }); 15307 }); 15308 } 15309 15310 _constructor.closePhoneReminder = function() { 15311 $("#Phone_Call_dt").datepicker("hide"); 15312 $("#Phone_Call_dt").datepicker("destroy"); 15313 $.modal.close(); 15314 } 15315 15316 return _constructor; 15317})(); 15318 15319 15320GLO.Provider = (function() { 15321 function _cProvider() { } 15322 15323 _cProvider.isValidGoldPackage = function() { 15324 if (GLO.Data.provider.packageType == 2 || GLO.Data.provider.packageType == 20 || GLO.Data.provider.packageType == 10) { 15325 if (_cProvider.isValidNextBillDate()) { 15326 return true; 15327 } 15328 } 15329 15330 return false; 15331 } 15332 15333 _cProvider.isValidNextBillDate = function() { 15334 if (UTIL.isDate(GLO.Data.provider.next_bill_dt)) { 15335 var dtNext = new Date(GLO.Data.provider.next_bill_dt); 15336 var dtCutoff = new Date().addDays(-14); 15337 15338 if (dtNext > dtCutoff) { 15339 return true; 15340 } 15341 } 15342 15343 if (GLO.Data.provider.var_cd == 3) { 15344 return true; 15345 } 15346 15347 return false; 15348 } 15349 15350 _cProvider.isPaidAccount = function(includeTrial) { 15351 var sd = GLO.Data.provider.signupDetail; 15352 15353 if (GLO.Data === undefined || GLO.Data.provider === undefined) { 15354 return true; 15355 } else if (UTIL.coalesceInt(sd, 0) < 20 || sd == 40 || sd == 50 || sd == 51) { 15356 return true; 15357 } else if (includeTrial && sd == 52) { //(sd == 52 || sd == 200) 15358 return true; 15359 } else { 15360 return false; 15361 } 15362 } 15363 15364 _cProvider.isInCanada = function() { 15365 if (['NL','PE','NS','NB','QC','ON','MB','SK','AB','BC','YT','NT','NU'].has(GLO.Data.provider.state)) { 15366 return true; 15367 } 15368 15369 return false; 15370 } 15371 15372 _cProvider.isManagerCheck = function(action, jpop, checkIfExists) { 15373 if (GLO.Info.roleType > 219) { 15374 return true; 15375 } else { 15376 if (jpop) { 15377 if (checkIfExists) { 15378 jpop.find('.btnSave').remove(); 15379 jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" }); 15380 jpop.find('input,select,textarea').prop('disabled', true); 15381 } else { 15382 GLO.Popup.close(jpop); 15383 } 15384 } 15385 15386 GLO.Popup.Warning.open('Must be a manager or admin edit ' + action, 'Insufficient Privilege'); 15387 return false; 15388 } 15389 } 15390 15391 return _cProvider; 15392})(); 15393 15394 15395GLO.Provider.Referral = (function() { 15396 function _conRefer() { } 15397 15398 _conRefer.init = function() { 15399 GLO.Info.init(); 15400 15401 var jrpt = $('.report-container'); 15402 var jcontainer = jrpt.find('#ReferralList'); 15403 SA.Upgrade.initReadOnly('referrals', jcontainer); 15404 15405 _initData(jrpt); 15406 GLO.Report.enableFullPageCheck(); 15407 GLO.Report.setupFastClick(); 15408 } 15409 15410 function _initData(jrpt) { 15411 UI.initTableSorter(jrpt.find('.tablesorter')); 15412 GLO.Report.CellSummary.initReport(jrpt, false, true); 15413 } 15414 15415 _conRefer.changeMinPurchase = function(thisTextBox) { 15416 if (thisTextBox.value) {
15417 $('#require-min-purchase').prop('checked', true); 15418 } 15419 } 15420 15421 _conRefer.openEdit = function(thisLink) { 15422 if (SA.Upgrade.initReadOnly('referrals')) { return; } 15423 15424 var jPop = $('#manage-referral-popup'); 15425 var ojpop = new GLO.Popup.Custom(jPop, GLO.Provider.Referral.save); 15426 15427 jPop = ojpop.getPopup(); //.addClass('no-persist'); 15428 jPop.find('.msg').append('<style> .ui-datepicker { z-index: 9999 !important; } </style>'); 15429 jPop.find("#Expire_dt").datepicker({ minDate: 0 }); 15430 15431 var jbtns = jPop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "480px" }); 15432 jbtns.find('.btnSave').css({ "margin": "0", "text-align": "center" }); 15433 15434 if (thisLink) { 15435 var tr = $(thisLink).closest('tr'); 15436 _openEditPopulate(jPop, tr); 15437 } 15438 15439 if (GLO.Provider.isManagerCheck('Referral', jPop, thisLink)) { 15440 jPop.find('input, select, textarea').change( function() { 15441 $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" }); 15442 }); 15443 } 15444 } 15445 15446 function _openEditPopulate(jPop, tr) { 15447 var jname = tr.find('.referral-column-name'); 15448 var minPurchase = tr.find('.min-purchase').text().replace('$', ''); 15449 var jdiscount = tr.find('.referral-column-discount'); 15450 15451 jPop.find('#Provider_Referral_id').val(tr.attr('provider_referral_id')); 15452 jPop.find('#Referral_Name_vc').val(UTIL.coalesce(jname.attr('title'), jname.find('a').text())); 15453 15454 jPop.find('#Coupon_Code_vc').val(tr.find('.coupon-code').text()); 15455 jPop.find('#Max_Allowed_Per_Client_sr').val(tr.find('.max-allowed').text()); 15456 jPop.find('#Expire_dt').val(tr.find('.expire-date').attr('dt')); 15457 15458 if (!UTIL.isEmpty(minPurchase)) { 15459 jPop.find('#require-min-purchase').prop('checked', true); 15460 jPop.find('#Minimum_Purchase_mn').val(minPurchase); 15461 } 15462 15463 var dpct = UTIL.coalesceMoney(jdiscount.attr('discount_pct')); 15464 var dmn = UTIL.coalesceMoney(jdiscount.attr('discount_mn')); 15465 15466 jPop.find('#Discount_pct').val(dpct); 15467 jPop.find('#Discount_mn').val(dmn); 15468 } 15469 15470 _conRefer.refresh = function() { 15471 jbutton = $('#manage-referral-header .fa-refresh'); 15472 var jd = {}; 15473 15474 if (jbutton.hasClass('fa-spin')) { 15475 return; 15476 } else if (!GLO.Report.hasReportPassword(jd)) { 15477 return; 15478 } 15479 15480 jbutton.addClass('fa-spin'); //GLO.UI.Form.beginProcessing(jbutton); 15481 15482 var jrpt = $('.report-container'); 15483 var uri = GLO.Link.WebsiteDomain + 'provider/manage/referral?ispartial=1&display-expired=' + $('#manage-referral-container #Include_Inactive_fl').prop('checked'); 15484 15485 var jqxhr = $.ajax({ "type": "POST", "url": uri, "cache": false, "data": jd }) 15486 .success(function(data, textStatus, jqXHR) { 15487 jbutton.removeClass('fa-spin'); //GLO.UI.Form.resetProcessing(); 15488 15489 jrpt.html($(data).html()); 15490 _initData(jrpt); 15491 }) 15492 .error(function(jqXHR, textStatus, errorThrown) { 15493 jbutton.removeClass('fa-spin'); 15494 //jrpt.html('<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>'); 15495 }); 15496 } 15497 15498 _conRefer.remove = function(thisTD) { 15499 var tr = $(thisTD).closest('tr'); 15500 var referral = tr.find('.referral-column-name span').text(); 15501 15502 if (GLO.Provider.isManagerCheck('Referral')) { 15503 GLO.Popup.Confirm(SA.Resource.RemoveConfirmQuestion + ' ' + referral + '?', function() { GLO.Provider.Referral.removeConfirmed(tr); }); 15504 } 15505 } 15506 15507 _conRefer.removeConfirmed = function(tr) { 15508 if (!GLO.Provider.isManagerCheck('Referral')) { return; } 15509 15510 var url = GLO.Link.Page.Provider.Home + 'manage/RemoveReferral'; 15511 var prId = tr.attr('provider_referral_id'); 15512
15513 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_referral_id": prId } }) 15514 .success(function(data, textStatus, jqXHR) { 15515 var tbl = $('#ReferralList tbody'); 15516 tbl.find('tr[provider_referral_id="' + prId + '"]').remove(); 15517 }) 15518 .error(function(jqXHR, textStatus, errorThrown) { 15519 new GLO.Popup.Error('Unable to remove this referral at this time. Please try again later.'); 15520 }); 15521 } 15522 15523 _conRefer.save = function() { 15524 if (!GLO.Provider.isManagerCheck('Referral')) { return; } 15525 if (!GLO.Info.isRequireGold()) { return false; } 15526 15527 var jpop = $('#manage-referral-edit'); 15528 var referral = jpop.find('#Referral_Name_vc').val(); 15529 15530 if (UTIL.isEmpty(referral)) { 15531 GLO.Popup.Warning(SA.Resource.PleaseEnterReferralName, function() { $('#manage-referral-edit').find('#Referral_Name_vc').focus(); }); 15532 return; 15533 } 15534 15535 var prId = jpop.find('#Provider_Referral_id').val(); 15536 var expire = jpop.find('#Expire_dt').val(); 15537 var coupon = jpop.find('#Coupon_Code_vc').val(); 15538 var maxAllowed = jpop.find('#Max_Allowed_Per_Client_sr').val(); 15539 15540 //if (jpop.find('#Discount_Type_cd1').prop('checked')) { var pctDiscount = jpop.find('#Discount_pct').val(); } else { var pctDiscount = ''; } 15541 //if (jpop.find('#Discount_Type_cd2').prop('checked')) { var mnDiscount = jpop.find('#Discount_mn').val(); } else { var mnDiscount = ''; } 15542 15543 var pctDiscount = jpop.find('#Discount_pct').val(); 15544 var mnDiscount = jpop.find('#Discount_mn').val(); 15545 15546 var jsonRefer = { 15547 "referral_name_vc": referral, "provider_referral_id": prId, "expire_dt": expire 15548 , "coupon_code_vc": coupon, "max_allowed_per_client_sr": maxAllowed 15549 , "discount_pct": pctDiscount, "discount_mn": mnDiscount 15550 }; 15551 15552 if (jpop.find('#require-min-purchase').prop('checked')) { 15553 jsonRefer.minimum_purchase_mn = jpop.find('#Minimum_Purchase_mn').val(); 15554 } 15555 15556 var url = GLO.Link.Page.Provider.Home + 'manage/referralSave'; 15557 GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btnSave') ); 15558 15559 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jsonRefer }) 15560 .success(function(data, textStatus, jqXHR) { 15561 GLO.UI.Form.resetProcessing(); 15562 GLO.Popup.close( $('#manage-referral-popup').closest('.pop-custom') ); 15563 15564 var tr = $(data); 15565 var tbl = $('#ReferralList tbody'); 15566 15567 tbl.find('tr[provider_referral_id="' + tr.attr('provider_referral_id') + '"]').remove(); 15568 tbl.prepend(tr); 15569 15570 tbl.find('#no-referrals-row').remove(); 15571 }) 15572 .error(function(jqXHR, textStatus, errorThrown) { 15573 GLO.UI.Form.resetProcessing(); 15574 new GLO.Popup.Error('Unable to edit this referral at this time. Please try again later.'); 15575 }); 15576 } 15577 15578 _conRefer.openHelpReferBy = function() { 15579 var p1 = '<p>'; 15580 var msg1 = p1 + 'Can setup and track <a onclick="GLO.Uri.gotoUri2(\'report/refer\')">Referral Types</a></p>'; 15581 var msg2 = p1 + '</p>'; 15582 var msg3 = p1 + '</p>'; 15583 var msg4 = p1 + '</p>'; 15584 15585 var htm = '<div id="pop-help-refer">' + msg1 + msg2 + msg3 + msg4 + '</div>'; 15586 GLO.Popup.Info.open(htm, 'Refer Information'); 15587 } 15588 15589 return _conRefer; 15590})(); 15591 15592 15593GLO.Provider.Advanced = (function() { 15594 function _conAdvanced() { } 15595 var _isLoading = true, _timeoutChangeEmailReminder = null, _timeoutChangeTextReminder = null, _timeoutInstantConfirmationTextReminder = null, _timeoutChangeTextReminderSecond = null; 15596 15597 _conAdvanced.init = function() { 15598 _initAddTabs(); 15599 15600 var j = $('#advanced-options'); 15601 15602 if (false && SA.App.isWKWebView()) { //toDo: Mar 2017!!! 15603 j.find('#sa-rate-app').removeClass('hide'); 15604 j.find('#sa-share-app').removeClass('hide'); 15605 } 15606 15607 _conAdvanced.initReadOnlyCheck(); 15608 _conAdvanced.Payment.init(); 15609 _initUrlAction(true); 15610 _initTextFields(j);
15611 _initCalendarOptions(true); 15612 _initOnlineBookingOptions(); 15613 15614 var jclient = $('#advanced-options #page-client'); 15615 _conAdvanced.initClientOptions(jclient); 15616 _isLoading = false; 15617 15618 jscolor.init(); 15619 GLO.Inventory.initHeaderHelpIcon(); 15620 } 15621 15622 _conAdvanced.initClientOptions = function(jclient) { 15623 jclient.find('#Text_Reminder_fl').click(function() { UI.changeFocus(this, 'Text_Reminder_Hr_sr'); }); 15624 jclient.find('#Text2_Reminder_fl').click(function() { UI.changeFocus(this, 'Text2_Reminder_Hr_sr'); }); 15625 jclient.find('#Email_Reminder_fl').click(function() { UI.changeFocus(this, 'Email_Reminder_Day_sr'); }); 15626 15627 jclient.find('#Text_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text_Reminder_fl'); }).change(); 15628 jclient.find('#Text2_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text2_Reminder_fl'); }).change(); 15629 jclient.find('#Email_Reminder_Day_sr').change(function() { UI.markCheckbox(this, 'Email_Reminder_fl'); }).change(); 15630 15631 jclient.find('#Email_Reminder_Day_sr').change(); 15632 jclient.find("input:checkbox").change(UI.CrossOutCheckbox).change(); 15633 } 15634 15635 function _initOnlineBookingOptions(isInit) { 15636 var j = $('#advanced-options'); 15637 var jBookEvery = j.find('#cc-book-every-row'); 15638 var be = jBookEvery.attr('avg_book_every'); 15639 15640 if (!UTIL.isEmpty(be)) { 15641 jBookEvery.removeAttr('avg_book_every'); 15642 jBookEvery.find('option[value="' + be + '"]').prop('selected', true); 15643 } 15644 15645 var jonline = j.find('#advanced-online-booking'); 15646 var waitListClientPortalStart = UTIL.coalesceInt(jonline.attr('wait_list_start_cd')), waitListClientPortalEnd = UTIL.coalesceInt(jonline.attr('wait_list_end_cd')); 15647 15648 jonline.find('#Wait_List_Start_cd').val(waitListClientPortalStart); 15649 jonline.find('#Wait_List_End_cd').val(waitListClientPortalEnd); 15650 15651 var enableToday = jonline.find('#Enable_Wait_List_Today_fl').prop('checked'), enableClientAccess = jonline.find('#Enable_Wait_List_fl').prop('checked'); 15652 15653 if (!enableClientAccess) { _conAdvanced.Online.greyClientAccess(enableClientAccess); } 15654 if (!enableToday) { _conAdvanced.Online.greyToday(enableToday); } 15655 } 15656 15657 function _toggleEasyLoginSetting(loginFormType) { 15658 return false; 15659 15660 /* if (loginFormType == '10') { 15661 $('#easy-login-form').removeClass('hide'); 15662 } else { 15663 $('#Easy_Login_fl').prop('checked', false); // Unchecks it 15664 $('#easy-login-form').addClass('hide'); 15665 } */ 15666 } 15667 15668 function _initCalendarOptions(isPageLoad) { 15669 var j = $('#advanced-calendar'); 15670 15671 if (j.find('#Display_Running_Total_fl').prop('checked')) { 15672 j.find('#row-running-total-order').removeClass('hide'); 15673 } else { 15674 j.find('#row-running-total-order').addClass('hide'); 15675 } 15676 15677 if (isPageLoad) { 15678 j.find('#First_Available_Width_sr').val(j.find('#First_Available_Width_sr').attr('original_value')); 15679 15680 var isKeypadDevice = $.cookies.get('is-keypad-device'); 15681 var divTouchScreen = $('#advanced-feature-this-device-enable-keypad').removeClass('hideX'); 15682 15683 divTouchScreen.find('#Touch_Screen_fl').prop('checked', UTIL.parseBool(isKeypadDevice)); 15684 //if (!UTIL.isEmpty(isKeypadDevice)) { divTouchScreen.find('#Touch_Screen_fl').prop('checked', UTIL.parseBool(isKeypadDevice)); } 15685 15686 var jThisDeviceCalSize = $('#advanced-this-device-cal-header-size').removeClass('hideX').find('#This_Device_Calendar_Header_Size_cd'); 15687 var size = $.cookies.get('cal-header-size'); 15688 15689 if (jThisDeviceCalSize.length && !UTIL.isEmpty(size)) { 15690 jThisDeviceCalSize.val(size); 15691 } 15692 15693 if (GLO.staffResources.length > 9 && !GLO.Info.isIPad) { ///later also enable for resource calendar based on -> SA.Data.resourceJson.resources.length 15694 var jThisDeviceCalSticky = $('#advanced-this-device-cal-header-sticky').removeClass('hideX'); 15695 var isSticky = UTIL.parseBool($.cookies.get('is-cal-header-sticky')); 15696 jThisDeviceCalSticky.find('#This_Device_Calendar_Sticky_Header_fl').prop('checked', isSticky); 15697 } 15698 15699 _conAdvanced.Calendar.setAppointmentNotRequestColor(true); 15700 } 15701 } 15702 15703 function _initTextFields(jcontainer) { 15704 var jfield = jcontainer.find('#Create_Appt_Hr_nr'); 15705 _initTextField(jfield); 15706 15707 var jfield = jcontainer.find('#Update_Appt_Hr_nr'); 15708 _initTextField(jfield); 15709 15710 var jfield = jcontainer.find('#Search_Result_Limit_sr'); 15711 _initTextField(jfield); 15712 15713 var jfield = jcontainer.find('#Email_Notify_Day_sr'); 15714 _initTextField(jfield); 15715 15716 var jfield = jcontainer.find('#Text_Notify_Hr_sr'); 15717 _initTextField(jfield); 15718 15719 var jfield = jcontainer.find('#Today_Wait_List_Max_nr'); 15720 _initTextField(jfield); 15721 } 15722 15723 function _initTextField(jfield) {
15724 var uriSave = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedFields'; 15725 var fnAfterSave = function() { GLO.Provider.Advanced.afterSaveFieldText(jfield); }; 15726 new UI.AutoSave(jfield, uriSave, fnAfterSave, 2800); 15727 } 15728 15729 _conAdvanced.initReadOnlyCheck = function() { 15730 GLO.Info.init(); 15731 15732 if (!GLO.Provider.isPaidAccount(true)) { 15733 var arrow = '<b class="arrow-right">➜</b>'; 15734 var btnUpdateCard = '<span class="btnAdd btnAdd2"> <a onclick="GLO.Uri.gotoUri(\'provider/profile/6\', this, event, true)">Profile ' + arrow + ' My Account</a> </span>'; 15735 15736 var apaid = '<a onclick="GLO.Uri.gotoUri(\'/hello/pricing\', this, event, true)" style="border-bottom: none;">'; 15737 var msg2 = '<p>A ' + apaid + 'paid package</a> is required to change the Advanced Settings</p>' + '<p>Update your card by going to ' + btnUpdateCard + '</p>'; 15738 var btnCSS = 'position: absolute; left: 8px; font-family: Georgia;'; 15739 15740 if (GLO.Info.providerPackage === 2) { 15741 var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'provider/profile/6\', this, event, true)">Update Card</a> </span>'; 15742 } else { 15743 msg2 += '<p style="min-width: 300px; font-weight: bold;">' + apaid + 'Press here to checkout our different packages</a></p>'; 15744 15745 var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'/hello/pricing\', this, event, true)">Paid Packages</a> </span>'; 15746 } 15747 } else if (GLO.Info.roleType < 220) { 15748 var msg2 = '<p>Only a manager or admin user can change an Advanced Setting</p>'; 15749 var btn = null; 15750 } else { 15751 return; 15752 } 15753 15754 var msg1 = '<p>You are welcome to checkout the ' + GLO.Info.getScheduleAnyoneHtm() + ' advanced settings</p>'; 15755 var jinput = $('#advanced-options').find('input, select'); 15756 15757 for (var i=0; i < jinput.length; i++) { 15758 jinput.prop('disabled', true); 15759 } 15760 15761 var h1 = '<b style="font-size: larger;">Read Only Mode</b>'; 15762 var jpop = _conAdvanced.Help.open(h1, msg1 + msg2); 15763 15764 if (innerWidth > 600) { 15765 jpop.find('.msg').find('p').css({ "text-align": "center" }); 15766 } 15767 15768 if (btn) { 15769 var jbtns = jpop.find('.pop-buttons').css({ "position": "relative" }); 15770 jbtns.prepend(btn); 15771 jbtns.find('.btnCancel').addClass('btnClick').css({ "position": "absolute", "right": "8px", "width": "64px", "font-size": "100%" }); 15772 } 15773 } 15774 15775 function _initUrlAction(isInit) { 15776 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 15777 var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase(); 15778 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 15779 var step = GLO.Uri.url('step'); 15780 15781 if (isInit && UTIL.isEmpty(open)) { open = 'tab-online-booking'; } 15782 15783 if (!UTIL.isEmpty(open)) { 15784 var jtab = $('.advanced-tabs').find('#' + open); 15785 15786 if (jtab.length > 0) { 15787 jtab.click(); 15788 } else { 15789 $('.advanced-tabs').find('td:first').click(); 15790 } 15791 } 15792 15793 if (popup == 'anon-search') { 15794 GLO.Provider.Advanced.Online.confirmAllowAnon(); 15795 //} else if (popup == 'how-online-booking-works') { 15796 // GLO.Provider.Advanced.Help.Online.openAppointmentSearch(); 15797 } else if (popup == 'client-address-help') { 15798 GLO.Provider.Advanced.Help.Client.openAddressConfig(); 15799 } else if (popup == 'how-to-guide-reports' || popup == 'how-to-guide-report' || popup == 'help-report-overview') { 15800 SA.Menu.openReportHelp(step); 15801 } else if (popup == 'how-to-guide-payroll' || popup == 'help-commission') { 15802 GLO.Provider.Commission.openReportHelp(step); 15803 } else if (popup == 'membership-setup-how-to' || popup == 'how-to-guide-membership') { 15804 GLO.Provider.Membership.Help.openHowToSetup(step); 15805 } else if (popup == 'how-to-guide-client-list' || popup == 'client-list-help') { 15806 GLO.Message.Bulk.openHelp(step); 15807 } else if (popup == 'how-to-guide-message' || popup == 'message-help-pop-container') { 15808 GLO.Message.Marketing.openHelp(step); 15809 } else if (popup == 'how-to-guide-online-booking') { 15810 GLO.Provider.Advanced.Help.Online.openOnlineBookingGuide(step); 15811 } else if (!UTIL.isEmpty(popup)) { 15812 var jPopTrigger =$('#advanced-options #' + popup); 15813 15814 if (!UTIL.isEmpty(jPopTrigger.attr('onclick'))) { 15815 jPopTrigger.click(); 15816 } else { 15817 jPopTrigger.find('a').click(); 15818 } 15819 } 15820 15821 if (!UTIL.isEmpty(highlight)) { 15822 setTimeout(function() { 15823 var jhighlight = $('#advanced-options').find('#' + highlight); 15824 15825 if (jhighlight.length > 0) { 15826 UI.highlight(jhighlight, 800, 6400, true); 15827 } 15828 }, 1200); 15829 } 15830 } 15831 15832 function _initAddTabs() { 15833 if (innerWidth < 480) { 15834 var labelAppt = 'Appt', labelPay = 'Pay', labelOnlineBooking = 'Booking'; 15835 } else { 15836 var labelAppt = 'Appointments', labelPay = 'Payment', labelOnlineBooking = 'Online Booking'; 15837 } 15838 15839 var j = $('.shadow0'); 15840 var tabHtm = '<td id="tab-appointment"><span>' + labelAppt + '</span></td>' 15841 + '<td id="tab-payment"><span>' + labelPay + '</span></td>' 15842 + '<td id="tab-online-booking"><span>' + labelOnlineBooking + '</span></td>' 15843 + '<td id="tab-client"><span>Clients</span></td>' 15844 + '<td id="tab-location"><span>Locations</span></td>' 15845 + '<td id="tab-help"><span>Help</span></td>'; 15846 15847 j.before('<div class="advanced-tabs"><table><tbody><tr>' + tabHtm + '</tr></tbody></table></div>'); 15848 $('.advanced-tabs').find('td').click(GLO.Provider.Advanced.goToPageFromTab); 15849 } 15850 15851 _conAdvanced.goToItem = function(tab, highlight, element) { 15852 var jadvanced = $('#doc3 #advanced-options'); 15853 var isAdvancedScreen = jadvanced.length; 15854 15855 GLO.Popup.close(); 15856 15857 if (isAdvancedScreen) { 15858 $('#advanced-tabs').find('#tab-' + tab).click(); 15859 15860 if (!UTIL.isEmpty(highlight)) { 15861 var jhigh = jadvanced.find('#' + highlight); 15862 UI.highlight(jhigh, 800, 6400, true); 15863 } 15864 } else { 15865 var url = document.location.origin + '/provider/manage/advanced?open=tab-' + UTIL.coalesceString(tab, '') + '&highlight=' + UTIL.coalesceString(highlight, ''); 15866 15867 setTimeout(function() { 15868 GLO.Uri.gotoUriWithSpinner(url, element, event, true); 15869 }, 100); 15870 } 15871 } 15872 _conAdvanced.goToPageFromTab = function() { 15873 $('.advanced-tabs').find('.wiz-tab').removeClass('wiz-tab'); 15874 15875 var id = $(this).addClass('wiz-tab').attr('id').replace('tab-', 'page-'); 15876 15877 $('#advanced-options').find('.wiz-page').removeClass('wiz-page'); 15878 $('#advanced-options').find('#' + id).addClass('wiz-page'); 15879 } 15880 15881 _conAdvanced.changeConfirmOnCreate = function(element, event) { 15882 if (_isLoading) { return; } 15883 if (!_conAdvanced.canSaveChanges()) { return; } 15884 15885 if (GLO.Info.providerPackage == 1) { 15886 GLO.Provider.Advanced.saveField(element, event); 15887 return; 15888 } 15889 15890 var jclient = $('#advanced-client'); 15891 var yesCount = jclient.attr('send_confirmation_email_count_sr'); 15892 15893 if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; } 15894 15895 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)'; 15896 var msg = '<p style="font-weight: bold;">Do you want to send clients a confirmation email when an appointment is created?</p>' 15897 + '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send confirmation emails to clients when an appointment is created</a></p>'; 15898 15899 var htm = '<div id="pop-confirm-email"> <h1 class="friendly-msg">Send Confirmation Email?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 15900 15901 var fnYes = function() { GLO.Provider.Advanced.changeConfirmOnCreate2(element, event, true); } 15902 var fnNo = function() { GLO.Provider.Advanced.changeConfirmOnCreate2(element, event, false); } 15903 var jpop = new GLO.Popup.Confirm(htm, fnYes, fnNo).getPopup(); 15904 15905 var btnCancel = '<span class="btnCancel" style="position: inherit;">
15905<a onclick="GLO.Provider.Advanced.cancelCheckboxChange(\'' + $(element).attr('id') + '\', event)">Do Nothing</a></span>'; 15906 var jbtns = jpop.find('.pop-buttons-parent').addClass('pop-buttons-parent-responsive'); 15907 jbtns.find('.btnNo').addClass('btnDelete').removeClass('btnNo').css({ "width": "60px" }).after(btnCancel); 15908 jbtns.find('.btnYes').addClass('btnSave').removeClass('btnYes').css({ "width": "60px" }); 15909 } 15910 15911 _conAdvanced.cancelCheckboxChange = function(checkboxId, event) { 15912 var jcheckbox = $('#advanced-options').find('#' + checkboxId); 15913 15914 _isLoading = true; 15915 jcheckbox.prop('checked', !jcheckbox.prop('checked')).change(); 15916 _isLoading = false; 15917 15918 GLO.Popup.close(); 15919 } 15920 15921 _conAdvanced.changeConfirmOnUpdate = function(element, event) { 15922 if (_isLoading) { return; } 15923 if (!_conAdvanced.canSaveChanges()) { return; } 15924 15925 if (GLO.Info.providerPackage == 1) { 15926 GLO.Provider.Advanced.saveField(element, event); 15927 return; 15928 } 15929 15930 var jclient = $('#advanced-client'); 15931 var yesCount = jclient.attr('confirm_on_update_count_sr'); 15932 15933 if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; } 15934 15935 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)'; 15936 var msg = '<p style="font-weight: bold;">Do you want to send clients a confirmation email when an appointment is UPDATED?</p>' 15937 + '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send confirmation emails to clients when an appointment is UPDATED</a></p>'; 15938 15939 var htm = '<div id="pop-confirm-email"> <h1 class="friendly-msg">Send Confirmation Email?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 15940 15941 var fnYes = function() { GLO.Provider.Advanced.changeConfirmOnUpdate2(element, event, true); } 15942 var fnNo = function() { GLO.Provider.Advanced.changeConfirmOnUpdate2(element, event, false); } 15943 var jpop = new GLO.Popup.Confirm(htm, fnYes, fnNo).getPopup(); 15944 15945 var btnCancel = '<span class="btnCancel" style="position: inherit;"><a onclick="GLO.Provider.Advanced.cancelCheckboxChange(\'' + $(element).attr('id') + '\', event)">Do Nothing</a></span>'; 15946 var jbtns = jpop.find('.pop-buttons-parent').addClass('pop-buttons-parent-responsive'); 15947 jbtns.find('.btnNo').addClass('btnDelete').removeClass('btnNo').css({ "width": "60px" }).after(btnCancel); 15948 jbtns.find('.btnYes').addClass('btnSave').removeClass('btnYes').css({ "width": "60px" }); 15949 } 15950 15951 _conAdvanced.changeConfirmOnCreate2 = function(element, event, isSend) { 15952 var jclient = $('#advanced-client'); 15953 15954 _isLoading = true; 15955 jclient.find('#Send_Confirmation_Email_fl').prop('checked', isSend).change(); 15956 _isLoading = false; 15957 15958 if (isSend) { 15959 jclient.attr('send_confirmation_email_count_sr', jclient.attr('staff_count_sr')); 15960 } else { 15961 jclient.attr('send_confirmation_email_count_sr', 0).attr('confirm_on_update_count_sr', 0); 15962 15963 _isLoading = true; 15964 jclient.find('#Confirm_On_Update_fl').prop('checked', false).change(); 15965 _isLoading = false; 15966 } 15967 15968 GLO.Provider.Advanced.saveField(element, event); 15969 } 15970 15971 _conAdvanced.changeConfirmOnUpdate2 = function(element, event, isSend) { 15972 var jclient = $('#advanced-client'); 15973 15974 _isLoading = true; 15975 jclient.find('#Confirm_On_Update_fl').prop('checked', isSend).change(); 15976 _isLoading = false; 15977 15978 if (isSend) { 15979 jclient.attr('confirm_on_update_count_sr', jclient.attr('staff_count_sr')); 15980 } else { 15981 jclient.attr('confirm_on_update_count_sr', 0); 15982 } 15983 15984 GLO.Provider.Advanced.saveField(element, event); 15985 } 15986 15987 _conAdvanced.changeEmailReminder = function(element, event) { 15988 if (_isLoading) { return; } 15989 if (!_conAdvanced.canSaveChanges()) { return; } 15990 15991 clearTimeout(_timeoutChangeEmailReminder); 15992 if ($('#pop-confirm-email-reminder').closest('.glopop').length > 0) { return; } 15993 15994 var jclient = $('#advanced-client'); 15995 var fl = jclient.find('#Email_Reminder_fl'); 15996 var isChecked = fl.prop('checked'); 15997 var txt = jclient.find('#Email_Reminder_Day_sr'); 15998 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)'; 15999 16000 if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; } 16001 if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; } 16002 16003 if (!isChecked) { 16004 var msg = '<p style="font-weight: bold; color: red;">Turn off email reminders for all appointments?</p>'; 16005 } else { 16006 var msg = '<p style="font-weight: bold; color: green;">For all appointments, send email reminders to clients ' + txt.val() + ' days before the appointment?</p>'; 16007 } 16008 16009 var yesCount = jclient.attr('count_email_reminder_hr_sr'); 16010 if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; } 16011 16012 msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send email reminders to clients</a></p>'; 16013 16014 var htm = '<div id="pop-confirm-email-reminder"> <h1 class="friendly-msg">Update Email Reminders?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 16015 16016 var fnYes = function() { GLO.Provider.Advanced.changeEmailReminder2(element, event, isChecked); } 16017 var jpop = new GLO.Popup.Confirm(htm, fnYes); 16018 } 16019 16020 _conAdvanced.changeTextReminder = function(element, event) { 16021 if (_isLoading) { return; } 16022 if (!_conAdvanced.canSaveChanges()) { return; } 16023 16024 clearTimeout(_timeoutChangeTextReminder); 16025 if ($('#pop-confirm-text-reminder').closest('.glopop').length > 0) { return; } 16026 16027 var jclient = $('#advanced-client'); 16028 var fl = jclient.find('#Text_Reminder_fl'); 16029 var isChecked = fl.prop('checked'); 16030 var txt = jclient.find('#Text_Reminder_Hr_sr'); 16031 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config&highlight=report-column-remind-text", this)'; 16032 16033 if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; } 16034 if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; } 16035 16036 if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) { 16037 GLO.Provider.Advanced.changeTextReminder2(element, event, isChecked); 16038 return; 16039 } 16040 16041 if (!isChecked) { 16042 var msg = '<p style="font-weight: bold; color: red;">Turn off text reminders for all appointments?</p>'; 16043 } else { 16044 var msg = '<p style="font-weight: bold; color: green;">For all appointments, send text reminders to clients ' + txt.val() + ' hours before the appointment?</p>'; 16045 } 16046 16047 var yesCount = jclient.attr('count_text_reminder_hr_sr'); 16048 if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; } 16049 16050 msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Currently ' + yesCount + ' of your staff are setup to send text reminders to clients</a></p>'; 16051 16052 var htm = '<div id="pop-confirm-text-reminder"> <h1 class="friendly-msg">Update Text Reminders?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 16053 16054 var fnYes = function() { GLO.Provider.Advanced.changeTextReminder2(element, event, isChecked); } 16055 var jpop = new GLO.Popup.Confirm(htm, fnYes); 16056 } 16057 16058 _conAdvanced.keyUpTextReminderSecond = function(element, event) { 16059 if (_isLoading) { return; } 16060 16061 clearTimeout(_timeoutChangeTextReminderSecond); 16062 16063 if (UTIL.coalesceInt(element.value, 0) > 0) { 16064 var jbox = $('#advanced-client #Text2_Reminder_fl'); 16065 16066 if (!jbox.prop('checked')) { 16067 _isLoading = true; 16068 jbox.prop('checked', true); 16069 _isLoading = false; 16070 } 16071 } 16072 16073 _timeoutChangeTextReminderSecond = setTimeout(function() { 16074 _conAdvanced.changeTextReminderSecond(element, event); 16075 }, 1500); 16076 } 16077 _conAdvanced.changeTextReminderSecond = function(element, event) { 16078 if (_isLoading) { return; } 16079 if (!_conAdvanced.canSaveChanges()) { return; } 16080 16081 clearTimeout(_timeoutChangeTextReminderSecond); 16082 if ($('#pop-confirm-text-reminder2').closest('.glopop').length > 0) { return; } 16083 16084 var jclient = $('#advanced-client'); 16085 var fl = jclient.find('#Text2_Reminder_fl'); 16086 var isChecked = fl.prop('checked'); 16087 var txt = jclient.find('#Text2_Reminder_Hr_sr'); 16088 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config&highlight=report-column-remind-text2", this)'; 16089 16090 if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; } 16091 if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; } 16092 16093 if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) { 16094 GLO.Provider.Advanced.changeTextReminderSecond2(element, event, isChecked); 16095 return; 16096 } 16097 16098 if (!isChecked) { 16099 var msg = '<p style="font-weight: bold; color: red;">Turn off text reminders #2 for all appointments?</p>'; 16100 } else { 16101 var msg = '<p style="font-weight: bold; color: green;">For all appointments, send text reminders #2 to clients ' + txt.val() + ' hours before the appointment?</p>'; 16102 } 16103 16104 var yesCount = jclient.attr('count_text2_reminder_hr_sr'); 16105 if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; } 16106 16107 msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Currently ' + yesCount + ' of your staff are setup to send text reminders #2 to clients</a></p>'; 16108 16109 var htm = '<div id="pop-confirm-text-reminder2"> <h1 class="friendly-msg">Update Text Reminders #2?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 16110 16111 var fnYes = function() { GLO.Provider.Advanced.changeTextReminderSecond2(element, event, isChecked); } 16112 var jpop = new GLO.Popup.Confirm(htm, fnYes); 16113 } 16114 _conAdvanced.changeTextReminderSecond2 = function(element, event, isChecked) { 16115 var jclient = $('#advanced-client'); 16116 var isSend = jclient.find('#Text2_Reminder_fl').prop('checked'); 16117 var jelement = jclient.find('#Text2_Reminder_Hr_sr'); 16118 var hasMessagePackage = UTIL.parseBool(jclient.find('#cc-text-reminder2').attr('hasMessagePackage')); 16119 16120 clearTimeout(_timeoutChangeTextReminderSecond); 16121 16122 if (!isChecked) { 16123 jelement.val(''); 16124 } else if (!_isValidTextReminderHr(true)); { 16125 return; 16126 } 16127 16128 if (!hasMessagePackage) { 16129 var label = '<b class="narrow-text">A Second Text Reminder for each Appointment</b>'; 16130 var link = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=client&highlight=cc-text-reminder2")\'>Message Plan</a>'; 16131 16132 var msg1 = '<p style="margin-bottom: 32px;">To enable ' + label + ' please enable the ' + link + ' <b class="narrow-text">Pay as Use</b> or another <b class="narrow-text">Message Plan</b></p>'; 16133 var msg2 = '<p>Text reminders cost 1 cent per message</p>'; 16134 var msg3 = '<p>Email reminders are free</p>'; 16135 16136 var htm = '<div id="pop-warn-staff-text-alerts-require-message-package">' + msg1 + msg2 + msg3 + '</div>'; 16137 var jpop = GLO.Popup.Warning.open(htm, 'Text Reminder #2 - Requires Message Package'); 16138 //GLO.Popup.Custom.singleButton(jpop, 'Close'); 16139 16140 jclient.find('#Text2_Reminder_fl').prop('checked', false); 16141 jclient.find('#Text2_Reminder_Hr_sr').val(''); 16142 return; 16143 } 16144 16145 if (isSend) { 16146 jclient.attr('count_text2_reminder_hr_sr', jclient.attr('staff_count_sr'));
16147 } else { 16148 jclient.attr('count_text2_reminder_hr_sr', 0); 16149 } 16150 16151 GLO.Provider.Advanced.saveField(jelement[0], event); 16152 } 16153 16154 _conAdvanced.changeInstantTextConfirmation = function(element, event) { 16155 if (_isLoading) { return; } 16156 if (!_conAdvanced.canSaveChanges()) { return; } 16157 16158 // clearTimeout(_timeoutInstantConfirmationTextReminder); 16159 if ($('#pop-confirm-instant-text-confirmation').closest('.glopop').length > 0) { return; } 16160 16161 var jclient = $('#advanced-client'); 16162 var fl = jclient.find('#Is_Send_Instant_Text_Confirmation_fl'); 16163 var isChecked = fl.prop('checked'); 16164 16165 var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)'; 16166 16167 if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) { 16168 GLO.Provider.Advanced.changeInstantTextConfirmation2(element, event, isChecked); 16169 return; 16170 } 16171 16172 if (!isChecked) { 16173 var msg = '<p style="font-weight: bold; color: red;">Turn off instant text confirmations for all appointments?</p>'; 16174 } else { 16175 var msg = '<p style="font-weight: bold; color: green;">For all appointments created by staff, send text confirmations to clients immediately?</p>'; 16176 msg += '<p><a onclick="' + link + '" style="font-size: smaller;">*Requires a paid message plan</a></p>'; 16177 } 16178 16179 16180 var htm = '<div id="pop-confirm-instant-text-confirmation"> <h1 class="friendly-msg">Update Instant Text Confirmation?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 16181 16182 var fnYes = function() { GLO.Provider.Advanced.changeInstantTextConfirmation2(element, event, isChecked); } 16183 var jpop = new GLO.Popup.Confirm(htm, fnYes); 16184 } 16185 16186 _conAdvanced.changeReserveWithGoogle = function(element, event) { 16187 if (_isLoading) { return; } 16188 if (!_conAdvanced.canSaveChanges()) { return; } 16189 16190 var jclient = $('#advanced-client'); 16191 var jelement = jclient.find('#Reserve_with_Google_fl'); 16192 16193 GLO.Provider.Advanced.saveField(jelement[0], event); 16194 16195 } 16196 16197 _conAdvanced.keyUpEmailReminder = function(element, event) { 16198 if (_isLoading) { return; } 16199 16200 clearTimeout(_timeoutChangeEmailReminder); 16201 16202 if (UTIL.coalesceInt(element.value, 0) > 0) { 16203 var jbox = $('#advanced-client #Email_Reminder_fl'); 16204 16205 if (!jbox.prop('checked')) { 16206 _isLoading = true; 16207 jbox.prop('checked', true); 16208 _isLoading = false; 16209 } 16210 } 16211 16212 _timeoutChangeEmailReminder = setTimeout(function() { 16213 _conAdvanced.changeEmailReminder(element, event); 16214 }, 1500); 16215 } 16216 16217 _conAdvanced.keyUpTextReminder = function(element, event) { 16218 if (_isLoading) { return; } 16219 16220 clearTimeout(_timeoutChangeTextReminder); 16221 16222 if (UTIL.coalesceInt(element.value, 0) > 0) { 16223 var jbox = $('#advanced-client #Text_Reminder_fl'); 16224 16225 if (!jbox.prop('checked')) { 16226 _isLoading = true; 16227 jbox.prop('checked', true); 16228 _isLoading = false; 16229 } 16230 } 16231 16232 _timeoutChangeTextReminder = setTimeout(function() { 16233 _conAdvanced.changeTextReminder(element, event); 16234 }, 1500); 16235 } 16236 16237 _conAdvanced.changeEmailReminder2 = function(element, event, isChecked) { 16238 var jclient = $('#advanced-client'); 16239 var isSend = jclient.find('#Email_Reminder_fl').prop('checked'); 16240 var jelement = jclient.find('#Email_Reminder_Day_sr'); 16241 16242 clearTimeout(_timeoutChangeEmailReminder); 16243 16244 if (!isChecked) { 16245 jelement.val(''); 16246 } 16247 16248 if (isSend) { 16249 jclient.attr('count_email_reminder_hr_sr', jclient.attr('staff_count_sr')); 16250 } else { 16251 jclient.attr('count_email_reminder_hr_sr', 0); 16252 } 16253 16254 GLO.Provider.Advanced.saveField(jelement[0], event); 16255 } 16256 16257 function _isValidTextReminderHr(isSecondText) { 16258 var jclient = $('#advanced-client'); 16259 var isSend = jclient.find('#Text_Reminder_fl').prop('checked'); 16260 var isSend2 = jclient.find('#Text2_Reminder_fl').prop('checked'); 16261 var textHr = jclient.find('#Text_Reminder_Hr_sr').val(); 16262 var textHr2 = jclient.find('#Text2_Reminder_Hr_sr').val(); 16263 16264 if (isSend && isSend2 && Math.abs(textHr - textHr2) < 8) { 16265 var msg1 = '<p>Text Reminder #1 (' + UTIL.pluralLabel(textHr, 'hour') + ') and Text Reminder #2 (' + UTIL.pluralLabel(textHr2, 'hour') + ') must be 8 or more hours apart</p>'; 16266 var msg2 = '<p>Please change the Text Reminder or Text Reminder #2 hours sent before appointment</p>'; 16267 var htm = '<div id="pop-warning-text-reminder-hour">' + msg1 + msg2 + '</div>'; 16268 16269 var fn = function() { 16270 if (isSecondText) { 16271 var jhr = $('#advanced-client #Text2_Reminder_Hr_sr'); 16272 } else { 16273 var jhr = $('#advanced-client #Text_Reminder_Hr_sr'); 16274 } 16275 16276 UI.highlight(jhr); 16277 jhr.focus(); 16278 }; 16279 16280 GLO.Popup.Warning.open(htm, 'Invalid Text Reminder Setting', fn); 16281 return false; 16282 } 16283 16284 return true; 16285 } 16286 16287 _conAdvanced.changeTextReminder2 = function(element, event, isChecked) { 16288 var jclient = $('#advanced-client'); 16289 var isSend = jclient.find('#Text_Reminder_fl').prop('checked'); 16290 var jelement = jclient.find('#Text_Reminder_Hr_sr'); 16291 16292 clearTimeout(_timeoutChangeTextReminder); 16293 16294 if (!isChecked) { 16295 jelement.val(''); 16296 } else if (!_isValidTextReminderHr(false)) { 16297 return; 16298 } 16299 16300 if (isSend) { 16301 jclient.attr('count_text_reminder_hr_sr', jclient.attr('staff_count_sr'));
16302 } else { 16303 jclient.attr('count_text_reminder_hr_sr', 0); 16304 } 16305 16306 GLO.Provider.Advanced.saveField(jelement[0], event); 16307 } 16308 16309 _conAdvanced.changeInstantTextConfirmation2 = function(element, event, isChecked) { 16310 var jclient = $('#advanced-client'); 16311 var jelement = jclient.find('#Is_Send_Instant_Text_Confirmation_fl'); 16312 // var jelement = jclient.find('#Text_Reminder_Hr_sr'); 16313 16314 // clearTimeout(_timeoutInstantConfirmationTextReminder); 16315 16316 GLO.Provider.Advanced.saveField(jelement[0], event); 16317 } 16318 16319 _conAdvanced.setIsKeypadDevice = function(checkbox) { 16320 if (checkbox.checked) { 16321 var label = 'Use On-Screen Keyboard'; 16322 var isKeypadDevice = '1'; 16323 } else { 16324 var label = 'Use Normal Keyboard'; 16325 var isKeypadDevice = '0'; 16326 } 16327 16328 if (checkbox.checked == UTIL.parseBool(GLO.Data.provider.button_based_fl)) { 16329 UTIL.setCookie('is-keypad-device', null); 16330 16331 var msg = 'This device will use your normal On-Screen Keyboard setting which is <b class="narrow-text">' + label + '</b>'; 16332 } else { 16333 UTIL.setCookie('is-keypad-device', isKeypadDevice); 16334 16335 var msg = 'This device keyboard setting has been changed to <b class="narrow-text">' + label + '</b>'; 16336 } 16337 16338 GLO.Popup.Success.open(msg, 'On Screen Keyboard', 65000); 16339 } 16340 _conAdvanced.setIsTouchDevice = function(checkbox) { 16341 if (checkbox.checked) { 16342 var isTouchScreen = '1'; 16343 } else { 16344 var isTouchScreen = '0'; 16345 } 16346 16347 UTIL.setCookie('is-touch-screen', isTouchScreen); 16348 } 16349 _conAdvanced.setIsButtonBased = function(element) { 16350 GLO.Provider.Advanced.saveField(element, event); 16351 GLO.Data.provider.button_based_fl = $(element).prop('checked'); 16352 16353 if (UTIL.isEmpty($.cookies.get('is-keypad-device'))) { 16354 $('#Touch_Screen_fl').prop('checked', GLO.Data.provider.button_based_fl); 16355 } 16356 } 16357 16358 _conAdvanced.setThisDeviceCalHeaderSize = function(selectBox) { 16359 var size = $(selectBox).find('option:selected').attr('value'); 16360 16361 UTIL.setCookie('cal-header-size', size); 16362 } 16363 _conAdvanced.setThisDeviceCalHeaderSticky = function(checkbox) { 16364 if (checkbox.checked) { 16365 var isChecked = '1'; 16366 } else { 16367 var isChecked = '0'; 16368 } 16369 16370 UTIL.setCookie('is-cal-header-sticky', isChecked); 16371 } 16372 16373 _conAdvanced.gotoBirthdayEmailSetup = function(element, event) { 16374 GLO.Uri.gotoUriWithSpinner('message/Birthday?helloback=advanced&tabback=client', element, event, true) 16375 } 16376 _conAdvanced.gotoNewClientEmailSetup = function(element, event) { 16377 GLO.Uri.gotoUriWithSpinner('message/WelcomeClientMessage?helloback=advanced&tabback=client', element, event, true) 16378 }
16379 _conAdvanced.gotoHasFollowupEmailSetup = function(checkbox, event, btn) { 16380 if (_isLoading) { return; } 16381 16382 if (!GLO.Provider.isPaidAccount()) { 16383 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 39) { 16384 var msg = 'Automatic Follow-Up Messages Requires Paid Package'; 16385 16386 16387 if (GLO.Info.isIosApp || GLO.Info.isProviderApp) { 16388 var url = '/hello/pricing'; 16389 } else { 16390 var url = '/provider/profile/6'; 16391 } 16392 16393 var htm = '<div id="pop-followup-require-paid"><p>' + msg + '</p></div>'; 16394 var jpop = GLO.Popup.Warning.open(htm, 'Paid Package Required').getPopup(); 16395 var jbtns = jpop.find('.pop-buttons').css({ "margin-bottom": "12px" }); 16396 var btnOk = jpop.find('.btnOk').css({ "width": "inherit" }); 16397 var cssUpgrade = 'position: absolute; left: 2px; padding-top: 8px; padding-bottom: 6px;'; 16398 16399 if (innerWidth > 360) { 16400 jbtns.css({ "width": "100%", "max-width": "420px" }); 16401 } else { 16402 cssUpgrade += ' letter-spacing: 0;'; //font-family: Arial; font-stretch: condensed; 16403 } 16404 16405 var btnUpgrade = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)" style="' + cssUpgrade + '">Checkout Gold Package</a></span>'; 16406 16407 btnOk.find('>').text('Close').css({ "position": "absolute", "right": "2px", "padding": "8px 12px 6px" }); 16408 btnOk.before(btnUpgrade); 16409 16410 if (checkbox) { 16411 $(checkbox).prop('checked', false); 16412 } 16413 16414 return; 16415 } 16416 } 16417 16418 if (checkbox) { 16419 $(checkbox).prop('checked', !$(checkbox).prop('checked')); 16420 } 16421 16422 if (btn) { 16423 GLO.Uri.gotoUriWithSpinner('message/AutoMarketing?helloback=advanced&tabback=client', btn, event, true); 16424 } else { 16425 GLO.Uri.gotoUriWithSpinner('message/AutoMarketing?helloback=advanced&tabback=client', checkbox, event, false); 16426 } 16427 } 16428 16429 _conAdvanced.canSaveChanges = function(isRequireGold) { 16430 if (isRequireGold && !GLO.Info.isRequireGold()) { 16431 return false; 16432 } else if (GLO.Provider.isPaidAccount(true) && GLO.Info.roleType > 219) { 16433 return true; 16434 } 16435 //if (GLO.Data.provider.signupDetail == 50 || GLO.Data.provider.signupDetail == 52 || GLO.Data.provider.signupDetail == 200 || GLO.Data.provider.signupDetail == 400) { return true; } 16436 16437 return false; 16438 } 16439 16440 _conAdvanced.saveValue = function(fieldName, fieldValue, htmSaveSuccess, fnPostSave) { 16441 if (!_conAdvanced.canSaveChanges()) { return; } 16442 16443 var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField'; 16444 16445 $.ajax({ type: "POST", url: uri, "cache": false, data: { "field": fieldName, "value": fieldValue } }) 16446 .success(function(data, textStatus, jqXHR) { 16447 if (htmSaveSuccess) { 16448 GLO.Popup.Success.open(htmSaveSuccess); 16449 } 16450 16451 if (fnPostSave) { 16452 fnPostSave(); 16453 } 16454 }) 16455 .error(function(jqXHR, textStatus, errorThrown) { 16456 //_styleField(field, 0); 16457 //GLO.Popup.Error('Unable to save. Please try again'); 16458 }); 16459 } 16460 _conAdvanced.saveField = function(element, event, htmSaveSuccess) { 16461 if (!_conAdvanced.canSaveChanges()) { return; } 16462 16463 var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField'; 16464 var jfield = $(element); 16465 var field = UTIL.coalesce(jfield.attr('ProfileField'), jfield.attr('name'), jfield.attr('id')); 16466 var value = jfield.val(); 16467 var type = $.trim(jfield.attr('type')).toLowerCase(); 16468 16469 if (type === 'checkbox') { 16470 value = jfield.prop('checked'); 16471 } 16472 16473 _styleField(jfield); 16474 _initCalendarOptions(); 16475 if (field == 'New_Client_Form_cd') { 16476 _toggleEasyLoginSetting(value); 16477 } 16478 16479 //_initOnlineBookingOptions(); 16480 16481 $.ajax({ type: "POST", url: uri, "cache": false, data: { "field": field, "value": value } }) 16482 .success(function(data, textStatus, jqXHR) { 16483 _styleField(jfield, true, htmSaveSuccess); 16484 16485 setTimeout(function() { 16486 if (!UTIL.isEmpty(jfield.attr('original_value'))) { 16487 jfield.attr('original_value', value); 16488 } 16489 }, 800); 16490 }) 16491 .error(function(jqXHR, textStatus, errorThrown) { 16492 _styleField(field, 0); 16493 GLO.Popup.Error.open('Unable to save. Please try again later', 'Change Setting Failed'); 16494 }); 16495 } 16496 16497 function _styleField(jfield, isSuccess, htmSaveSuccess) { 16498 var jlabel = $('label[for="' + jfield.attr('id') + '"]'); 16499 var label = UTIL.coalesce(jlabel.attr('success_htm'), jlabel.text(), jfield.attr('success_htm')); 16500 var type = UTIL.coalesce($.trim(jfield.attr('type')).toLowerCase(), jfield.prop('type')); 16501 var af = jfield.closest('.advanced-feature'); 16502 16503 if (!UTIL.isEmpty(htmSaveSuccess)) { 16504 label = htmSaveSuccess; 16505 } else if (type === 'radio') { 16506 label = $.trim(af.find('.radio-label').text()) + label; 16507 } else if (type === 'text' || type === 'number') { 16508 if (!UTIL.isEmpty(jfield.val())) { 16509 var label2 = '<i>
16509New Value: </i><b>' + jfield.val() + '</b>'; 16510 } else { 16511 var label2 = '<b>Value Removed</b>'; 16512 } 16513 16514 label = '<p>' + label + '</p><p style="text-align: center;">' + label2 + '</p>'; 16515 } else if (type === 'select-one') { //|| type === 'select-multiple') { 16516 var value = jfield.find(':selected').text(); 16517 16518 if (!UTIL.isEmpty(value)) { 16519 var label2 = UTIL.coalesce(jlabel.attr('success_htm'), jfield.attr('success_htm')); 16520 16521 if (UTIL.isEmpty(label2) && jlabel.length === 2) { 16522 label = jlabel.eq(0).text() + ' <b>' + value + '</b> ' + jlabel.eq(1).text(); 16523 } else { 16524 label = '<p>' + label + '</p><p style="text-align: center;"><i>New Value: </i><b>' + value + '</b></p>'; 16525 } 16526 } else { 16527 var label2 = ''; 16528 label = '<p>' + label + '</p><p style="text-align: center;"><b>Value Removed</b></p>'; 16529 } 16530 } 16531 16532 if (isSuccess) { 16533 GLO.Popup.closeIfExist($('.pop-success.glopop')); 16534 16535 var htm = '<div> <h1 class="friendly-msg">Change Saved</h1> <div class="friendly-msg3">' + label + '</div> </div>'; 16536 var jpop = new GLO.Popup.Success(htm).getPopup(); 16537 //jpop.find('.pop-icon').css({ "top": "50%" }); 16538 16539 setTimeout(function() { 16540 af.removeClass('updating-feature'); 16541 jlabel.removeClass('updating-feature').removeClass('updating-feature-unchecked'); 16542 }, 6400); 16543 } else { 16544 af.addClass('updating-feature'); 16545 jlabel.addClass('updating-feature'); 16546 16547 if (type === 'checkbox' && !jfield.prop('checked')) { 16548 jlabel.addClass('updating-feature-unchecked'); 16549 } 16550 } 16551 16552 if (jfield.attr('id') === 'Display_Print_fl') { 16553 var jProfileMenu = $('#hd-profile-menu').find('.header-drop-menu'); 16554 var liLast = jProfileMenu.find('li:last'); 16555 var liPrint = jProfileMenu.find('#hd-profile-menu-print'); 16556 16557 if (jfield.prop('checked')) { 16558 if (liPrint.length === 0) { 16559 liLast.before('<li id="hd-profile-menu-print"><a onclick="SA.Menu.print()">Print</a></li>'); 16560 } 16561 } else { 16562 liPrint.remove(); 16563 } 16564 } 16565 } 16566 16567 _conAdvanced.afterSaveFieldText = function(jfield) { 16568 _styleField(jfield, 1); 16569 } 16570 16571 _conAdvanced.deleteSyncedClients = function() { 16572 if (!_conAdvanced.canSaveChanges()) { return; } 16573 16574 var h1 = 'Delete Synced Clients?'; 16575 var msg = 'Are you sure you want to delete the clients synced from phones and tablets?'; 16576 var htm = '<div id="pop-confirm-delete-sync"> <h1 class="friendly-msg">' + h1 + '</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>'; 16577 16578 var jpop = new GLO.Popup.Confirm(htm, GLO.Provider.Advanced.deleteSyncedClientsConfirmed).getPopup().addClass('no-persist'); 16579 jpop.find('.btnYes').addClass('btnDelete').removeClass('btnYes').find('>a').text('Delete'); 16580 } 16581 16582 _conAdvanced.deleteSyncedClientsConfirmed = function() { 16583 var uri = GLO.Link.WebsiteDomain + 'provider/manage/RemoveSyncedClients'; 16584 16585 var btns = $('.btnDeleteSyncClients'); 16586 GLO.UI.Form.beginProcessing(btns); 16587 16588 $.ajax({ type: "POST", url: uri, "cache": false }) 16589 .success(function(data, textStatus, jqXHR) { 16590 GLO.UI.Form.resetProcessing(btns); 16591 var jd = $(data); 16592 16593 if (jd.attr('id') === 'sync-results') { 16594 var htm = '<div><h1 class="friendly-msg">Sync Clients Deleted</h1><div class="friendly-msg3">' + data + '</div></div>'; 16595 var jpop = new GLO.Popup.Success(htm, 8500).getPopup(); 16596 } else { 16597 var htm = '<div><h1 class="friendly-msg">Sync Clients Deleted</h1><div class="friendly-msg3">Synced Clients Removed</div></div>'; 16598 new GLO.Popup.Success(htm); 16599 } 16600 }) 16601 .error(function(jqXHR, textStatus, errorThrown) { 16602 GLO.Popup.Error('Unable to merge clients. Please try again later.'); 16603 GLO.UI.Form.resetProcessing(btns); 16604 }); 16605 } 16606 16607 16608 _conAdvanced.Payment = (function() { 16609 function _conAdvancedPay() { } 16610 16611 _conAdvancedPay.init = function() { 16612 var isExtraPayIsTip = UTIL.parseBool($.cookies.get('keypad-extra-payment-is-tip')); 16613 16614 if (isExtraPayIsTip) { 16615 var j = $('#advanced-payment #advanced-payment-extra-payment-is-tip').removeClass('hide'); 16616 j.find('#extra-payment-is-tip').prop('checked', isExtraPayIsTip); 16617 } 16618 } 16619 _conAdvancedPay.changeExtraPaymentIsTip = function(element) { 16620 var isExtraPayIsTip = $(element).prop('checked'); 16621 16622 UTIL.setCookie('keypad-extra-payment-is-tip', isExtraPayIsTip); 16623 } 16624 _conAdvancedPay.changeSelfCheckoutMode = function(element) { 16625 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) { 16626 var msg = '<p>Self-Checkout requires merchant account</p>'; 16627 var btn = '<div>
16627<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></div>'; 16628 var htm = '<div id="pop-warn-missing-merchant-account">' + msg + btn + '</div>'; 16629 16630 GLO.Popup.Warning.open(htm, 'Merchant Account Required'); 16631 } 16632 16633 GLO.Provider.Advanced.saveField(element, event); 16634 } 16635 16636 return _conAdvancedPay; 16637 })(); 16638 16639 16640 _conAdvanced.Calendar = (function() { 16641 function _conAdvancedCal() { } 16642 16643 _conAdvancedCal.openAddFirstAvailableStaff = function() { 16644 var explanation = '<div style="font-size: 108%; cursor: help;" title="Clients will only be able to book an appointment for \"First Available\" if a staff is available during that time">' 16645 + 'Allows clients to book appointments for the <i>First Available</i> staff' 16646 + '</div>' 16647 + '<div>and gives you the ability to assign which staff performs the service</div>'; 16648 16649 var cssExplanation = 'padding-left: 20px; padding-right: 12px; padding-bottom: 40px; letter-spacing: 1px; line-height: 180%;'; 16650 var cssInput = 'display: inline-block; margin-bottom: 8px; letter-spacing: 1px;'; 16651 var cssLabel = cssInput + ' margin-top: 8px; padding-left: 16px; padding-right: 8px; letter-spacing: 0; white-space: normal; font-size: 108%; color: #666;'; 16652 16653 var mp = '<select id="Mobile_Provider_cd" style="width: 140px; margin-left: 20px;">' + $('#cell-mobile-provider #cMobile_Provider_cd').html() + '</select>'; 16654 var phoneInputType = "text"; 16655 if (GLO.Info.isAndroid) { phoneInputType = "tel"; } 16656 16657 var htm = $('<div id="pop-first-available-add-staff" style="text-align: center;">' 16658 + '<h1 style="letter-spacing: 2px; font-size: larger;">Add First Available Staff</h1>' 16659 + '<div style="' + cssExplanation + '">' + explanation + '</div>' 16660 + '<div>' 16661 + '<label for="Name_vc" style="margin-right: 8px; letter-spacing: 1px; font-size: 100%; font-weight: bold;">Name / Label</label>' 16662 + '<input type="text" id="Name_vc" placeholder="Name / Label" value="First Available" style="width: 280px; text-align: center; font-size: 108%;"/>' 16663 + '</div>' 16664 + '<div style="margin-top: 32px; margin-bottom: 12px; padding-bottom: 8px; text-align: center; border: 1px solid #444; color: #444;">' 16665 + '<label style="' + cssLabel + '">Want to Get Notified When Clients Book Appointments for First Available?</label>' 16666 + '<div style="margin-top: 12px;"> <input type="text" id="Email_vc" placeholder="Email Address" style="width: 280px; ' + cssInput + '"/> </div>' 16667 + '<input type="' + phoneInputType + '" id="Phone_vc" placeholder="Phone" style="width: 120px; ' + cssInput + '"/>' 16668 + mp 16669 + '</div>'); 16670 16671 var jpop = new GLO.Popup.Custom(htm, GLO.Provider.Advanced.Calendar.saveAddFirstAvailableStaff).getPopup().addClass('no-persist'); 16672 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" }); 16673 16674 if (innerWidth < 500) { 16675 jpop.find('label[for="Name_vc"]').css({ "display": "block", "margin": "0", "text-align": "center", "color": "#4F81BD", "": "" }); 16676 } 16677 16678 UI.phoneMask(jpop.find("#Phone_vc")); 16679 _conAdvanced.canSaveChanges(); 16680 } 16681 16682 _conAdvancedCal.saveAddFirstAvailableStaff = function() { 16683 if (!_conAdvanced.canSaveChanges()) { return; } 16684 16685 var jpop = $('#pop-first-available-add-staff').closest('.glopop'); 16686 var name = jpop.find('#Name_vc').val(); 16687 var email = jpop.find('#Email_vc').val(); 16688 var phone = jpop.find('#Phone_vc').val(); 16689 var mprovider = jpop.find('#Mobile_Provider_cd').val(); 16690 16691 var jd = { "name": name, "email": email, "phone": phone, "mprovider": mprovider }; 16692 16693 var uri = GLO.Link.WebsiteDomain + 'provider/manage/AddFirstAvailableStaff'; 16694 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 16695 16696 $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 16697 .success(function(data, textStatus, jqXHR) { 16698 GLO.Popup.close(jpop); 16699 new GLO.Popup.Success('First Available Staff Added'); 16700 16701 $('#add-first-available').remove(); 16702 $('#advanced-calendar #Has_First_Available_fl').prop('checked', true); 16703 }) 16704 .error(function(jqXHR, textStatus, errorThrown) { 16705 GLO.Popup.Error('Unable to save. Please try again'); 16706 GLO.UI.Form.resetProcessing(); 16707 }); 16708 } 16709 _conAdvancedCal.saveNotRequestBorderOnly = function(element, event) { 16710 _conAdvancedCal.setAppointmentNotRequestColor(); 16711 16712 var label = $('#Is_Request_Color_Rgb_fl option:selected').text(); 16713 16714 GLO.Provider.Advanced.saveField(element, event, 'Appointment ' + label + ' Color on Border Only'); 16715 } 16716 _conAdvancedCal.setAppointmentNotRequestColor = function(isInit) { 16717 var j = $('#advanced-client-request'); 16718 var jcolor = j.find('#Not_Request_Color_Rgb_vc'); 16719 var color = jcolor.val(); 16720 var jlabel = j.find('label[for="Not_Request_Color_Rgb_vc"]'); 16721 var trBorderOnly = j.find('#advanced-client-request-border-only'); 16722 var label = $('#Is_Request_Color_Rgb_fl option:selected').text(); 16723 16724 if (j.find('#Not_Request_Color_Rgb_fl').prop('checked')) { 16725 trBorderOnly.find('label').css({ "text-decoration": "" }); 16726 trBorderOnly.find('input').prop('disabled', false); 16727 16728 jlabel.css({ "visibility": "visible", "display": "" }); 16729 16730 if (!isInit && UTIL.isEmpty(color)) { 16731 jlabel.click(); 16732 return; 16733 } 16734 16735 if (j.find('#Not_Request_Border_Only_fl').prop('checked')) { 16736 var cssPropName = 'border-color'; 16737 var cssPropNameRemove = 'background-color'; 16738 } else { 16739 var cssPropName = 'background-color'; 16740 var cssPropNameRemove = 'border-color'; 16741 } 16742 16743 jlabel.css(cssPropName, "#" + color); 16744 jlabel.css(cssPropNameRemove, ''); 16745 return '<div style="' + cssPropName + ': #' + color + '">Appointment Color when Staff ' + label + '</div>'; 16746 } else { 16747 trBorderOnly.find('label').css({ "text-decoration": "line-through" });
16748 trBorderOnly.find('input').prop('disabled', true); 16749 16750 jlabel.css({ "visibility": "hidden", "display": "none" }); 16751 jcolor.val(''); 16752 16753 return 'Not Using Changing Appointment Color when Staff ' + label; 16754 } 16755 } 16756 _conAdvancedCal.saveNotRequestColor = function(event) { 16757 var j = $('#advanced-client-request'); 16758 var jcolor = j.find('#Not_Request_Color_Rgb_vc'); 16759 16760 if (j.find('#Is_Request_Color_Rgb_fl option:selected').val() == 1) { 16761 jcolor.attr('ProfileField', 'Request_Color_Rgb_vc'); 16762 } else { 16763 jcolor.attr('ProfileField', 'Not_Request_Color_Rgb_vc'); 16764 } 16765 16766 var htmSaveSuccess = _conAdvancedCal.setAppointmentNotRequestColor(); 16767 16768 GLO.Provider.Advanced.saveField(jcolor[0], event, htmSaveSuccess); 16769 } 16770 16771 _conAdvancedCal.changeHasFirstAvailable = function(element, event) { 16772 if (!GLO.Info.isRequireGold()) { 16773 element.checked = !element.checked; 16774 return false; 16775 } 16776 16777 if (element.checked) { 16778 _conAdvancedCal.openAddFirstAvailableStaff(); 16779 } else { 16780 _conAdvancedCal.removeFirstAvailableStaffConfirm(); 16781 } 16782 16783 element.checked = !element.checked; 16784 } 16785 16786 _conAdvancedCal.removeFirstAvailableStaffConfirm = function() { 16787 if (!_conAdvanced.canSaveChanges()) { return; } 16788 16789 var h1 = 'Delete First Available?'; 16790 var msg = 'Are you sure you want to delete the first available staff?'; 16791 var htm = '<div id="pop-confirm-delete-first-available"> <h1 class="friendly-msg">' + h1 + '</h1> <div class="friendly-msg2">' + msg + '</div> </div>'; 16792 16793 var jpop = new GLO.Popup.Confirm(htm, GLO.Provider.Advanced.Calendar.removeFirstAvailableStaff).getPopup().addClass('no-persist'); 16794 jpop.find('.btnYes').addClass('btnDelete').removeClass('btnYes').find('>a').text('Delete'); 16795 } 16796 16797 _conAdvancedCal.removeFirstAvailableStaff = function() { 16798 if (!_conAdvanced.canSaveChanges()) { return; } 16799 16800 var uri = GLO.Link.WebsiteDomain + 'provider/manage/DeleteFirstAvailableStaff'; 16801 var jpop = $('#pop-confirm-delete-first-available').closest('.glopop'); 16802 GLO.UI.Form.beginProcessing( jpop.find('.btnDelete') ); 16803 16804 $.ajax({ type: "POST", url: uri, "cache": false }) 16805 .success(function(data, textStatus, jqXHR) { 16806 GLO.Popup.close(jpop); 16807 new GLO.Popup.Success('First Available Deleted'); 16808 16809 $('#advanced-calendar #Has_First_Available_fl').prop('checked', false); 16810 }) 16811 .error(function(jqXHR, textStatus, errorThrown) { 16812 GLO.Popup.Error('Unable to delete first available staff. Please try again'); 16813 GLO.UI.Form.resetProcessing(); 16814 }); 16815 } 16816 16817 _conAdvancedCal.enableTurnTracking = function(element, event) { 16818 if (!GLO.Info.isRequireGold()) { 16819 element.checked = !element.checked; 16820 return false; 16821 } 16822 16823 GLO.Provider.Advanced.saveField(element, event); 16824 } 16825 16826 _conAdvancedCal.changeStaffAlert = function(element, hasMessagePackage, label) { 16827 var orig = $(element).attr('original_value'); 16828 16829 if (!hasMessagePackage && orig < 20) { 16830 var link = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=appointment&highlight=advanced-feature-staff-alert-text")\'>Message Plan</a>'; 16831 var msg1 = '<p style="margin-bottom: 32px;">To enable ' + label + ' please enable the ' + link + ' <b class="narrow-text">Pay as Use</b> or another <b class="narrow-text">Message Plan</b></p>'; 16832 var msg2 = '<p>Text alerts cost 1 cent per message</p>'; 16833 var msg3 = '<p>In-app alerts are free</p>'; 16834 16835 var htm = '<div id="pop-warn-staff-text-alerts-require-message-package">' + msg1 + msg2 + msg3 + '</div>'; 16836 var jpop = GLO.Popup.Warning.open(htm, 'Staff Text Alerts Require Message Package'); 16837 //GLO.Popup.Custom.singleButton(jpop, 'Close'); 16838 16839 $(element).find('option[value="10"]').prop('selected', 'selected'); 16840 return; 16841 } 16842 16843 GLO.Provider.Advanced.saveField(element, event); 16844 } 16845 16846 return _conAdvancedCal; 16847 })(); 16848 16849 16850 _conAdvanced.Online = (function() { 16851 function _conAdvancedOnline() { } 16852 16853 _conAdvancedOnline.openChangeBookOutDays = function(element) { 16854 if (!_conAdvanced.canSaveChanges()) { return; } 16855 16856 var jelement = $(element); 16857 16858 var label1 = '<label for="Edit_Book_Out_Days_nr">Clients can book up to </label>'; 16859 var label2 = '<label for="Edit_Book_Out_Days_nr"> days in the future</label>'; 16860 var input = '<input type="text" id="Edit_Book_Out_Days_nr" value="' + element.value + '" onkeypress="UI.numberOnly(event)"/>'; // onchange="GLO.Provider.Advanced.saveField(this, event)" 16861 var divInput = '<div style="margin-top: 12px; margin-bottom: 32px; text-align: center;">' + label1 + input + label2 + '</div>'; 16862 16863 var msg1 = '<p>How far in advance due you want to allow ' + GLO.Info.getScheduleAnyoneHtm(
16863) + ' to setup your schedule so clients can book online?</p>'; 16864 var msg2 = '<p>The default is 180 days (about 6 months) which works well for most businesses</p>'; 16865 var htm = '<div id="pop-book-days-out">' + msg1 + msg2 + divInput + '</div>'; 16866 16867 var jpop = GLO.Popup.Custom.openSimple(htm, 'Schedule How Many Days in the Future', GLO.Provider.Advanced.Online.saveBookOutDays); 16868 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "400px" }); 16869 jbtns.find('.btnCancel > a').css({ "font-weight": "bold" }); 16870 16871 } 16872 _conAdvancedOnline.saveBookOutDays = function() { 16873 if (!_conAdvanced.canSaveChanges()) { return; } 16874 16875 var jpop = $('#pop-book-days-out').closest('.glopop'); 16876 var fieldElement = $('#advanced-online-booking #Book_Out_Days_nr')[0]; 16877 var htmSaveSuccess = null; 16878 16879 fieldElement.value = jpop.find('#Edit_Book_Out_Days_nr').val(); 16880 GLO.Provider.Advanced.saveField(fieldElement, null, htmSaveSuccess); 16881 GLO.Popup.close(jpop); 16882 } 16883 _conAdvancedOnline.saveBookOutDaysConfirmed = function() { 16884 var jpop = $('#pop-booking-limit').closest('.glopop'); 16885 var limit = jpop.find('#Booking_Limit_sr').val(); 16886 var uri = GLO.Link.WebsiteDomain + 'provider/manage/BookingLimit?period=' + period + '&id=' + id; 16887 16888 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 16889 16890 $.ajax({ type: "POST", url: uri, "cache": false }) 16891 .success(function(data, textStatus, jqXHR) { 16892 GLO.Popup.closeIfExist(jpop); 16893 16894 }) 16895 .error(function(jqXHR, textStatus, errorThrown) { }); 16896 } 16897 16898 _conAdvancedOnline.openBookingLimit = function(element) { 16899 if ($('#pop-booking-limit').closest('.glopop').length > 0) { return; } 16900 16901 var jelement = $(element); 16902 var jrow = jelement.closest('li.booking-limit-row'); 16903 var jclient = jelement.closest('#client-form'); 16904 16905 if (jclient.length) { 16906 var clientName = UTIL.cleanString(jclient.find('#First_Name_vc').val()) + ' ' + UTIL.cleanString(jclient.find('#Last_Name_vc').val()); 16907 } else { 16908 var clientName = ''; 16909 } 16910 16911 var htm = _getBookingLimitPopup(jrow, clientName); 16912 var jpop = GLO.Popup.Custom.openSimple(htm, 'Client Booking Limit', GLO.Provider.Advanced.Online.saveBookingLimit); 16913 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 16914 jbtns.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" }); 16915 16916 if (!UTIL.isEmpty(jpop.find('#Schedule_Limit_id').val())) { 16917 var btnDelete = '<span class="btnDelete" style="position: absolute; left: 8px; margin: 0;"><a onclick="GLO.Provider.Advanced.Online.deleteBookingLimit()">Delete</a></span>'; 16918 jbtns.prepend(btnDelete); 16919 } 16920 } 16921 16922 function _getBookingLimitPopup(li, clientName) { 16923 var htm = '<div id="pop-booking-limit">'; 16924 var id = '', cid = '', period = '', limit = '', apptLimitTypeChecked = ''; 16925 16926 if (li && li.length) { 16927 var jrow = $(li); 16928 var apptLimit = UTIL.coalesceInt(jrow.attr('appt_limit_sr')); 16929 id = UTIL.cleanString(jrow.attr('schedule_limit_id')); 16930 cid = UTIL.cleanString(jrow.attr('client_id')); 16931 period = UTIL.cleanString(jrow.attr('period_cd')); 16932 limit = UTIL.coalesceInt(jrow.attr('service_limit_sr'), apptLimit); 16933 16934 if (apptLimit > 0) { 16935 apptLimitTypeChecked = ' selected="selected"'; 16936 } 16937 } 16938 16939 if (!UTIL.isEmpty(clientName)) { 16940 clientName = UTIL.maxString(clientName, 12, true); 16941 } else { 16942 clientName = 'Each Client'; 16943 } 16944 16945 var lbl1 = '<label for="Booking_Limit_sr">Limit ' + clientName + ' to</label>'; 16946 var lbl2 = '<label for="Period_cd"> per </label>'; 16947 16948 var inputId = '<input type="hidden" id="Schedule_Limit_id" value="' + id + '"/>'; 16949 var inputCount = '<input type="number" id="Booking_Limit_sr" value="' + limit + '"/>'; 16950 var selectLimitType = '<select id="Limit_Type_cd"> <option value="appointment"' + apptLimitTypeChecked + '>Appointment</option> <option value="service">Service</option> </select>'; 16951 var selectLimitPeriod = '<select id="Period_cd">' 16952 + '<option value="10"' + _getCheckedAttribute(period, 10) + '>Day</option>' 16953 + '<option value="20"' + _getCheckedAttribute(period, 20) + '>Week</option>' 16954 + '<option value="30"' + _getCheckedAttribute(period, 30) + '>Month</option>' 16955 + '<option value="70"' + _getCheckedAttribute(period, 70) + '>Year</option>' 16956 + '<option value="100"' + _getCheckedAttribute(period, 100) + '>All Upcoming</option>' 16957 + '</select>'; 16958 16959 return htm + inputId + lbl1 + inputCount + selectLimitType + lbl2 + selectLimitPeriod + '</div>'; 16960 } 16961 16962 _conAdvancedOnline.deleteBookingLimit = function() { 16963 var htm = '<div id="pop-confirm-delete-booking-limit">Are you sure you want to delete this client booking limit?</div>'; 16964 var fn = function() { GLO.Provider.Advanced.Online.saveBookingLimit(true); }; 16965 16966 GLO.Popup.Confirm.open(htm, 'Confirm Delete Booking Limit', fn); 16967 } 16968 _conAdvancedOnline.saveBookingLimit = function(isDelete) { 16969 var clientId = UTIL.cleanString($('#displayProfile-Client').find('#Client_id').val()); 16970 16971 if (UTIL.isEmpty(clientId) && !_conAdvanced.canSaveChanges()) { return; } 16972 16973 if (isDelete) { 16974 GLO.Popup.close($('#pop-confirm-delete-booking-limit').closest('.glopop')); 16975 } 16976 16977 var jpop = $('#pop-booking-limit').closest('.glopop'); 16978 var limit = jpop.find('#Booking_Limit_sr').val(); 16979 var period = jpop.find('#Period_cd').val(); 16980 var id = UTIL.cleanString(jpop.find('#Schedule_Limit_id').val()); 16981 var apptLimit = 0, svcLimit = 0; 16982 16983 if (jpop.find('#Limit_Type_cd').find('option:selected').attr('value') === 'appointment') { 16984 apptLimit = limit; 16985 } else { 16986 svcLimit = limit; 16987 } 16988 16989 _saveBookingLimit(id, period, apptLimit, svcLimit, isDelete, clientId); 16990 } 16991 function _saveBookingLimit(id, period, apptLimit, svcLimit, isDelete, clientId) { 16992 var uri = GLO.Link.WebsiteDomain + 'provider/manage/BookingLimit?period=' + period + '&id=' + id; 16993 var jd = { "svclimit": svcLimit, "apptlimit": apptLimit, "isdelete": isDelete }; 16994 var jtbl = $('#aob-booking-limit-list'); 16995 var jpop = $('#pop-booking-limit').closest('.glopop'); 16996 16997 if (!UTIL.isEmpty(clientId)) { uri += '&client=' + clientId; } 16998 16999 if (isDelete) { 17000 GLO.UI.Form.beginProcessing(jpop.find('.btnDelete')); 17001 } else { 17002 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 17003 } 17004
17005 $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 17006 .success(function(data, textStatus, jqXHR) { 17007 GLO.Popup.close(jpop); 17008 jtbl.find('li[schedule_limit_id="' + id + '"]').remove(); 17009 17010 if (!isDelete) { 17011 jtbl.append(data); 17012 } 17013 }) 17014 .error(function(jqXHR, textStatus, errorThrown) { }); 17015 } 17016 17017 function _getCheckedAttribute(value1, value2) { 17018 if (value1 == value2) { 17019 return ' selected="selected"'; 17020 } else { 17021 return ''; 17022 } 17023 } 17024 17025 _conAdvancedOnline.changeWaitListMax = function(element) { 17026 UI.verifyNumberInput(element, true); 17027 17028 if (element.value > 0) { 17029 var isChecked = true; 17030 } else { 17031 var isChecked = false; 17032 } 17033 17034 $('#Enable_Today_Wait_List_Max_fl').prop('checked', isChecked); 17035 } 17036 17037 _conAdvancedOnline.saveExistingOnly = function(event) { 17038 if (!_conAdvanced.canSaveChanges()) { return; } 17039 17040 var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField'; 17041 var jfeature = $('#aob-allow-online-booking') 17042 var jonline = jfeature.find('#Online_Booking_fl'); 17043 var jExistingCheck = jfeature.find('#aob-row-existing-client-only .html-character-checkbox'); 17044 var hasOnlineBooking = true; 17045 17046 if (jExistingCheck.attr('id') === 'only-existing-is-off') { 17047 var clientAccess = 2, isExistingOnly = true; 17048 17049 jExistingCheck.replaceWith('<b id="only-existing-is-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.saveExistingOnly(event)">☑</b>'); 17050 } else { 17051 var clientAccess = 1, isExistingOnly = false; 17052 17053 jExistingCheck.replaceWith('<b id="only-existing-is-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.saveExistingOnly(event)">☐</b>'); 17054 } 17055 17056 if (!jonline.prop('checked')) { 17057 hasOnlineBooking = false; 17058 17059 if (isExistingOnly) { 17060 jonline.click(); 17061 } else { 17062 _saveExistingOnlyComplete('Online Booking Disabled'); 17063 return; 17064 } 17065 } 17066 17067 $.ajax({ type: "POST", url: uri, "cache": false, data: { "field": "Client_Access_cd", "value": clientAccess } }) 17068 .success(function(data, textStatus, jqXHR) { 17069 if (isExistingOnly) { 17070 var msg = '<p style="text-align: center;">Online Booking Updated to: <b>Existing Clients Only</b></p>'; 17071 } else if (hasOnlineBooking) { 17072 var msg = '<p style="text-align: center;">Online Booking Updated to: <b>Anyone Can Book Only</b></p>' 17073 + '<p style="font-size: smaller;">who completes new client form or has a client profile in your ' + GLO.Info.getScheduleAnyoneHtm() + ' account</p>'; 17074 } 17075 17076 _saveExistingOnlyComplete(msg); 17077 }) 17078 .error(function(jqXHR, textStatus, errorThrown) { }); 17079 } 17080 17081 function _saveExistingOnlyComplete(msg) { 17082 var htm = '<div><h1 class="friendly-msg">Update Successful</h1><div class="friendly-msg3">' + msg + '</div></div>'; 17083 var jpop = new GLO.Popup.Success(htm, 8500).getPopup(); 17084 } 17085 17086 _conAdvancedOnline.confirmAllowAnon = function(event, isConfirmSave) { 17087 var hasOnlineBooking = $('#aob-allow-online-booking #Online_Booking_fl').prop('checked'); 17088 17089 if (!hasOnlineBooking) { 17090 var msg1 = '<p style="max-width: 500px; margin: 8px; auto; padding: 2px 8px; text-align: center; background-color: rgba(0, 240, 0, .6);">Must Enable Online Booking</p>'; 17091 } else { 17092 var msg1 = ''; 17093 } 17094 17095 var aLoginLink = UserPortal.getProviderUri() + 'login'; 17096 var aLogin = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aLoginLink + '\', this, null, true, \'BookOnline\')">Login</a>'; 17097 var aNewUser = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aLoginLink + '/NewUser\', this, null, true, \'BookOnline\')">Create Client Profile</a>'; 17098 var msg2 = '<p>By default before a client can search for an available appointment, the client must ' + aNewUser + ' or ' + aLogin + '</p>'; 17099 17100 if (!isConfirmSave) { 17101 var h1 = 'Online Booking - Appointment Search'; 17102 var msg3 = '<p>You can allow users to first search and find an available appointment before entering their <i>name</i>, <i>phone</i>, and <i>email</i> to create a client profile and book an appointment online</p>'; 17103 } else if ($('#allow-anon-search-on').length) { 17104 var h1 = 'Disable Anonymous Appointment Search?'; 17105 var msg3 = '<p>Change to <b>Disable Anonymous Appointment Search</b> so client must first create profile <small>(by entering <i>name</i>, <i>phone</i>, and <i>email</i>) before can search for available appointment</p>'; 17106 } else { 17107 var h1 = 'Allow Anonymous Appointment Search?'; 17108 var msg3 = '<p>Change to <b>Allow Anonymous Appointment Search</b> so client can first search and find available appointment before entering <i>name</i>, <i>phone</i>, and <i>email</i> to create client profile</p>'; 17109 } 17110 17111 var aHow = '<a onclick="GLO.Provider.Advanced.Help.Online.openAppointmentSearch()">How Online Booking Works</a>'; 17112 var divHow = '<div style="margin-bottom: 16px; text-align: center; letter-spacing: 1px; font-weight: bold;">' + aHow + '</div>'; 17113 17114 var htm = '<div id="pop-allow-anon-appt-search">
17114' + divHow + msg1 + msg2 + msg3 + '</div>'; 17115 17116 if (isConfirmSave) { 17117 var jpop = GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Advanced.Online.confirmAllowAnon2); 17118 } else { 17119 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 17120 GLO.Popup.Custom.singleButton(jpop, 'Close'); 17121 } 17122 } 17123 _conAdvancedOnline.confirmAllowAnon2 = function() { 17124 if ($('#allow-anon-search-on').length) { 17125 var newFieldValue = 0; 17126 var htmSaveSuccess = 'Client Must Create Profile before Searching for Appointment'; 17127 } else { 17128 var newFieldValue = 1; 17129 var htmSaveSuccess = 'Anonymous Appointment Search Enabled'; 17130 } 17131 17132 var fnPostSave = function() { 17133 var jfeature = $('#aob-row-allow-anon'); 17134 var jfield = jfeature.find('#allow-anon-search-on'); 17135 17136 if (jfield.length) { 17137 var htm = '<b id="allow-anon-search-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmAllowAnon(event)">☐</b>'; 17138 } else { 17139 jfield = jfeature.find('#allow-anon-search-off'); 17140 var htm = '<b id="allow-anon-search-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmAllowAnon(event)">☑</b>'; 17141 } 17142 17143 jfield.replaceWith(htm); 17144 } 17145 17146 _conAdvanced.saveValue('Allow_Anonymous_Search_fl', newFieldValue, htmSaveSuccess, fnPostSave); 17147 } 17148 17149 _conAdvancedOnline.confirmFA = function(event) { 17150 if (!GLO.Info.isRequireGold()) { 17151 return false; 17152 } 17153 17154 var jfeature = $('#aob-allow-online-booking') 17155 var hasOnlineBooking = jfeature.find('#Online_Booking_fl').prop('checked'); 17156 17157 if (jfeature.find('#only-fa-is-on').length) { 17158 if (hasOnlineBooking) { 17159 var msg1 = '<p>This will enable online booking for all staff</p>'; 17160 } else { 17161 var msg1 = '<p>This will disable online booking for all staff</p>'; 17162 } 17163 17164 var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', this)">Profile ' + UI.arrow + ' Staff</a>'; 17165 var anyone = '<b style="color: green;">Anyone</b>'; 17166 var existing = '<b style="color: orange;">Existing</b>'; 17167 var forbid = '<b style="color: red;">Forbid</b>'; 17168 var msg2 = '<p style="">You can go to ' + aProfile + ' and set the Client Online Booking option for each staff to ' + anyone + ', ' + existing + ', or ' + forbid + '</p>'; 17169 17170 var h1 = 'Confirm Cancel First Available Only'; 17171 var msg = msg1 + msg2; 17172 } else { 17173 var hasFA = $('#advanced-calendar #Has_First_Available_fl').prop('checked'); 17174 var staffCount = UTIL.coalesceInt(jfeature.attr('client_access_count_anyone_sr'), 0) + UTIL.coalesceInt(jfeature.attr('client_access_count_existing_sr'), 0); 17175 var faAllowsOnlineBooking = jfeature.attr('fa_client_access_cd'); 17176 17177 if (hasFA) { 17178 var msg = '<p>This will create a "First Available" column on the calendar and allow clients to book an appointment with First Available when the needed staff is available<p>'; 17179 17180 if (staffCount > 0) { 17181 msg += '<p>And forbid online booking for any specific staff member<br/><small>(clients will not be able to book a specific staff only \'First Available\')</small></p>'; 17182 } 17183 } else { 17184 var msg = ''; 17185 17186 if (!faAllowsOnlineBooking) { 17187 msg += '<p>This will allow clients to book an appointment with First Available when staff is available<p>'; 17188 } 17189 17190 if (staffCount > 0) { 17191 msg += '<p>This will forbid online booking for any specific staff member</p>'; 17192 } 17193 } 17194 17195 var h1 = 'Confirm Enable First Available Only'; 17196 } 17197 17198 var aHelpFA = '<a onclick="GLO.Provider.Advanced.Help.C
17198alendar.openHasFirstAvailable2()">How First Available Works</a>'; 17199 msg += '<div style="margin-top: 16px; margin-bottom: 32px; text-align: center; letter-spacing: 1px;">' + aHelpFA + '</div>'; 17200 17201 //var htm = '<div id="pop-confirm-first-available-only" class="friendly-msg4"><h1 class="friendly-msg4">' + h1 + '</h1><div class="friendly-msg4">' + msg + '</div></div>'; 17202 var htm = '<div id="pop-confirm-first-available-only">' + msg + '</div>'; 17203 GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Advanced.Online.confirmFA2); 17204 } 17205 _conAdvancedOnline.confirmFA2 = function() { 17206 var uri = GLO.Link.WebsiteDomain + 'provider/manage/FirstAvailableOnlineBookingOnly?'; 17207 var jfa = $('#advanced-calendar #Has_First_Available_fl'); 17208 var jfeature = $('#aob-allow-online-booking'); 17209 var jcheck = jfeature.find('#aob-row-restrict-fa .html-character-checkbox'); 17210 var hasOnlineBooking = jfeature.find('#Online_Booking_fl').prop('checked'); 17211 var total = UTIL.coalesceInt(jfeature.attr('client_access_count_forbid_sr', 0)) + UTIL.coalesceInt(jfeature.attr('client_access_count_existing_sr', 0)) + UTIL.coalesceInt(jfeature.attr('client_access_count_anyone_sr', 0)); 17212 17213 if (jfeature.find('#only-fa-is-off').length) { 17214 if (uri.substring(uri.length-1) !== '?') { uri += '&'; } 17215 uri += 'enable_fl=1'; 17216 17217 if (!jfa.prop('checked')) { 17218 if (uri.substring(uri.length-1) !== '?') { uri += '&'; } 17219 uri += 'must_create_fa=1'; 17220 17221 jfa.prop('checked', true); 17222 } 17223 17224 jfeature.find('#Online_Booking_fl').prop('checked', true); 17225 jfeature.attr('fa_client_access_cd', '1'); 17226 17227 jfeature.attr('client_access_count_forbid_sr', total); 17228 jfeature.attr('client_access_count_existing_sr', '0'); 17229 jfeature.attr('client_access_count_anyone_sr', '0'); 17230 17231 jcheck.replaceWith('<b id="only-fa-is-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmFA(event)">☑</b>'); 17232 } else { 17233 if (hasOnlineBooking) { 17234 jfeature.attr('fa_client_access_cd', '1'); 17235 17236 jfeature.attr('client_access_count_forbid_sr', '0'); 17237 jfeature.attr('client_access_count_existing_sr', '0'); 17238 jfeature.attr('client_access_count_anyone_sr', total); 17239 } else { 17240 jfeature.attr('fa_client_access_cd', '3'); 17241 17242 jfeature.attr('client_access_count_forbid_sr', total); 17243 jfeature.attr('client_access_count_existing_sr', '0'); 17244 jfeature.attr('client_access_count_anyone_sr', '0'); 17245 } 17246 17247 jcheck.replaceWith('<b id="only-fa-is-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmFA(event)">☐</b>'); 17248 } 17249 17250 $.ajax({ type: "POST", url: uri, "cache": false }) 17251 .success(function(data, textStatus, jqXHR) { 17252 var msg = '<p style="text-align: center;">First Available Only Online Booking Status Updated</p>'; 17253 var htm = '<div><h1 class="friendly-msg">Update Successful</h1><div class="friendly-msg3">' + msg + '</div></div>'; 17254 var jpop = new GLO.Popup.Success(htm, 8500).getPopup(); 17255 }) 17256 //.error(function(jqXHR, textStatus, errorThrown) { }); 17257 } 17258 17259 _conAdvancedOnline.saveServiceGroupAccessType = function(element, event) { 17260 if (!_conAdvanced.canSaveChanges()) { return; } 17261 17262 var jpop = $('#pop-service-group-access-type').closest('.glopop'); 17263 var label = '<div>' + jpop.find('h1').text() + ' updated to: </div> <div>' + jpop.find('label[for="' + $(element).attr('id') + '"]').outerHTML() + '</div>'; 17264 var sgid = jpop.find('h1').attr('service_group_id'); 17265 var jd = { "service_group_id": sgid, "access_type_cd": element.value }; 17266 17267 if (jd.access_type_cd == 0) { 17268 var arrowRight = '<b class="arrow-right" style="padding: 0 8px;">➜</b>'; 17269 var aServiceProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4\', this, event, true)">Profile' + arrowRight + 'Service</a>'; 17270 var htm = '<div id="pop-warn-customize-by-service">To customize the client access by service go to ' + aServiceProfile + '</div>'; 17271 17272 GLO.Popup.Info.open(htm, 'Customize by Service'); 17273 GLO.Popup.close(jpop); 17274 return; 17275 } 17276 17277 var uri = GLO.Link.WebsiteDomain + 'provider/manage/ServiceGroupAccessType'; 17278 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 17279
17280 $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 17281 .success(function(data, textStatus, jqXHR) { 17282 GLO.Popup.close(jpop); 17283 new GLO.Popup.Success(label); 17284 17285 var j = $('#aob-summary-service-group'); 17286 var jrow = j.find('#aob-summary-service-type').find('.advanced-feature[service_group_id="' + sgid + '"]'); 17287 jrow.attr('access_type_cd', jd.access_type_cd); 17288 jrow.find('.access-type-icon').attr('id', 'access-type-icon' + jd.access_type_cd); 17289 17290 var onlineCount = j.find('.advanced-feature[access_type_cd="1"]').length; 17291 j.find('#aob-service-group-online-count').text(onlineCount); 17292 17293 var viewCount = onlineCount + j.find('.advanced-feature[access_type_cd="2"]').length + j.find('.advanced-feature[access_type_cd="3"]').length; 17294 j.find('#aob-service-group-view-count').text(viewCount); 17295 }) 17296 .error(function(jqXHR, textStatus, errorThrown) { 17297 GLO.Popup.Error('Unable to save. Please try again'); 17298 GLO.UI.Form.resetProcessing(); 17299 }); 17300 } 17301 17302 _conAdvancedOnline.saveWaitListClientAccess = function(element, event) { 17303 if (!_conAdvanced.canSaveChanges()) { return; } 17304 _conAdvancedOnline.greyClientAccess($(element).prop('checked')); 17305 GLO.Provider.Advanced.saveField(element, event); 17306 } 17307 17308 _conAdvancedOnline.saveWaitListToday = function(element, event) { 17309 if (!_conAdvanced.canSaveChanges()) { return; } 17310 _conAdvancedOnline.greyToday($(element).prop('checked')); 17311 GLO.Provider.Advanced.saveField(element, event); 17312 } 17313 17314 _conAdvancedOnline.greyClientAccess = function(isEnabled) { 17315 if (isEnabled) { 17316 $('#aob-waiting-list-date-row').css({ "background-color": "" }); 17317 $('#aob-waiting-list-client-access-today').css({ "background-color": "" }); 17318 } else { 17319 $('#aob-waiting-list-date-row').css({ "background-color": "rgba(80,80,80,.4)" }); 17320 $('#aob-waiting-list-client-access-today').css({ "background-color": "rgba(80,80,80,.4)" }); 17321 } 17322 } 17323 17324 _conAdvancedOnline.greyToday = function(isEnabled) { 17325 if (isEnabled) { 17326 $('#aob-waiting-list-today-row').find('#aob-notify-client-when-next, #aob-customize-client-signin').css({ "background-color": "" }); 17327 $('#aob-waiting-list-client-access-today').css({ "background-color": "" }); 17328 } else { 17329 $('#aob-waiting-list-today-row').find('#aob-notify-client-when-next, #aob-customize-client-signin').css({ "background-color": "rgba(80,80,80,.4)" }); 17330 $('#aob-waiting-list-client-access-today').css({ "background-color": "rgba(80,80,80,.4)" }); 17331 } 17332 } 17333 17334 _conAdvancedOnline.saveWaitListHourRange = function(element, event) { 17335 if (!_conAdvanced.canSaveChanges()) { return; } 17336 17337 var jelement = $(element); 17338 var id = jelement.attr('id'); 17339 var isStart = (id == 'Wait_List_Start_cd'); 17340 17341 var j = $('#aob-waiting-list-row'); 17342 var jstart = j.find('#Wait_List_Start_cd'); 17343 var jend = j.find('#Wait_List_End_cd'); 17344 var label = 'Client Access to Waiting List '; 17345 17346 if (element.value == '') { 17347 jstart.val(''); 17348 jend.val(''); 17349 } else if (UTIL.isEmpty(jstart.val())) { 17350 jstart.val(1015); 17351 17352 } else if (UTIL.isEmpty(jend.val())) { 17353 jend.val(4970); 17354 } 17355 17356 label += 'Enabled during your defined hour range of: ' + jstart.find(':selected').text() + ' - ' + jend.find(':selected').text(); 17357 17358 var json = { "Wait_List_Start_cd": jstart.val(), "Wait_List_End_cd": jend.val() }; 17359 _saveWaitListHourRange2(json, label); 17360 //_enableTodayWaitListForClients(); 17361 } 17362 17363 function _enableTodayWaitListForClients() { 17364 var j = $('#advanced-online-booking'); 17365 var jWaitToday = j.find('#Enable_Wait_List_Today_fl'); 17366 var jWaitClient = j.find('#Enable_Wait_List_fl'); 17367 17368 if (!jWaitToday.prop('checked')) { 17369 jWaitToday.prop('checked', true).change(); 17370 } 17371 17372 if (!jWaitClient.prop('checked')) { 17373 jWaitClient.prop('checked', true).change(); 17374 } 17375 } 17376 17377 function _saveWaitListHourRange2(json, label) { 17378 var uri = GLO.Link.WebsiteDomain + 'provider/manage/WaitListHourRange'; 17379
17380 $.ajax({ type: "POST", url: uri, "cache": false, data: json }) 17381 .success(function(data, textStatus, jqXHR) { 17382 new GLO.Popup.Success(label); 17383 }) 17384 .error(function(jqXHR, textStatus, errorThrown) { 17385 }); 17386 } 17387 17388 return _conAdvancedOnline; 17389 })(); 17390 17391 17392 _conAdvanced.CustomApp = (function() { 17393 function _conAdvancedApp() { } 17394 17395 _conAdvancedApp.initCustomAppInfo = function() { 17396 17397 } 17398 17399 _conAdvancedApp.saveCustomAppRequest = function() { 17400 var uri = GLO.Link.WebsiteDomain + 'provider/manage/CustomApp'; 17401 var note = UTIL.htmlEncode($('#custom-app-note').val()); 17402 17403 var btn = $('.btnCustomAppRequest'); 17404 GLO.UI.Form.beginProcessing(btn); 17405 17406 $.ajax({ type: "POST", url: uri, "cache": false, data: { "note": note } }) 17407 .success(function(data, textStatus, jqXHR) { 17408 GLO.UI.Form.resetProcessing(btn); 17409 17410 var msg = '<p style="text-align: center;">Thank You for Your Custom App Request</p> <p>A ' + GLO.Info.getScheduleAnyoneHtm() + ' custom app specialist will contact you soon</p>'; 17411 var htm = '<div><h1 class="friendly-msg">Custom App Requested</h1><div class="friendly-msg3">' + msg + '</div></div>'; 17412 17413 var jpop = new GLO.Popup.Success(htm, 8500).getPopup(); 17414 jpop.css({ "background-color": "#222" }); //.css({ "background-color": "rgba(220, 240, 200, .4)" }); 17415 jpop.find('.msg').css({ "color": "rgb(80, 240, 20)" }); 17416 //jpop.find('.pop-icon').css({ "top": "36%" }); 17417 17418 var jsa = jpop.find('.sa-brand'); 17419 jsa.find('b').css({ "color": "rgb(0, 200, 240)" }); 17420 jsa.find('i').css({ "color": "rgb(80, 240, 20)" }); 17421 17422 setTimeout(function() { 17423 $('.hello-bar-container').find('.hello-bar-label').click(); 17424 }, 3600); 17425 }) 17426 .error(function(jqXHR, textStatus, errorThrown) { 17427 GLO.UI.Form.resetProcessing(); 17428 }); 17429 } 17430 17431 return _conAdvancedApp; 17432 })(); 17433 17434 17435 _conAdvanced.Client = (function() { 17436 function _conAdvancedClient() { } 17437 17438 _conAdvancedClient.changeTextPackage = function(element, event, helloback) { 17439 if (_isLoading) { return; } 17440 17441 var jclient = $('#advanced-client'); 17442 var email_package_cd = UTIL.coalesceInt(jclient.attr('email_package_cd'), 0); 17443 var textPackage = 20; 17444 var isChecked = $(element).prop('checked'); 17445 17446 if (!isChecked) { textPackage = 0; } 17447 17448 if (email_package_cd > 0 || textPackage === 0) { 17449 GLO.Message.Marketing.saveTextPackage(textPackage); 17450 } else { 17451 $(element).prop('checked', !isChecked); 17452 var url = 'provider/manage/Upgrade?reason=email-blast&highlight=message-package'; 17453 17454 if (!UTIL.isEmpty(helloback)) { 17455 url += '&' + helloback; 17456 } 17457 17458 GLO.Uri.gotoUri(url, this); 17459 } 17460 } 17461 17462 return _conAdvancedClient; 17463 })(); 17464 17465 17466 _conAdvanced.Help = (function() { 17467 function _conAdvancedHelp() { } 17468 var _ojPop = null; 17469 17470 _conAdvancedHelp.realign = function() { 17471 if (_ojPop) { 17472 _ojPop.realign(); 17473 } 17474 } 17475 17476 function _open(h1, msg, mustRemovePadding) { 17477 var jhtm = $('<div><h1 class="friendly-msg">' + h1 + '</h1><div class="friendly-msg3">' + msg + '</div></div>'); 17478 _ojPop = new GLO.Popup.Custom(jhtm); 17479 var jpop = _ojPop.getPopup().addClass('pop-help'); 17480 17481 var jbtns = jpop.find('.pop-buttons'); 17482 jbtns.find('.btnSave').remove(); 17483 jbtns.find('.btnCancel').addClass('btnOk').addClass('btnCancelWhite').css({ "float": "none", "margin": 0, "padding": 0 }).find('>a').css({ "padding": "4px 10px 3px" }).text('Close'); 17484 17485 if (mustRemovePadding) { 17486 jpop.find('h1').css({ "margin-bottom": "0" }); 17487 var jmsg = jpop.find('.msg').css({ "padding": "0" }); 17488 jmsg.find('p').css({ "margin-left": "20px", "margin-right": "4px" }); 17489 } 17490 17491 return jpop; 17492 } 17493 17494 _conAdvancedHelp.open = function(h1, msg, mustRemovePadding) { 17495 return _open(h1, msg, mustRemovePadding); 17496 } 17497 17498 _conAdvancedHelp.openAboutQuestionMark = function() { 17499 var questionMark = '<span class="helpIcon2 sa-sprite" style="float: left; margin-top: 3px; margin-left: 4px;"></span>'; 17500 var msg1 = '<span style="float: left;">Whenever you see a blue question mark </span>'; 17501 var msg2 = '<span style="float: left; clear: both; margin-bottom: 12px;"> press it to see more information on that subject</span>'; 17502 var msg3 = '<div style="clear: both;"> </div>'; 17503 17504 _open('Blue Question Mark', '<div>' + msg1 + questionMark + msg2 + msg3 + '</div>'); 17505 } 17506 17507 _conAdvancedHelp.openClientEmail = function() { 17508 var url1 = '/provider/webtemplate/email?helloback=advanced&tabback=client'; 17509 var url2 = '/provider/profile/1?helloback=advanced&tabback=client'; 17510 17511 var msg1a = 'You can have ' + GLO.Info.getScheduleAnyoneHtm(
17511) + ' email your clients reminders, confirmations, receipts, appointment follow-ups, and marketing messages'; 17512 var msg1b = 'Go to your <a onclick="GLO.Uri.gotoUri(\'' + url1 + '\', this)">Email Template</a> to customize the emails your clients receive'; 17513 var msg2 = ''; 17514 17515 /* 17516 var aProfileMe = '<a onclick="GLO.Uri.gotoUri(\'' + url2 + '\', true)">Profile -> Me</a>'; 17517 var btnClientSetup = '<span class="btnAdd btnAction2 btnClientSetup"> <a style="padding: 0 8px;">Client Setup</a> </span>'; 17518 msg2 = 'Go to ' + aProfileMe + ' and press the ' + btnClientSetup + ' button to set when reminders are sent to your clients and if you want confirmations to also be sent to your clients'; 17519 msg2 = <p style="margin-top: 20px;">' + msg2 + '</p>'; 17520 */ 17521 17522 var htm = '<p>' + msg1a + '</p> <p style="padding-bottom: 8px; border-bottom: 1px solid #444;">' + msg1b + '</p>' + msg2; 17523 17524 _open('Customize Emails To Your Clients', htm).css({ "background-color": "rgb(240, 250, 250)" }); 17525 } 17526 17527 17528 _conAdvancedHelp.Calendar = (function() { 17529 function _conAHelpCal() { } 17530 17531 _conAHelpCal.openSignin = function() { 17532 var h1 = 'Client Self Sign-In Screen'; 17533 var header = '<p>Change What Happens When a Client Signs In</p>'; 17534 var waitIcon = '<span id="wait-list-icon" class="letter-over-background wait-list-icon-fixed" onclick="GLO.WaitList.open()" title="1 clients on the waiting list">W</span>'; 17535 var commingSoon = '<b class="sa-soon" style="font-size: 14px;">Comming Soon</b>'; 17536 var commingSoon2 = '<b class="sa-soon">Comming Oct 2024</b>'; 17537 17538 var label1 = '<h3>Add to Waiting List <i style="font-size: small;">Default</i></h3>'; 17539 var ul1 = GLO.Template.ClientSignin.helpWaitListItem(); 17540 var msg1 = 'All client sign-ins added to the Waiting List, press ' + waitIcon + ' at the top of the Calendar to open wait list and see your sign-ins'; 17541 var opt1 = label1 + '<div class="sign-in-option">' + '<p>' + msg1 + '</p>' + ul1 + '</div>'; 17542 17543 var label2 = '<h3>Auto Check-In Existing Appointment</h3>'; 17544 var msg2 = 'When a client signs-in'; 17545 var li2a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Check-In Appointment</li>'; 17546 var li2b = '<li>if client has no appointment <b class="html-arrow"></b> Add Sign-In to the Waiting List</li>'; 17547 var opt2 = label2 + '<div class="sign-in-option">' + '<p>' + msg2 + '</p>' + '<ul>' + li2a + li2b + '</ul></div>'; 17548 17549 var label3 = '<h3>' + 'Auto Sign-In Appointment</h3>'; 17550 var msg3 = 'When a client signs-in'; 17551 var li3a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Sign-In Appointment</li>'; 17552 var li3b = '<li>if client has no appointment <b class="html-arrow"></b> Create Appointment</li>'; 17553 var opt3 = label3 + '<div class="sign-in-option">' + '<p>' + msg3 + '</p>' + '<ul>' + li3a + li3b + '</ul></div>'; 17554 17555 var label4 = '<h3>' + commingSoon + 'Auto Create Appointment</h3>'; 17556 var msg4 = commingSoon2 + 'When a client signs-in'; 17557 var how4b = '<a onclick="GLO.Provider.Advanced.Help.Calendar.autoCreateAppt()" style="display: inline-block; margin-left: 4px; font-weight: bold;">How this works</a>'; 17558 var li4a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Check-In Appointment</li>'; 17559 var li4b = '<li>if client has no appointment <b class="html-arrow"></b> Create Appointment' + how4b + '</li>'; 17560 var opt4 = label4 + '<div class="sign-in-option">' + '<p>' + msg4 + '</p>' + '<ul>' + li4a + li4b + '</ul></div>'; 17561 17562 return _open(h1, '<div id="pop-help-signin-options">' + header + opt1 + opt2 + opt3 + opt4 + '</div>'); 17563 } 17564 _conAHelpCal.autoCreateAppt = function() { 17565 var h1 = 'Client Self Sign-In: Auto-Create'; 17566 var commingSoon = '<b class="sa-soon">Comming Soon</b>'; 17567 var bFeature = '<b style="color: rgb(40, 80, 240);">'; 17568 var bArrow = '<b class="html-arrow"></b>'; 17569 var small = '<small style="letter-spacing: 0;">'; 17570 17571 var p1 = '<p>' + commingSoon + '<b>Auto Sign-In Existing Appointment or Create Appointment</b></p>'; 17572 var p2 = '<p>Client Signs in and does not have an appointment, then appointment is automatically created</p>'; 17573 var p3 = '<p>This feature requires enabling ' + bFeature + 'First Available</b> or ' + bFeature + 'Turn Tracking</b> to know which staff to assign to appointment</p>'; 17574 var msg = p1 + p2 + p3; 17575 17576 var li1a = '<li>if staff is available within 15 minutes ' + bArrow + ' create appointment</li>'; 17577 var li1b = '<li>if staff not available within 15 minutes ' + bArrow + ' add to wait list</li>'; 17578 var ol1 = '<ul style="">' + li1a + li1b + '</ul>'; 17579 var li1 = '<li>' + bFeature + 'Staff Selected</b> If client selects staff ' + small + '(when sigin in)</small>' + bArrow + 'run search to verify staff is available' + ol1 + '</li>'; 17580 17581 var small2 = small + 'who does the service(s) + is available</small>'; 17582 var li2 = '<li>' + bFeature + 'Turn Tracking</b> If no staff selected during sign-in and using turn tracking, then assign staff by finding which staff is next ' + small2 + '</li>'; 17583 17584 var li3 = '<li>' + bFeature + 'First Available</b> If no staff selected and not using turn tracking ' + bArrow + ' create appointment under First Available</li>'; 17585 var li4 = '<li>' + bFeature + 'Wait List</b> If cannot assign staff then adds sign-in to Waiting List</li>'; 17586 17587 return _open(h1, '<div id="pop-help-signin-auto-create">' + msg + '<ol>' + li1 + li2 + li3 + li4 + '</ul></div>'); 17588 } 17589 17590 _conAHelpCal.openPrintTraveler = function() { 17591 var h1 = 'Print Traveler'; 17592 var imgTraveler = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/print-traveler2.png" style="min-height: 120px; width: 90%; max-width: 320px; margin-bottom: 0;"></div>'; 17593 17594 var label1 = '<h3 style="margin-top: 0;">None</h3>'; 17595 var msg1 = '<p>Do Not Print Traveler</p>'; 17596 17597 var label2 = '<h3>Display Print Option on Check-In</h3>'; 17598 var msg2 = '<p>When Check-In Appointment have option to <b>Check-In & Print Traveler</b></p>'; 17599 17600 var label3 = '<h3>On Check-In</h3>'; 17601 var msg3 = '<p>Automatically Print Traveler when Check-In Appointment</p>'; 17602 17603 var label4 = '<h3>On Check-In (Walk-Ins Only)</h3>'; 17604 var msg4 = '<p>Only Automatically Print Traveler when Check-In Walkin Appointment (if appointment pre-booked do not print traveler)</p>'; 17605 17606 var imgEditApptUrl = GLO.Data.cdnDirectory + 'image/faq/appointment/edit/checkin-and-print-traveler2.png'; 17607 var imgEditAppt = '<div><img src="' + imgEditApptUrl + '" style="min-height: 120px; width: 90%; max-width: 480px; margin-bottom: 0;"></div>'; 17608 var noteList = '<ol><li>Open appointment</li><li>Press blue triangle to right of client name</li><li>Select "Print Appointment"</li></ol>'; 17609 var notePrintAppt = '<div id="pop-help-print-traveler-note"><p style="margin-top: 32px;">Also, you can always Print Appointments</p>' + noteList + '</div>'; 17610 17611 var aInvoice = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=other&id=faq-other-pay-invoice-online\', null, this, event)">Invoices</a>'; 17612 var aReceipt = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/receipt?helloback=advanced&tabback=payment\', this, event, true)">Receipts</a>'; 17613 var notePrintReceipt = '<div id="pop-help-print-traveler-receipt"><p style="margin-top: 32px;">You can also print ' + aInvoice + ' and ' + aReceipt + '</p></div>'; 17614 17615 var urlCustomize = 'provider/manage/traveler?helloback=advanced&tabback=appointments'; 17616 var btnCustomize = '<span class="btnAdd btnCustomize">
17616<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlCustomize + '\', this, event, true)">Customize</a></span>'; 17617 17618 var htm = btnCustomize + imgTraveler + label1 + msg1 + label2 + msg2 + label3 + msg3 + label4 + msg4 + imgEditAppt + notePrintAppt + notePrintReceipt; 17619 var jpop = _open(h1, '<div id="pop-help-print-traveler">' + htm + '</div>'); 17620 jpop.find('.msg').css({ "max-width": "720px" }); 17621 17622 setTimeout(function() { 17623 if (_ojPop && _ojPop.realign) { 17624 _ojPop.realign(); 17625 } 17626 }, 1200); 17627 } 17628 17629 _conAHelpCal.openRequireClient = function() { 17630 var h1 = 'Require Client on Create Appointment'; 17631 var msg1 = '<p>Leave un-checked if you want to create appointments without including a client on the appointment</p>'; 17632 var msg2 = '<p>If this is turned on, when attempting to create an appointment without a client name will trigger this message:</p>'; 17633 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/create-appt-require-client-name.png" style="max-width: 300px; min-height: 200px; width: 80%; border-radius: 20px;"/> </div>'; 17634 var msgZ = '<p>This setting does <b>not</b> affect Personal Time Appointments (Off, Lunch, Vacation, etc) which never include a client</p>'; 17635 17636 return _open(h1, '<div>' + msg1 + msg2 + img + msgZ + '</div>'); 17637 } 17638 17639 _conAHelpCal.openDisplayClientRequest = function() { 17640 var h1 = 'Display Client Request Checkbox'; 17641 var msg1 = '<p>You can include a client request checkbox to indicate if the client specifically requested the given staff member</p>'; 17642 var msg2 = '<p>This will add a checkbox to the create appointment and the edit appointment popups</p>'; 17643 17644 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/create-appointment-client-requested.png" style="max-width: 300px; min-height: 200px; width: 80%;"/> </div>'; 17645 var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/edit-appointment-client-requested.png" style="max-width: 480px; min-height: 24px; width: 80%;"/> </div>'; 17646 17647 var msg3 = '<p>If there are multiple staff on an appointment clicking the client requested checkbox allows you to select staff</p>'; 17648 var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-requested-by-client.jpg" style="max-width: 300px; min-height: 40px; width: 80%;"/> </div>'; 17649 17650 var a = '<b onclick="GLO.Provider.Advanced.Help.Calendar.openDisplayRunningTotal()" style="color: rgb(40, 80, 240); cursor: pointer;">Display Turn Tracking (Who is Next)</b>'; 17651 var msgZ = '<p>If you are using ' + GLO.Info.getScheduleAnyoneHtm() + ' to determine who gets the next walkin (by using the ' + a + ' option) then requested clients are ignored in determining who\'s next</p>'; 17652 17653 _open(h1, '<div>' + msg1 + msg2 + img1 + img2 + msg3 + img3 + msgZ + '</div>').css({ "background-color": "rgb(240, 250, 250)" }); 17654 } 17655 17656 _conAHelpCal.openHasFirstAvailable = function() { 17657 var h1 = 'First Available'; 17658 var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;'; 17659 var msg1 = '<div style="' + css1 + '">First Available gives you more control over your clients and staff, with the ability to benefit from the time savings, productivity, and increased sales that online booking offers</div>'; 17660 17661 var msg2 = '<p>With First Available you can restrict online booking so clients only book appointments with "First Available" and then at your convenience you assign the client to the desired staff</p>'; 17662 var msg3 = '<p>The appointment search looks at how many staff you have working at the desired time, what services the staff perform, and then returns openings for "First Available" based on availability</p>'; 17663 17664 var msg4 = '<p>The appointment is then saved under the first available column on the calendar</p>'; 17665 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/first-available-calendar.png" style="max-width: 600px; min-height: 120px; width: 98%;"/> </div>'; 17666 17667 var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', this)">Profile ' + UI.arrow + ' Staff</a>'; 17668 var anyone = '<b style="color: green;">Anyone</b>'; 17669 var existing = '<b style="color: orange;">Existing</b>'; 17670 var msgZ = '<p style="">Go to ' + aProfile + ' and set the Client Online Booking option for "First Available" to ' + anyone + ' or ' + existing + ', then set the online booking option as desired for all other staff</p>'; 17671 17672 var jpop = _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + img + msgZ + '</div>', true); 17673 jpop.find('.msg > div').css({ "padding": "0" }); 17674 } 17675 17676 _conAHelpCal.openHasFirstAvailable2 = function() { 17677 var h1 = 'First Available'; 17678 var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;'; 17679 var msg1 = '<div style="' + css1 + '">First Available gives you more control over your clients and staff, while benef
17679iting from the time savings, productivity, and increased sales of having online booking</div>'; 17680 17681 var msg2 = '<li>When a client searches for an appointment, ' + GLO.Info.getScheduleAnyoneHtm() + ' looks at how many staff you have working at the requested time, what services the staff perform, and then returns openings for "First Available" based on your staff available</li>'; 17682 17683 var msg3 = '<li>The appointment is saved under the first available column on the calendar</li>'; 17684 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/first-available-calendar.png" style="max-width: 600px; min-height: 120px; width: 98%;"/> </div>'; 17685 17686 var msg4 = '<li>Then at your convenience you assign the client to the staff that fits best</li>'; 17687 17688 /* 17689 var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', true)">Profile -> Staff</a>'; 17690 var anyone = '<b style="color: green;">Anyone</b>'; 17691 var existing = '<b style="color: orange;">Existing</b>'; 17692 var msgZ = '<p style="">Go to ' + aProfile + ' and set the Client Online Booking option for "First Available" to ' + anyone + ' or ' + existing + ', then set the online booking option as desired for all other staff</p>'; 17693 */ 17694 17695 var msg5 = '<p style="font-size: initial;">This also defaults appointment requests and the waiting list (if enabled) to "First Available"</p>'; 17696 17697 var msgMain = '<ol>' + msg2 + msg3 + msg4 + '</ol>'; 17698 var jpop = _open(h1, '<div>' + msg1 + msgMain + img + msg5 + '</div>', true); 17699 17700 if (innerWidth > 700) { 17701 jpop.css({ "max-width": "90%" }); 17702 } 17703 17704 setTimeout(function() { 17705 GLO.Provider.Advanced.Help.realign(); //= gives the image a little time to load. 17706 }, 900); 17707 17708 GLO.Provider.Advanced.Help.realign(); 17709 return jpop.find('.msg > div').css({ "padding": "0" }); 17710 } 17711 17712 _conAHelpCal.openDisplayRunningTotal = function() { 17713 var h1 = 'Turn Tracking (Who is Next)'; 17714 var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;'; 17715 var msg1 = '<div style="' + css1 + '">Use ' + GLO.Info.getScheduleAnyoneHtm() + ' to calculate which staff member gets the next walkin client</div>'; 17716 17717 var signin = '<span style="display: inline-block; height: 28px; padding: 0 4px; border-top-left-radius: 6px; border-top-right-radius: 6px; background-color: rgba(136,136,136,.8); color: white;">sign-in</span>'; 17718 var clockInHelp = '<span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Commission.openReportHelp(1)" title="Overview of Clock In/Out, Wages, and Timesheets"></span>'; 17719 var ol1a = '<div style="max-width: 680px;">If you want to track staff hours you can have your clients clock in/out' + clockInHelp + '</div>'; 17720 var ol1 = '<li>Staff check-in when they arrive: <small>by clicking ' + signin + ' above their name on the calendar</small>' + ol1a + '</li>'; 17721 17722 var ol2 = '<li><b style="color: rgb(40, 80, 240);">Who is Next</b> is determined by the order the staff checks in and how many walkins they have had today</li>'; 17723 var ol3 = '<li>The staff with the green calendar header gets the current walkin</li>'; 17724 var ol4 = '<li>The staff with the yellow calendar header gets the next walkin</li>'; 17725 var ol5 = '<li>Each staff\'s daily sales total is displayed at the top of the calendar <i style="display: block; padding-left: 8px;">(this amount can be displayed in dollar amount or in hours)</i></li>'; 17726 var ol6 = '<li>Click the calendar header to sign-out the staff or re-arrange the staff order on the calendar</li>'; 17727 17728 var ol = '<ol style="margin-left: 40px;">' + ol1 + ol2 + ol3 + ol4 + ol5 + ol6 + '</ol>'; 17729 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/front-desk-cal-who-is-next.png" style="max-width: 600px; min-height: 80px; width: 96%;"/> </div>'; 17730 17731 return _open(h1, '<div>' + msg1 + ol + img + '</div>', true); 17732 } 17733 17734 function _getButtonCheckinHelp() { 17735 var btnCheckin = '<span style="padding: 2px 8px; letter-spacing: 1px; border: 1px solid #c5dbec; border-radius: 20px; font-weight: bold; font-size: 12px; color: black;">Check-In</span>'; 17736 return '<span style="display: inline-block; border-radius: 20px; background-color: rgba(220,240,0, .8);">' + btnCheckin + '</span>'; 17737 } 17738 function _getButtonCheckoutHelp() { 17739 var btnCheckout2 = '<span style="padding: 2px 8px; letter-spacing: 1px; border: 1px solid #c5dbec; border-radius: 20px; font-weight: bold; font-size: 12px; color: rgb(240,240,240);">
17739Check-Out</span>'; 17740 return '<span style="display: inline-block; border-radius: 20px; background-color: rgba(20,200,120,.8);">' + btnCheckout2 + '</span>'; 17741 } 17742 function _getButtonPosHelp() { 17743 var css = 'position: relative; display: inline-block; height: 16px; width: 60px; padding: 4px 12px 3px; line-height: 1.2; font-size: 14px; background-color: black; color: white;'; 17744 var cssSmall = 'position: absolute; top: 7px; left: 10px; padding-right: 2px; letter-spacing: 0; font-size: 10px;' 17745 17746 var btnInner = '<small style="' + cssSmall + '">go to</small><b style="position: absolute; top: 6px; right: 12px;">POS</b>'; 17747 var btnPOS2 = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'/pos\', this, event, true)" style="' + css + '">' + btnInner + '</a>'; 17748 17749 return '<span id="btnGoToPos" class="btnAdd">' + btnPOS2 + '</span>'; 17750 } 17751 function _getButtonRefreshHelp() { 17752 return '<b id="cal-refresh-icon" class="fa fa-refresh" style="position: relative; top: inherit; right: inherit; color: black;">↻</b>'; 17753 } 17754 function _getPosModeNote(isCheckout) { 17755 var btnRefresh = _getButtonRefreshHelp(); 17756 var btnCheckIn = _getButtonCheckinHelp(); 17757 var btnCheckout = _getButtonCheckoutHelp(); 17758 var btnPOS = _getButtonPosHelp(); 17759 17760 var threeBtns = 'Adds 4 buttons to <b class="calendar-mode">Front Desk Calendar</b> ' + btnCheckIn + ' ' + btnCheckout + ' ' + btnRefresh + ' ' + btnPOS; 17761 //var viewInSmall = '<small style="letter-spacing: 0;">(upper-right corner)</small>'; 17762 //var viewIn = '<p><i>Edit Appointment popup</i> press appointment length ' + viewInSmall + ' to open appointment in POS Screen</p>'; 17763 var h4 = '<h4 style="margin-bottom: 4px; padding: 2px; text-align: center; border-radius: 24px; font-size: 16px; background-color: rgba(0,0,0,.8); color: white;">Full P.O.S. Mode</h4>'; 17764 17765 if (isCheckout) { 17766 var msg = 'Quickly Check-Out clients on both <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S. Screen</b>'; 17767 } else { 17768 var msg = 'Quickly Check-In and Check-Out appointments on both <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S. Screen</b>'; 17769 } 17770 17771 var msg2 = '<p>With Quick Check-In and Check-Out there is no need to enter appointment time ' + GLO.Info.getScheduleAnyoneHtm() + ' automatically calculates that for you</p>'; 17772 var msg3 = '<p>The <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S.</b> integrate giving you all the scehduling features along with the ease of use of the <b class="pos-mode">P.O.S. Screen</b></p>'; 17773 17774 return '<div style="margin-top: 48px; font-size: smaller;">' + h4 + '<p>' + msg + '</p><p>' + threeBtns + '</p>' + msg2 + msg3 + '</div>'; 17775 } 17776 _conAHelpCal.openPosNote = function() { 17777 var msg1 = '<p>Add the P.O.S. buttons to the top of the front desk calendar to speed up checking in and out clients</p>'; 17778 var msg2 = '<p style="font-style: italic;">The front desk calendar is the calendar with all your staff on 1 screen</p>'; 17779 17780 var note = _getPosModeNote(); 17781 var htm = '<div id="pop-help-check-settings">' + msg1 + msg2 + note + '</div>'; 17782 return _open('Quick Check-In/Out', htm); 17783 } 17784 _conAHelpCal.openCheckInSettings = function() { 17785 var b = '<b style="letter-spacing: 0; font-family: arial; font-size: large; color: black;">'; 17786 var small = '<small style="display: block; margin-top: 4px; margin-left: 24px; letter-spacing: 0;">'; 17787 var li1 = b + 'Normal</b> Automatically Check-In New Appointment ' + small + ' when create new appointment that start within 10 minutes, 20 minutes if paid</small>'; 17788 //var li2 = b + 'Check-In button on Calendar</b> add ' + _getButtonCheckinHelp() + ' to <b class="calendar-mode">Front Desk Calendar</b> to easily lookup appointment for quick check-in and adjustments</small>'; 17789 //var li2 = '<b>Normal with Refresh</b> Adds refresh button at top of <b class="calendar-mode">Front Desk Calendar</b> ' + _getButtonRefreshHelp(); 17790 //var li3 = '<b>Quick, Auto Check-In with POS</b> Adds <b class="pos-mode">P.O.S.</b> Mode to <b class="calendar-mode">Front Desk Calendar</b> ' + small + 'to easily lookup appointment for quick check-in</small>'; 17791 var li2 = b + 'Strict</b> Do Not Automatically Check-In Appointments'; 17792 var ul = '<ul id="pop-help-check-settings-list"> <li>' + li1 + '</li> <li>' + li2 + '</li> </ul>'; 17793 17794 var msg = ''; 17795 var note = _getPosModeNote(); 17796 var htm = '<div id="pop-help-check-settings">' + msg + ul + note + '</div>'; 17797 return _open('Check-In Settings', htm); 17798 } 17799 _conAHelpCal.openCheckOutSettings = function() { 17800 var span = '<span style="display: inline-block; margin-left: 24px;">'; 17801 17802 var li1 = '<b>Normal</b> Automatically checkout appointment when paid during appointment'
17803 + span + 'specifically paid 30 minutes before apointment, during appointment, or after appointment</span>'; 17804 17805 //var li2 = '<b>Normal with P.O.S.</b>'; 17806 17807 var li2 = '<b>Quick</b> Similar to normal but also ends appointment when Checkout' 17808 + span + 'When appointment checked out automatically mark current time as end of appoinment ' 17809 + '<small>(if appointment has already started)</small> so staff can start on next client</span>'; 17810 // automatically adjusts service time so appointment ends at Check-Out time 17811 17812 var li3 = '<b>Review</b> Keep ticket open after payment' 17813 + span + 'During checkout, when pay full amount with credit card do not auto-close ticket</span>'; 17814 17815 var li4 = '<b>Review if no Tip</b> Keep ticket open after payment' 17816 + span + 'During checkout, when pay full amount with credit card do not auto-close ticket if the ticket has no tip</span>'; 17817 17818 //var li4 = '<b>Quick with P.O.S.</b>'; 17819 var ul = '<ul style="margin-left: 0;"> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li> <li>' + li4 + '</li> </ul>'; 17820 17821 var btnCheckout = _getButtonCheckoutHelp(); 17822 var msg1 = ''; //'<b>Normal</b> works best for most businesses'; 17823 //var msg2 = '<b>Quick</b> adds ' + btnCheckout + ' button at the top of <b class="calendar-mode">Front Desk Calendar</b> to use <b class="pos-mode">Quick Check-In mode</b> which helps find: appointment, client, and add/change services'; 17824 //When add service: automatically uses previous service\'s staff 17825 var msg = '<div style="margin-bottom: 32px; border-bottom: 1px grey solid; font-size: smaller;"><p>' + msg1 + '</p></div>'; 17826 17827 var note = _getPosModeNote(); 17828 var htm = '<div id="pop-help-check-settings">' + ul + note + '</div>'; 17829 return _open('Check-Out Settings', htm); 17830 } 17831 _conAHelpCal.openCheckoutRestriction = function() { 17832 var li = '<li style="margin-bottom: 20px;">'; 17833 var span = '<span style="display: block; margin-left: 24px;">'; 17834 var small = '<small style="display: inline-block; margin-left: 4px; letter-spacing: 0; white-space: nowrap;">'; 17835 17836 var li1 = '<b>No Payment Restriction</b>' + span + 'Can checkout an appointment that is not fully paid</span>'; 17837 17838 var li2 = '<b>Receptionists and Other Staff Require Payment</b>' 17839 + span + 'Receptionists cannot checkout appointment that is not fully paid</span>' 17840 + span + 'Once an appointment is checked-out the appointment date cannot be changed</span>' 17841 + span + small + '(only staff with manager or admin role can checkout appointment that is not fully paid or move appointment that is checked-out)</small></span>'; 17842 17843 var li3 = '<b>Full Payment Required to Checkout Appointment</b>' 17844 + span + 'No one can checkout appointment that is not fully paid</span>' 17845 + span + 'Once an appointment is checked-out the appointment date cannot be changed</span>' 17846 + span + small + '(Even Manager/Admin cannot checkout un-paid tickets; to move checked-out appointment first must change appointment status)</small></span>'; 17847 17848 var ul = '<ul style="margin-left: 0;"> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li> </ul>'; 17849 17850 var btnCheckout = _getButtonCheckoutHelp(); 17851 var note = '<div style="font-style: italic; font-size: smaller;"> <b>Fully Paid</b> <span>when ticket payment >= ticket price</span> </div>'; 17852 var htm = '<div id="pop-help-check-settings">' + ul + note + '</div>'; 17853 17854 return _open('Check-Out Payment Restriction', htm); 17855 } 17856 17857 _conAHelpCal.openStaffTextAlert = function() { 17858 var alerts = '<b class="narrow-text">Check-In / Sign-In alerts</b>'; 17859 var inApp = '<i class="narrow-text">in-app notifications</i>'; 17860 var text = '<i class="narrow-text">text messages</i>'; 17861 var saApp = GLO.Info.getScheduleAnyoneHtm(false, true) + ' app'; 17862 17863 var aEnableText = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/advanced?open=tab-appointment&highlight=advanced-feature-staff-alert-text")\'>Staff Alert Texts Enabled</a>' 17864 var aEnableInApp = '<a onclick=\'GLO.Uri.gotoUri2("help#tab=message&id=faq-message-staff-in-app-notifications")\'>Enable Notifications</a>'; 17865 var aResetInApp = '<a onclick=\'GLO.Uri.gotoUri2("help#tab=message&id=faq-message-staff-in-app-notifications-reset")\'>Reset In-App Notifications</a>'; 17866 17867 var inAppEnable = ' <small class="narrow-text">(must ' + aEnableInApp + ' in the ' + saApp + ')</small>'; 17868 var textEnable = ' <small class="narrow-text">(must have ' + aEnableText + ' | texts cost 1 cent per message)</small>'; 17869 17870 var msg1 = '<p style="margin-bottom: 0;">When ' + aEnableText + ' staff can choose if they want ' + alerts + ' to be:</p>'; 17871 var li = '<li style="line-height: 1.2;">'; 17872 var ul1 = '<ul>' + li + inApp + inAppEnable + '</li>
17872' + li + 'or ' + text + textEnable + '</li></ul>'; 17873 17874 var msg2 = '<p>Staff can go to their profile in the ' + saApp + ' to enable ' + alerts + '</p>'; 17875 var msg3 = '<p style="margin-bottom: 24px; line-height: 1.2;">Receptionists and admin can view and change ' + alerts + ' settings for each staff ' 17876 + '<span class="narrow-text" style="white-space: normal;">(but only staff can enable ' + inApp + ' on their phone in the ' + saApp + ')</span></p>'; 17877 var msg4 = '<p>Instructions to ' + aEnableInApp + ' in the ' + saApp + '</p>'; 17878 var msg5 = '<p>Instructions to ' + aResetInApp + '</p>'; 17879 17880 return _open('Staff Sign-In & Check-In Alerts', '<div id="pop-help-staff-alerts">' + msg1 + ul1 + msg2 + msg3 + msg4 + msg5 + '</div>'); 17881 } 17882 17883 _conAHelpCal.openHasAppointment = function() { 17884 var h1 = 'Offer Appointments'; 17885 var msg = '<p style="padding-left: 20px; padding-top: 12px;">Check this box if your business schedules appointments with clients</p>'; 17886 17887 return _open(h1, '<div>' + msg + '</div>'); 17888 } 17889 17890 _conAHelpCal.openHasClassOrEvent = function() { 17891 var h1 = 'Classes or Events'; 17892 var msg1 = '<p>Does your business offer classes that your clients can attend or do you have events that your clients attend?</p>'; 17893 var msg2 = '<p>With ' + GLO.Info.getScheduleAnyoneHtm() + ' classes work similar to appointments, the differences are that with classes:</p>'; 17894 17895 var ul = '<ul>' 17896 + '<li>You first create the class, then open the class to add clients</li>' 17897 + '<li>You can add as many clients as you want to a class</li>' 17898 + '<li>If you offer online booking, you set the maximum number of clients that can reserve a spot in the class <small style="display: block;">(although it does not limit how many staff you can add to a class)</small></li>' 17899 + '<li>If you offer online booking clients don\'t create classes, they reserve a spot in classes that you have already created</li>' 17900 + '</ul>' 17901 17902 var aProfileService = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4?helloback=advanced&tabback=calendar\', this)">Profile ' + UI.arrow + ' Service</a>'; 17903 var aCalendar = '<a onclick="GLO.Uri.gotoUri(\'provider/calendar\', this)">Schedule -> Calendar</a>'; 17904 var msg3 = '<p style="line-height: 180%;">Once you have enabled class or events go to ' + aProfileService + ' to create class services, then you can go to ' + aCalendar + ' to create and edit classes</p>'; 17905 17906 return _open(h1, '<div>' + msg1 + msg2 + ul + msg3 + '</div>'); 17907 } 17908 17909 _conAHelpCal.getStartDayOfWeek = function(day, isMobile) { 17910 var dayLabel, day = UTIL.coalesceInt(day, GLO.Data.firstWeekDay); 17911 17912 if (day === 1) { 17913 dayLabel = 'Sunday'; 17914 } else if (day === 2) { 17915 dayLabel = 'Monday'; 17916 } else if (day === 3) { 17917 dayLabel = 'Tuesday'; 17918 } else if (day === 4) { 17919 dayLabel = 'Wednesday'; 17920 } else if (day === 5) { 17921 dayLabel = 'Thursday'; 17922 } else if (day === 6) { 17923 dayLabel = 'Friday'; 17924 } else if (day === 7) { 17925 dayLabel = 'Saturday'; 17926 } 17927 17928 if (isMobile) { 17929 return dayLabel.substring(0,3); 17930 } else { 17931 return dayLabel; 17932 } 17933 } 17934 _conAHelpCal.openWeekStartDayQuick = function() { 17935 var msg = 'The start day of the week is: ' + _conAHelpCal.getStartDayOfWeek(); 17936 var url = 'provider/manage/advanced?open=tab-appointment&highlight=advanced-cal-week-start'; 17937 var btnAdd = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)">Change Start of Week</a></span>'; 17938 var htm = '<div><p>' + msg + '</p><div style="margin-top: 12px; margin-bottom: 24px;">' + btnAdd + '</div></div>'; 17939 17940 GLO.Popup.Info.open(htm); 17941 }
17942 _conAHelpCal.openWeekStartDay = function(isAdvancedProfile) { 17943 var h1 = 'First Day of the Week'; 17944 var aCal = '<a onclick="GLO.Uri.gotoUri(\'provider/calendarOne?sfilter=' + GLO.Info.StaffId + '#vw=agendaWeek\', this)">Calendar\'s Week View</a>'; 17945 var msg0 = '', msg3 = '', msg2 = '', msg1 = '<p style="padding-top: 8px; padding-bottom: 8px;">You can change the first day of the week on your ' + aCal + '</p>'; 17946 17947 if (GLO.Info.providerPackage != 1) { 17948 /* if (GLO.Info.providerPackage === 2 || GLO.Info.providerPackage === 10) { 17949 var rptPayroll = '<a onclick="GLO.Uri.gotoUri(\'report/payroll\', this)">Payroll</a>'; 17950 var rptTimesheet = '<a onclick="GLO.Uri.gotoUri(\'report/timesheet\', this)">Timesheet</a>'; 17951 var rptGoal = '<a onclick="GLO.Uri.gotoUri(\'report/StaffGoal?isActiveStaffOnly=1\', this)">Staff Goals</a>'; 17952 msg2 = '<p>this also changes the week start date on reports: ' + rptPayroll + ', ' + rptTimesheet + ', ' + rptGoal + '</p>'; 17953 } */ 17954 17955 msg3 = '<p>Changing this changes it for all staff members</p>'; 17956 } 17957 17958 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-sun.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>'; 17959 var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-mon.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>'; 17960 var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-tue.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>'; 17961 17962 if (!isAdvancedProfile) { 17963 var link = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/advanced?open=tab-appointment&highlight=advanced-cal-week-start\', this, event, true)">Profile -> Advanced, Appointment tab</a>'; 17964 msg0 = '<div>Change now: ' + link + '</div>'; 17965 } 17966 17967 return _open(h1, '<div>' + msg0 + msg1 + img1 + img2 + img3 + msg2 + msg3 + '</div>'); 17968 } 17969 17970 _conAHelpCal.getStaffOrderList = function(msg) { 17971 var aCalendar = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/calendar\', this, event, true)">Front Desk Calendar</a>'; 17972 var aPos = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)">P.O.S. Screen</a>'; 17973 17974 var urlGallery = UserPortal.getProviderUri() + 'gallery/staff?helloback=advanced&tabback=appointments'; 17975 var aGallery = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlGallery + '\', this, event, true)">Website Staff Gallery</a>'; 17976 17977 msg = '<p id="staff-order-sort-help" style="margin-top: 16px; margin-bottom: 0; padding-bottom: 2px;">' + msg + '</p>'; 17978 17979 return '<div id="staff-order-sort-help">' + msg + '<ul id="staff-order-sort-list-help"> <li>' + aCalendar + '</li> <li>' + aPos + '</li> <li>' + aGallery + '</li> </ul> </div>'; 17980 } 17981 _conAHelpCal.openStaffOrder = function() { 17982 var h1 = 'Staff Order'; 17983 var msg1 = '<p>As staff clock-in they are moved to the start of the staff list on the <b class="narrow-text">P.O.S. Screen</b></p>'; 17984 var msg2 = '<p>By default your staff are displayed in alphabetical order</p>'; 17985 var msg3 = _conAHelpCal.getStaffOrderList('You can change the default order your staff are displayed on'); 17986 17987 return _open(h1, '<div id="pop-help-staff-order">' + msg1 + msg2 + msg3 + '</div>'); 17988 } 17989 17990 return _conAHelpCal; 17991 })(); 17992 17993 17994 _conAdvancedHelp.Payment = (function() { 17995 function _conAHelpPayment() { } 17996 17997 function _currentSelfCheckoutSetting(aCustomApp) { 17998 var aSetting = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/advanced?open=tab-payment&highlight=advanced-payment-self-checkout\', this, event, true)">Self Checkout Setting</a>'; 17999 var msgStyle = ' style="margin-bottom: 0; padding-bottom: 2px; line-height: 1.4;"'; 18000 var msgHtm = '<p' + msgStyle + '>Based on the your ' + aSetting + ' clients can pay for their appointment from the</p>'; 18001 18002 var liLink = '<li>Self-Checkout Link</li>'; 18003 var liWeb = '<li>Client profile on your website</li>'; 18004 var liApp = '<li>' + aCustomApp + '</li>'; 18005 18006 if (GLO.Data.provider.self_checkout_cd < 20) { 18007 liWeb = liApp = ''; 18008 //} else if (GLO.Data.provider.self_checkout_cd > 19 || GLO.Data.provider.self_checkout_cd < 40) { 18009 } else if (GLO.Data.provider.self_checkout_cd > 59) { 18010 //liLink = '<b style="color: red;">Self-Checkout Not Allowed</b>'; 18011 var aInvoiceLink = '<a onclick="GLO.FAQ.gotoQuestion(\'faq-other-pay-invoice-online\', \'other\', this, event)">Text/Email Client Invoice</a>'; 18012 18013 liLink = '<li>Only if ' + aInvoiceLink + '</li>'; 18014 liWeb = liApp = ''; 18015 } 18016 18017 var listStyle = ' style="margin: 0; margin-bottom: 24px; padding-left: 32px; padding-bottom: 2px; line-height: 1.4;"'; 18018 var listHtm = '<ul' + listStyle + '>' + liLink + liWeb + liApp + '</ul>'; 18019 18020 return '<div style="padding-top: 4px; padding-left: 6px; background-color: rgba(20,200,100, .4);">' + msgHtm + listHtm + '</div>'; 18021 } 18022 18023 _conAHelpPayment.openHowSelfCheckoutWorks = function() { 18024 var aApptSurvey = '<a onclick="GLO.Uri.gotoUri(\'repman\', this)">Reputation Management</a>'; 18025 var aCustomApp = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/CustomApp\', this, event, true)">Custom Mobile App</a>'; 18026 var aAllowTip = '<a id="goto-disable-tipping" onclick="GLO.Provider.Advanced.goToItem(\'payment\', \'advanced-payment-product-tip\', this)">Go here to disable tip option</a>'; 18027 var h1 = 'How Self Checkout Works'; 18028 18029 var msg1 = '<p>Allow clients to pay for their appointment on their phone</p>'; 18030 var msg2 = '<p></p>'; 18031 var msg3 = '<p style="margin-bottom: 2px;"></p>'; 18032 18033 var li1 = '<li>When open appointment or ticket select <b>Ready to Pay</b> or <b>Self-Checkout</b> to text client a link they can use to pay online</li>'; 18034 var li2 = '<li>Client clicks link in the text message which opens ticket summary</li>'; 18035 var li3 = '<li>In the ticket summary client presses <b>Pay Now</b></li>'; 18036 var li4 = '<li>
18036Client enters tip amount' + aAllowTip + '</li>'; 18037 var li5 = '<li>Client enters or selects credit card</li>'; 18038 var li6 = '<li>Receipt emailed to client</li>'; 18039 var li7 = '<li>If ' + aApptSurvey + ' enabled, client sees brief appointment survey and if they liked the appointment ' 18040 + UI.arrow + ' the client is sent to your social media to leave a 5 star review!</li>'; 18041 18042 var currentSetting = _currentSelfCheckoutSetting(aCustomApp); 18043 var staffOnlyNote = '<i class="narrow-text">(client not texted self-checkout link and cannot pay on website)</i>'; 18044 18045 var hSettings = '<h3 class="glopop-sub-header">Self Checkout Settings</h3>'; 18046 var opt1 = '<div><label>Require Ready to Pay</label> <span>Client can only pay with link texted to their phone when mark appointment as <b>Ready to Pay</b> or <b>Self-Checkout</b></span> </div>'; 18047 var opt2 = '<div><label>Allow on Day of Appointment</label> <span>Client can pay with self-checkout link and on the day of the appointment on your website or ' + aCustomApp + '</span> </div>'; 18048 var opt3 = '<div><label>Allow Anytime</label> <span>Client can pay with self-checkout link, your website, or ' + aCustomApp + '</span> </div>'; 18049 var opt4 = '<div><label>Staff Use Only</label> <span> <b>Ready to Pay</b> option only used by staff to indicate all services, add-ons, products, etc have been included on ticket and is ready for payment ' + staffOnlyNote + ' </span> </div>'; 18050 var opt5 = '<div><label>Disabled</label> <span>Do Not display <b>Ready to Pay</b> or <b>Self-Checkout</b> options</span></div>'; 18051 18052 var cssSetting = ''; //'padding-top: 8px; border-top: 1px solid;'; //font-size: smaller; 18053 var htmSetting = '<div id="help-self-checkout-options" style="' + cssSetting + '">' + hSettings + currentSetting + opt1 + opt2 + opt3 + opt4 + opt5 + '</div>'; 18054 18055 var hLink = '<h3 class="glopop-sub-header">Ready to Pay + Self-Checkout Link</h3>'; 18056 var p1 = '<p>New appointment status <b class="narrow-text">Ready to Pay</b> can be set on any appointment</p>'; 18057 var p2 = '<p>Marking appointment as <b class="narrow-text">Ready to Pay</b> or <b class="narrow-text">Self-Checkout</b> sends client a text message with a link they can use to pay for their appointment</p>'; 18058 var p3 = '<p>Before client is sent the text message with their <b class="narrow-text">Self-Checkout Link</b> you have option to include a short note in the text message</p>'; 18059 var p4 = '<p>Each <b class="narrow-text">Self-Checkout Link</b> is unique for each appointment</p>'; 18060 var p5 = '<p>The Self Checkout Link also acts as an <b class="narrow-text">automatic login link</b> for your client so they can easily pay with a card-on-file and book their next appointment</p>'; 18061 var htmLink = '<div id="help-self-checkout-options" style="' + cssSetting + '">' + hLink + p1 + p2 + p3 + p4 + p5 + '</div>'; 18062 18063 var hBenefits = '<h3 class="glopop-sub-header">Benefits</h3>'; 18064 var benefit1 = '<p>Helps build your client database: full client name, phone number, email, and card-on-file</p>'; 18065 var benefit2 = '<p>Allows clients to pay comfortably in the chair or room they are receiving services</p>'; 18066 var benefit3 = '<p>Allows faster checkout on days you are busiest</p>'; 18067 var benefit4 = '<p>When used with Reputation management generate more 5 star reviews in Google and Facebook</p>'; 18068 var benefit5 = '<p>Client automatically logged into their profile making it easier for them to book their next appointment</p>'; 18069 var htmBenefits = '<div id="help-self-checkout-benefits" style="' + cssSetting + '">' + hBenefits + benefit1 + benefit2 + benefit3 + benefit4 + benefit5 + '</div>'; 18070 18071 //var imgCSS = 'width: 90%; max-width: 480px; margin: 0; margin-left: -8px; padding: 2px 4px; border: 1px inset grey; border-radius: 8px;'; 18072 //var img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/online-booking-appointment-search.png" style="' + imgCSS + '"/> </div>'; 18073 18074 var jpop = _open(h1, '<div id="pop-help-self-checkout">' + msg1 + msg2 + msg3 + '<ol>' + li1 + li2 + li3 + li4 + li5 + li6 + li7 + '</ol>' + htmSetting + htmLink + htmBenefits + '</div>'); 18075 _conAdvancedHelp.realign(); 18076 } 18077 18078 return _conAHelpPayment; 18079 })(); 18080 18081 18082 _conAdvancedHelp.Online = (function() { 18083 function _conAHelpOnline() { } 18084 18085 _conAHelpOnline.openOnlineBookingGuide = function(stepNumber) { 18086 SA.Help.openReportHelp('#pop-how-to-guide-online-booking', stepNumber, 'info/HelpGuide?name=OnlineBookingHelp'); 18087 } 18088 18089 _conAHelpOnline.openAppointmentSearch = function() { 18090 var h1 = 'Online Booking Appointment Search'; 18091 18092 var msg1 = '<p>When client books online they cannot see your schedule</p>'; 18093 var msg2 = '<p>Client enters desired appointment then searches for best available opening</p>'; 18094 var msg3 = '<p style="margin-bottom: 2px;">
18094To book online, client enters</p>'; 18095 var li1 = '<li>Desired service(s)</li>'; 18096 var li2 = '<li>Desired staff <small>(or can leave blank if want first available)</small></li>'; 18097 var li3 = '<li>Day and time <small>(or can leave blank if want first available)</small></li>'; 18098 var li4 = '<li>Press search to see best available openings</li>'; 18099 var li5 = '<li>Select desired opening</li>'; 18100 18101 var imgMsg = '<p style="margin: 0; text-align: center; font-style: italic;">Sample screenshot of Client Booking Online</p>'; 18102 var imgCSS = 'width: 90%; max-width: 480px; margin: 0; margin-left: -8px; padding: 2px 4px; border: 1px inset grey; border-radius: 8px;'; 18103 var img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/online-booking-appointment-search.png" style="' + imgCSS + '"/> </div>'; 18104 18105 var jpop = _open(h1, '<div id="pop-help-appointment-search">' + msg1 + msg2 + msg3 + '<ol>' + li1 + li2 + li3 + li4 + li5 + '</ol>' + imgMsg + img + '</div>'); 18106 _conAdvancedHelp.realign(); 18107 18108 setTimeout(function() { 18109 GLO.Provider.Advanced.Help.realign(); 18110 }, 1200); 18111 } 18112 18113 _conAHelpOnline.openEnableWaitListForClients = function() { 18114 var h1 = 'Client Access to Waiting List'; 18115 18116 var msg1 = '<p>You can give clients access to add and remove themselves from your waiting list</p>'; 18117 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list-add.jpg" style="min-height: 120px; width: 90%; max-width: 420px;"/> </div>'; 18118 18119 var aOnClick = 'GLO.Uri.gotoUri(\'provider/WebTemplate/ConfigureLogin?back=%2fwizard%2fwebsite&helloback=website\', this)'; 18120 var aAdjustColors = '<a onclick="' + aOnClick + '" style="border-bottom: none;">(adjust colors here)</a>'; 18121 var smallAdjustColors = '<small style="padding-left: 12px;">' + aAdjustColors + '</small>'; 18122 var b1 = '<b style="padding: 2px 8px; white-space: nowrap; color: rgb(255,232,240); background-color: #9A26FF;">Add Me to the Waiting List</b>'; 18123 var msg2 = '<p style="margin-bottom: 20px;">After clients create an account and login clients will see a bar at the top that says: ' + b1 + smallAdjustColors + '</p>'; 18124 var msg3 = ''; 18125 18126 var msg4 = '<p>You have the option to allow clients to be able to request a specific date/time when adding themselves to your waiting list</p>'; 18127 var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list-popup.jpg" style="min-height: 360px; width: 80%; max-width: 280px;"/> </div>'; 18128 18129 var msg5 = '<p>Clients can see how many people are on your waiting list</p>'; 18130 var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list2.jpg" style="min-height: 120px; width: 90%; max-width: 420px;"/> </div>'; 18131 18132 return _open(h1, '<div>' + msg1 + msg2 + msg3 + img1 + msg4 + img2 + msg5 + img3 + '</div>'); 18133 } 18134 18135 _conAHelpOnline.openNotifyClientWhen = function() { 18136 var h1 = 'Notify Client When They Are Next'; 18137 18138 var x = '<span style="display: inline-block;" class="ui-icon ui-icon-circle-close" title="click to delete this row from the waiting list"></span>'; 18139 //var plusCSS = 'width: 36px; height: 36px; text-align: center; font-size: 32px;' 18140 //var plus = '<span class="wait-list-create-appt" title="Create Appointment & Remove from Waiting List"> <b style="' + plusCSS + '">+</b> </span>'; 18141 var spanDotStyle = 'min-width: 40px; padding: 0 2px; line-height: 120%; text-align: center; border-radius: 20px;'; 18142 var dotCreate = '<span class="wait-list-create-appt" style="' + spanDotStyle + ' margin-right: 2px;"><b style="height: inherit; width: 42px; padding: 1px 2px 3px; font-size: 16px;">new</b></span>'; 18143 var dotCheckin = '<span class="wait-list-create-appt wait-list-checkin-appt" style="' + spanDotStyle + '"><b style="height: inherit; width: 36px; font-size: 16px;">pre</b></span>'; 18144 18145 var msg1 = '<p>When you remove a client from the waiting list, you can have ' + GLO.Info.getScheduleAnyoneHtm(
18145) + ' send a text to the next client(s)</p>'; 18146 var msg2 = '<p>There are 3 ways to remove a client from the waiting list:</p>'; 18147 var msg3b = '<ul><li><small>Also in text message sent to the next client(s), includes an estimate start time</small></li></ul>'; 18148 var msg3 = '<ul>' 18149 + '<li style="list-style-type: decimal;">Press the ' + x + ' to the left of the client name to remove from wait list</li>' 18150 + '<li style="list-style-type: decimal;">Press the ' + dotCheckin + ' to sign-in pre-booked appointment and remove from wait list</li>' 18151 + '<li style="list-style-type: decimal;">Press the ' + dotCreate + ' to create appointment and remove from wait list</li>' 18152 + '</ul>'; 18153 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/waiting-list-staff-view2.jpg" style="min-height: 120px; width: 90%; max-width: 600px;"/> </div>'; 18154 18155 var codeCSS = 'display: block; margin: 4px; margin-left: 24px; white-space: pre-wrap; color: darkgreen;'; 18156 var textSample = '<code style="' + codeCSS + '">Hi Mary! You are next on the waiting list for TriBeCa Salon, estimated start time is 5:15 pm at 146 E 56th St New York, NY</code>'; 18157 var msg4 = '<p>Here is an example of the text message sent to the client: ' + textSample + '</p>' 18158 18159 var msg5css = 'margin-top: 12px; margin-bottom: 0; padding-top: 6px; text-align: center; border-top: 2px solid white; font-size: 85%; opacity: .8;'; 18160 var msg5 = '<p style="' + msg5css + '">This only applies to client\'s on <b style="color: #4F81BD;">Today\'s Waiting List</b></p>'; 18161 18162 return _open(h1, '<div>' + msg1 + msg2 + msg3 + img1 + msg4 + msg5 + '</div>'); 18163 } 18164 18165 _conAHelpOnline.openWaitingListToday = function() { 18166 var h1 = 'Today\'s Waiting List'; 18167 var uriSignIn = UserPortal.getProviderUri() + 'SignIn?open=help-overview'; 18168 var aSignIn = '<a href="' + uriSignIn + '" style="font-weight: bold; color: deeppink; border-color: deeppink;">Client Sign-In Screen</a>'; 18169 var today = '<b style="font-style: italic; color: #4F81BD;">Today\'s Waiting List</b>'; 18170 18171 var msg1 = '<p>The ' + today + ' feature allows you to have a sub-section of the waiting list dedicated to the current day</p>'; 18172 var msg2 = '<p>This feature is great on busy days to help you keep track of who is next; enable and disable ' + today + ' as desired</p>'; 18173 var msg3 = '<p>Turning on ' + today + ' also enables the ' + aSignIn + ' which allows clients to sign-in themselves at your front desk</p>'; 18174 var msg4 = '<p>If you also enable clients to have access to the waiting list, then clients can add themselves to ' + today + '</p>'; 18175 var msg5 = '<p>You can even have ' + GLO.Info.getScheduleAnyoneHtm() + ' send a text to the next client(s) on ' + today + '</p>'; 18176 18177 if (GLO.Info.providerPackage == 1) { 18178 msg3 = ''; 18179 } else if (GLO.Info.providerPackage == 4) { 18180 msg4 = msg5 = ''; 18181 } 18182 18183 return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>'); 18184 } 18185 18186 _conAHelpOnline.openCustomAppChanges = function() { 18187 var h1 = 'Custom App Changes'; 18188 var msg1 = '<p>When your app is opened it checks with ' + GLO.Info.getScheduleAnyoneHtm() + ' to see if anything has changed</p>'; 18189 var msg2 = '<p>If you change your profile and do not see the changes in the app just <i style="color: #4F81BD;">kill the app</i>, and re-open it</p>'; 18190 18191 var pCSS = ' style="margin-left: 2%; margin-bottom: 0;"' 18192 18193 var msg3 = '<div style="margin-top: 32px;">' 18194 + '<h4 style="padding-left: 0; text-align: left;">How Do I Kill An App?</h4>' 18195 + '<p' + pCSS + '><b>On an iPhone or iPad:</b> <ol style="margin-left: 8%;"> <li>Double click the home button</li> <li>Swipe the app up</li> </ol> </p>' 18196 + '<p' + pCSS + '><b>On an Android:</b> <ol style="margin-left: 8%; margin-bottom: 0;"><li>Launch the recent applications menu</li> <li>Swipe the app to the right</li> </ol> </p>' 18197 + '</div>'; 18198 18199 return _open(h1, '<div>' + msg1 + msg2 + msg3 + '</div>'); 18200 } 18201 18202 _conAHelpOnline.openClientApptRestrictions = function() { 18203 var jpage = $('#advanced-online-booking'); 18204 var isAdvancedProfile = true, footer = ''; 18205 18206 if (jpage.length === 0) { 18207 isAdvancedProfile = false;
18208 jpage = $('#aob-client-restrictions'); 18209 } 18210 18211 var chr = UTIL.coalesceInt(jpage.find('#Create_Appt_Hr_nr').val(), jpage.find('#Provider_Create_Appt_Hr_sr').val()); 18212 var uhr = UTIL.coalesceInt(jpage.find('#Update_Appt_Hr_nr').val(), jpage.find('#Provider_Update_Appt_Hr_sr').val()); 18213 18214 if (UTIL.coalesceInt(chr, 0) === 0) { 18215 chr = '5 minutes'; 18216 } else { 18217 chr = chr + ' hours'; 18218 } 18219 18220 if (UTIL.coalesceInt(uhr, 0) === 0) { 18221 uhr = '5 minutes'; 18222 } else { 18223 uhr = uhr + ' hours'; 18224 } 18225 18226 var h1 = 'Client Restrictions'; 18227 var msg0 = _warnMessageOnlineBookingDisabled(jpage); 18228 var msg = '<p style="margin-top: 8px; margin-bottom: 4px;">' + msg0 + 'You are setup to allow clients to:</p>'; 18229 18230 var li1 = '<li>Create appointments that start more than ' + chr + ' from right now</li>'; 18231 var li2 = '<li>Update appointments that start more than ' + uhr + ' from right now</li>'; 18232 18233 if (GLO.Info.providerPackage != 1) { 18234 footer = '<div style="margin-bottom: 12px; color: #888;">'; 18235 18236 if (isAdvancedProfile) { 18237 footer += 'This can be set per staff member by going to <a href="/provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column">Profile ' + UI.arrow + ' Staff</a></div>'; 18238 } else { 18239 footer += 'If empty, uses the values set at <a href="/provider/manage/advanced#open=tab-online-booking">Profile ' + UI.arrow + ' Advanced</a></div>'; 18240 } 18241 } 18242 18243 return _open(h1, '<div>' + msg + '<ul>' + li1 + li2 + '</ul>' + footer + '</div>'); 18244 } 18245 18246 function _warnMessageOnlineBookingDisabled(jpage) { 18247 if (!jpage.find('#Online_Booking_fl').prop('checked')) { 18248 return '<b style="color: green;">If you enable online booking</b> '; 18249 } else { 18250 return ''; 18251 } 18252 } 18253 18254 _conAHelpOnline.openSearchResults = function() { 18255 var jpage = $('#advanced-online-booking'); 18256 var cnt = UTIL.coalesceInt(jpage.find('#Search_Result_Limit_sr').val(), 5); 18257 var allDay = jpage.find('#Search_Result_Entire_Day_fl').prop('checked'); 18258 18259 var msg0 = _warnMessageOnlineBookingDisabled(jpage); 18260 18261 var h1 = 'Client Search Results'; 18262 18263 var msg1 = '<p>When clients search for an appointment set how many appointment options do you want to show them in the search results?</p>'; 18264 var msg2 = '<div style="margin: 8px 0; padding: 12px; padding-right: 4px; background-color: pink;">' 18265 18266 if (allDay) { 18267 msg2 += 'Currently clients are shown all available appointments on the selected day (up to 20 openings) or if less than ' + cnt + ' results are available on the specified day than other days are searched until ' + cnt + ' openings are found</div>'; 18268 } else { 18269 msg2 += 'Currently clients are shown ' + cnt + ' search results</div>'; 18270 } 18271 18272 var msg3 = '<p>When clients book an appointment with you online they cannot see your schedule; they enter their desired date and time and then search for the appointment opening that best matches</p>'; 18273 18274 var jpop = _open(h1, '<div>' + msg0 + msg1 + msg2 + msg3 + '</div>', true); 18275 } 18276 18277 _conAHelpOnline.openSearchStaffPriority = function() { 18278 var h1 = 'Staff Priority'; 18279 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 18280 18281 var urlCommissionReport = 'provider/manage/CommissionByStaffService?highlight=commission-column-is-employee&helloback=advanced&tabback=online-booking'; 18282 var aCommissionReport = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlCommissionReport + '\', this, event, true)">Payroll Setup</a>'; 18283 18284 var msg1 = '<p>When searching for appointments, you can prioritize commission and hourly staff before independent staff <small>(like booth renters)</small></p>'; 18285 var msg2 = '<p>This only applies if you have both commission and non-commission staff</p>'; 18286 18287 if (mt > 9 && mt < 20) { 18288 var msg3 = '<p style="margin-top: 32px; letter-spacing: 0;"><i>By default</i>, staff not assigned to the <b>House Merchant Account</b> are considered <b>Independent staff</b></p>'; 18289 var msg4 = '<p style="letter-spacing: 0;">You can override this default by checking/un-checking the <b>Employee checkbox</b> next to each staff on the ' + aCommissionReport + '</p>'; 18290 } else { 18291 var msg3 = '<p> </p>'; 18292 var msg4 = '<p>You can set who is an <b>Employee</b> or <b>Independent</b> staff by <i style="letter-spacing: 0;">checking/un-checking</i> the <b>Employee checkbox</b> next to each staff on the ' + aCommissionReport + '</p>'; 18293 } 18294 18295 return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + '</div>'); 18296 } 18297 18298 _conAHelpOnline.openSearchFinishTime = function() { 18299 var h1 = 'Processing / Finish Restrictions'; 18300 var msgA = 'Do you want to allow clients to be able to book appointments when the processing or finish out time will extend beyond the'; 18301 18302 if (GLO.Info.providerPackage == 1) { 18303 msgA += ' your'; 18304 } else { 18305 msgA += ' staff or business'; 18306 } 18307 18308 msgA = '<div style="margin-bottom: 12px; padding: 4px; padding-left: 20px; border-bottom: 1px solid #444; background-color: pink;">' + msgA + ' normal closing time?</div>'; 18309 18310 var msg1 = '<p>This setting only affects services that have a processing or finish out time</p>'; 18311 var aProfileSvc = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4?helloback=advanced&tabback=online-booking\', this)">Profile ' + UI.arrow + ' Service</a>'; 18312 var msg2 = '<p style="margin-top: 12px; margin-bottom: 2px;">Add processing and/or finish out to any service by going to ' + aProfileSvc + '</p>'; 18313 var liCSS = ' style="text-indent: -4px;"'; 18314 var ol = '<ol style="margin-left: 60px;">' 18315 + '<li' + liCSS + '>Click the desired service</li>' 18316 + '<li' + liCSS + '>Press the more button</li>' 18317 + '<li' + liCSS + '>Enter the desired processing / finish out minutes</li>' 18318 + '</ol>'; 18319 18320 var jpop = _open(h1, '<div>' + msgA + msg1 + msg2 + ol + '</div>', true); 18321 } 18322 18323 _conAHelpOnline.openAllowOnlineBooking = function() { 18324 //var book-online-url 18325 18326 if (GLO.Info.providerPackage == 1) { 18327 var page = 1, pageText = 'Profile ' + UI.arrow + ' Me', pageStep = ' and click on the "Client Setup" button'; 18328 } else { 18329 var page = 5, pageText = 'Profile ' + UI.arrow + ' Staff', pageStep = ' and click on the <b>Clients</b> column for each staff member'; 18330 } 18331 18332 var h1 = 'Enable Online Booking'; 18333 var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/' + page + '?helloback=advanced&tabback=online-booking\', this)">' + pageText + '</a>'; 18334 var msg1 = '<p>Check the box to Allow clients to book online</p>'; 18335 18336 var aHow = '<a onclick="GLO.Provider.Advanced.Help.Online.openAppointmentSearch()">How Online Booking Works</a>'; 18337 var divHow = '<div style="margin-bottom: 16px; text-align: center; letter-spacing: 1px; font-weight: bold;">' + aHow + '</div>'; 18338 18339 var list1 = '<ol> <h4>Customize Online Booking</h4>'; 18340 var li1 = '<li>Go to ' + aProfile + pageStep + ' to restrict when and which clients can book online</li>'; 18341 18342 var abanner = '<a onclick="GLO.Uri.gotoUri(\'help?helloback=advanced&tabback=online-booking#tab=profile&id=web-template-add-banner\', this)">Book Appointment banner</a>'; 18343 var abutton = '<a onclick="GLO.Uri.gotoUri(\'help?helloback=advanced&tabback=online-booking#tab=profile&id=web-template-add-button\', this)">Book Appointment button</a>'; 18344 var li2 = '<li>Add a ' + abanner + ' or a ' + abutton + ' to your website</li>'; 18345 18346 var aChangeLink = '<a onclick="GLO.Uri.gotoUri(\'wizard/website?helloback=advanced&tabback=online-booking#step=\', this)">Change where</a>'; 18347 var li3 = '<li>' + aChangeLink + ' your customers go to book appointments with you</li>'; 18348 18349 var aConfigureCportal = '<a onclick="GLO.Uri.gotoUri(\'provider/WebTemplate/ConfigureLogin?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this)">
18349what your clients see</a>'; 18350 var li4 = '<li>Customize ' + aConfigureCportal + ' when they create appointments with you</li>'; 18351 18352 //var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-create-appt.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>'; 18353 var msg = divHow + msg1 + list1 + li1 + li2 + li3 + li4 + '</ol>' 18354 18355 return _open(h1, '<div>' + msg + '</div>').attr('id', 'pop-help-allow-online-booking'); 18356 } 18357 18358 _conAHelpOnline.openAllowRequestAppt = function() { 18359 var h1 = 'Request Appointment Page'; 18360 var msg2 = '', msg1 = '<p>' + GLO.Info.getScheduleAnyoneHtm() + ' automatically creates this request appointment page allowing clients to request appointments</p>' 18361 18362 var msg1b = '<p>When a client requests an appointment using this page ' + GLO.Info.getScheduleAnyoneHtm() + ':' 18363 + '<ul style="">' 18364 + '<li>Adds the appoinment request to your <a onclick="GLO.Uri.gotoUri(\'/provider/apptportal?tab=wait\', this)">Waiting List</a></li>' 18365 + '<li>Send you an email that allows you to accept the appointment request</li>' 18366 + '</ul></p>'; 18367 18368 if (GLO.Info.providerPackage != 1) { 18369 var aBizEmail = '<a onclick="GLO.Uri.gotoUri(\'/provider/profile/2?helloback=advanced&tabback=online-booking\', this)">Business Email</a>'; 18370 msg2 = '<p>If a ' + aBizEmail + ' is set then the appointment request will be sent to that email, otherwise the email is sent to all the managers and admins in ' + GLO.Info.getScheduleAnyoneHtm() + '</p>'; 18371 } 18372 18373 var aConfigureCportal = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/ConfigureLogin?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this, event, true)">Online Booking Configuration</a>'; 18374 var aRequestApptSetting = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/RequestApptSetting?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this, event, true)">Request Appointment Settings</a>'; 18375 var msg3 = '<p>You can customize this page by going to the ' + aConfigureCportal + ' and ' + aRequestApptSetting + '</p>'; 18376 18377 return _open(h1, '<div>' + msg1 + msg1b + msg2 + msg3 + '</div>'); 18378 } 18379 18380 _conAHelpOnline.openAllowIndependentStatusChange = function() { 18381 var h1 = 'Independent Staff Permissions: Client Setup'; 18382 var msg1 = '<p>Do you want to allow your independent staff (staff with <a href="/hello/StaffRole">the Independent Role</a>) to set their:</p>'; 18383 var ul = '<ul>' 18384 + '<li>Online booking status</li>' 18385 + '<li>When/If email and text reminders are sent</li>' 18386 + '<li>If client confirmation emails are sent when appointments are created and/or updated</li>' 18387 18388 var imgCSS = 'max-width: 600px; min-height: 400px; width: 100%; margin-bottom: 4px; border-radius: 20px;'; 18389 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/Independent-Staff-Permissions-Client-Setup.jpg" style="' + imgCSS + '"/> </div>'; 18390 18391 return _open(h1, '<div>' + msg1 + ul + img + '</div>'); 18392 } 18393 18394 _conAHelpOnline.openProductVariantGuide = function() { 18395 SA.Help.openReportHelp('#pop-how-to-guide-product-variations', 0, 'info/HelpGuide?name=ProductVariations'); 18396 // $('.pop-modal').css('left','50px') 18397 18398 } 18399 18400 return _conAHelpOnline; 18401 })(); 18402 18403 18404 _conAdvancedHelp.Client = (function() { 18405 function _conAHelpClient() { } 18406 18407 _conAHelpClient.openAddressConfig = function() { 18408 //var msg1 = '<p>Based on your type of business the client address setting has been set automatically, but you can change it as desired</p>'; 18409 var addressFields = '<b>address fields <b class="narrow-text">(street, city, state, postal code, country)</b></b>'; 18410 var intro = '<p>When clients and staff create a new client profile do you want to display ' + addressFields + ' in the new client form?</p>' 18411 + '<p>Should address be required when creating a new client profile?</p>' 18412 + '<p>Should address be required when <a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/RequestApptSetting\', this, event, true)">clients request appointment</a>?</p>' 18413 var amerge = ''; 18414 + '<p>Should staff see directions to client address?</p>'; 18415 18416 var hDisplay = '<h2>When Display + Require Client Address</h2>'; 18417 var thead = '<thead> <tr> <th></th> <th>Display on<br/>New Client Form</th> <th>Require on<br/>New Client Form</th> <th>Display on<br/>Client Profile</th> <th>Staff Can<br/>See Directions</th> </tr> </thead>'; 18418 var tblDisplay = '<table id="client-address-config-table">' + thead + '<tbody>' 18419 + '<tr> <th>Display Address On Profile Only</td> <td class="display-new-client"></td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions"></td> </tr>' 18420 + '<tr> <th>Display Directions to Staff</td> <td class="display-new-client"></td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>' 18421 + '<tr> <th>Display On New Client Form, No Directions</td> <td class="display-new-client">x</td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions"></td> </tr>' 18422 + '<tr> <th>Display on New Client Form</td> <td class="display-new-client">x</td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>' 18423 + '<tr> <th>Require On New Client Form</td> <td class="display-new-client">x</td> <td class="require-new-client">x</td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>' 18424 + '</tbody></table>'; 18425 18426 var hDirections = '<h2>See Directions</h2>'; 18427 var cssGetDirections = 'padding: 0 8px; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; background-color: #139ad2; color: white;'; 18428 var msgDirections = '<p style="margin-bottom: 0;">If enabled, you can easily see directions to the client\s address by:</p>'; 18429 var listDirection = '<ol style="margin-left: 48px;">' 18430 + '<li>Open client\'s appointment or client\'s profile</li>' 18431 + '<li>Press triangle to right of the client name</li>' 18432 + '<li>Select <b style="' + cssGetDirections + '">Get Directions</b></li>' 18433 + '</ol>'; 18434 var imgDirections = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/edit-appointment-get-directions.png" style="max-width: 320px; min-height: 240px; width: 100%;"/> </div>'; 18435 18436 var header = 'Client Address Display Information'; 18437 var htm = '<div>' + intro + hDisplay + tblDisplay + hDirections + msgDirections + listDirection + imgDirections + '</div>'; 18438 return _open(header, htm).attr('id', 'pop-client-address-config'); 18439 } 18440 18441 _conAHelpClient.openHasBiz = function() { 18442 var h1 = 'Enable Business Clients'; 18443 18444 var msg1 = '<p>Enabling business clients allows you to go to a client profile and select if they are male, female, or a business</p>'; 18445 var msg2 = '<p>You can go to a business client profile and set if that business is taxable or not</p>'; 18446 var msg3 = '<p>Business clients by default are not taxable - so tickets (appointments and product sales) for business clients will not include taxes</p>'; 18447 18448 return _open(h1, '<div>' + msg1 + msg2 + msg3 + '</div>'); 18449 } 18450 18451 _conAHelpClient.openEasyLogin = function() { 18452 var h1 = 'Easy Login'; 18453 var pstart = '<p style="line-height: 1.4;">'; 18454 var bEasyLogin = '<b class="narrow-text">Easy Login</b>'; 18455 var htmArrow = ' <b style="display: inline-block; padding-left: 6px; padding-right: 6px;">➜</b> '; 18456 18457 var msg1 = pstart + 'Simplifies clients logging into ' + GLO.Info.getScheduleAnyoneHtm(
18457) + ' to book appointments with you'; 18458 var msg2 = pstart + '<span style="padding-right: 4px; color: #4F81BD;">When ' + bEasyLogin + ' Enabled</span>' 18459 + 'returning clients can simply use your new client form to automatically log into their existing profile' 18460 + htmArrow + 'if their name and phone matches, unless the client has a</p>'; 18461 var list = '<ul class="narrow-list"> <li>gift card</li> <li>card-on-file</li> <li>membership</li> </ul>'; 18462 18463 return _open(h1, '<div>' + msg1 + msg2 + list + '</div>'); 18464 } 18465 _conAHelpClient.openNewClientForm = function() { 18466 var h1 = 'New Client Form'; 18467 18468 var pstart = '<p style="line-height: 1.4;">'; 18469 var pstartSmall = '<p style="margin-left: 40px; margin-top: 0; margin-bottom: 32px; padding-top: 0; line-height: 1.4; letter-spacing: 0; font-size: 90%;">'; 18470 var b = '<b class="narrow-text">'; 18471 var bsimple = '<b class="narrow-text" style="font-size: larger; color: blue;">Simple Client Form</b>'; 18472 var bstandard = '<b class="narrow-text" style="font-size: larger; color: blue;">Standard Form</b>'; 18473 18474 var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&popup=how-to-guide-online-booking&step=15\')'; 18475 var aAutoLink = '<a class="narrow-text" onclick="' + fnAutoLink + '">Automatic Login Link</a>'; 18476 18477 var msg1 = pstart+ 'The ' + bsimple + ' is the fastest way to create new clients for both your staff and online</p>' 18478 var msg1b = pstartSmall+ 'When clients create an account' 18479 + ' <span class="narrow-text">(if you allow online booking)</span>' 18480 + ' the username/password is automatically created <span class="narrow-text">(username is usually the email)</span>' 18481 + ' - but with ' + aAutoLink + ' clients never need to know their <span class="narrow-text">Username</span> or <span class="narrow-text">Password</span><p>'; 18482 18483 var msg2 = pstart+ 'The ' + bstandard + ' contains the extra fields: ' + b + 'Username</b> + ' + b + 'Password</b></p>'; 18484 18485 return _open(h1, '<div id="pop-help-new-client-form-type" style="letter-spacing: 0;">' + msg1 + msg1b + msg2 + '</div>'); 18486 } 18487 18488 _conAHelpClient.openReferByClient = function() { 18489 var h1 = 'Refer by Client'; 18490 var msg1 = '<p>When enabled adds <b>Referred by Client</b> button when creating new clients and checking out new clients</p>'; 18491 var msg2 = '<p>Adds button to lookup referring client using the referring client\'s phone number</p>'; 18492 var msg3 = '<p></p>'; 18493 18494 var msg4 = '<p>Can automatically give new client a gift voucher + send referring client a gift voucher</p>'; 18495 var msg5 = '<p></p>'; 18496 //var msg6 = '<p></p>'; 18497 18498 return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>'); 18499 } 18500 18501 _conAHelpClient.openPhoneSync = function() { 18502 var h1 = 'Sync Client List From Phone'; 18503 var msg2 = '<p>You can disable that feature here: so no sync will occur</p>'; 18504 var msg4 = '<div style="margin-top: 12px; margin-bottom: 20px;"> <span class="btnDeleteSyncClients btnAdd" onclick="GLO.Provider.Advanced.deleteSyncedClients()"> <a>Remove Clients Synced From Phone</a> </span> </div>'; 18505 18506 if ($.cookies.get('pid') == 70 && (GLO.Info.isIPhone || GLO.Info.isIPad) && GLO.Info.isIosApp) { 18507 msg4 += '<div style="margin-top: 2px; margin-bottom: 20px;"> <span class="btnSyncClientList btnAdd" onclick="SA.App.GetContacts(true)"> <a>Sync Client List from this Device</a> </span> </div>'; 18508 } 18509 18510 if (GLO.Info.providerPackage == 1) { 18511 var msg1 = '<p>When you login to the ' + GLO.Info.getScheduleAnyoneHtm() + ' App on your iPhone or iPad it asks if you want to sync the client list from your phone/iPad to ' + GLO.Info.getScheduleAnyoneHtm() + '</p>'; 18512 var msg3 = '<p style="margin-top: 20px;">Do you want to delete all clients synced from your phone, that do not have an appointment or product purchase?</p>'; 18513 } else { 18514 var msg1 = '<p>When you or your staff login to the ' + GLO.Info.getScheduleAnyoneHtm(
18514) + ' App on your iPhone or iPad it asks if you want to sync the client list from your phone/ipad to ' + GLO.Info.getScheduleAnyoneHtm() + '</p>'; 18515 var msg3 = '<p style="margin-top: 40px;">Do you want to delete all clients synced from staff phones, that do not have an appointment or product purchase?</p>'; 18516 } 18517 18518 return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + '</div>'); 18519 } 18520 18521 _conAHelpClient.openMergeHelp = function() { 18522 var h1 = 'Merge Clients'; 18523 var hStreamline = '<h3>' + GLO.Info.getScheduleAnyoneHtm() + ' Helps Streamline Your Client List</h3>'; 18524 18525 if (GLO.Info.providerPackage == 1) { 18526 var labelYou = 'You'; 18527 var msg4b = ''; 18528 } else { 18529 var labelYou = 'Staff'; 18530 var msg4b = '<p>Staff with the role Receptionist, Manager, or Admin can merge client profiles</p>'; 18531 } 18532 18533 var btnViewDuplicates = '<span class="btnAdd"> <a onclick="GLO.Provider.Advanced.Help.Client.openProcessMerge()">Lookup Duplicate Clients</a></span>'; 18534 var btnMerge = '<span class="btnAdd"> <a onclick="GLO.Provider.Advanced.Help.Client.openProcessMerge(true)">Merge Duplicate Clients</a></span>'; 18535 18536 var msg0 = '<p>If attempting to create a duplicate client account, a list of similar clients are displayed to see if it is better to use an existing client account or create a new one</p>'; 18537 var msg1 = '<p>Every weekend your duplicate clients are automatically merged via a <b>Normal Merge</b>; you can also ' + btnViewDuplicates + ' and ' + btnMerge + '</p>'; 18538 var msg2 = '<p>A client is considered duplicate if another client profile has the same name and phone, email, or street address (or is empty)</p>'; 18539 var msg3 = '<p>When two client accounts are merged their profile, tickets (appointments and product purchases), waiting list requests, notes, loyalty points, and gift cards are merged into one client account</p>'; 18540 18541 var hSpecific = '<h3>Merge Specific Clients</h3>'; 18542 var msg4 = '<p>' + labelYou + ' can go to a client\'s profile and at the bottom of the profile press the merge button then select another client account to merge with</p>'; 18543 18544 return _open(h1, '<div>' + hStreamline + msg0 + msg1 + msg2 + msg3 + hSpecific + msg4 + msg4b + '</div>'); 18545 } 18546 18547 _conAHelpClient.openProcessMerge = function(isMerge) { 18548 if (GLO.Info.providerPackage != 1 && new Date().addDays(-180) > new Date(GLO.Data.provider.createDate)) { 18549 var warnHeader = '<div style="margin-bottom: 24px; color: rgb(240,0,0);">Merging Client List only allowed before 10 am EST or after 7pm PST</div>'; 18550 } else { 18551 var warnHeader = ''; 18552 } 18553 18554 var rdoNormal = '<input type="radio" name="mergeType" id="normalMerge" value="normal" checked="checked"/>'; 18555 var labelNormal = '<label for="normalMerge"><b>Normal Merge</b> <small>Merge Clients with the same name where the phone, email, or street address match (must be empty or if exist must match)</small></label>'; 18556 18557 var rdoExtreme = '<input type="radio" name="mergeType" id="extremeMerge" value="extreme"/>'; 18558 var labelExtreme = '<label for="extremeMerge"><b>Extreme Merge</b> <small>Merge any client with the same phone number (warning this will merge clients with different names who might share the same phone number)</small></label>'; 18559 18560 var divStart = '<div class="rdo-advanced">'; 18561 var divMergeType = '<div id="process-merge-type"><h3>Merge Type</h3>' + divStart + rdoNormal + labelNormal + '</div>' + divStart + rdoExtreme + labelExtreme + '</div></div>'; 18562 18563 var rdoMergeView = '<input type="radio" name="MergeOrView" id="isMergeView" value="mergeview"/>'; 18564 var labelMergeView = '<label>' + rdoMergeView + 'Lookup Duplicate Clients (Do Not Merge)</label>'; 18565 18566 var rdoMerge = '<input type="radio" name="MergeOrView" id="isMerge" value="ismerge"/>'; 18567 var labelMerge = '<label>' + rdoMerge + 'Merge Duplicate Clients</label>'; 18568 18569 var divMergeOrView = '<div id="process-merge-or-view"><h3>Lookup or Merge</h3>' + divStart + labelMergeView + '</div>' + divStart + labelMerge + '</div></div>'; 18570 var btnProcessInner = '<a onclick="GLO.Provider.Advanced.Help.Client.processMerge()" style="display: inline-block;">Process Now</a>'; 18571 var btnProcess = '<span id="btnProcessMerge" class="btnSave" style="margin: 0; margin-right: 120px;">' + btnProcessInner + '</span>'; 18572 18573 var htm = '<div id="pop-merge-duplicates">' + warnHeader + divMergeType + divMergeOrView + '</div>'; 18574 var jpop = GLO.Popup.Custom.openSimple(htm, 'Merge Client List'); 18575 var jbtns = jpop.find('.pop-buttons'); 18576 18577 jbtns.find('.btnSave').remove(); 18578 jbtns.css({ "margin-top": "32px" }).prepend(btnProcess); 18579 18580 if (isMerge) { 18581 jpop.find('#isMerge').prop('checked', true); 18582 } else { 18583 jpop.find('#isMergeView').prop('checked', true); 18584 } 18585 } 18586 18587 _conAHelpClient.processMerge = function() { 18588 if (!_conAdvanced.canSaveChanges()) { _conAdvanced.initReadOnlyCheck(); return; } 18589 18590 var jpop = $('#pop-merge-duplicates').closest('.glopop'); 18591 var isMerge = jpop.find('#isMerge').is(':checked'); 18592 var isExtreme = jpop.find('#extremeMerge').is(':checked'); 18593 18594 if (isMerge) { 18595 var fnYes = function() {
18596 GLO.Provider.Advanced.Help.Client.processMergeConfirmed(isMerge, isExtreme); 18597 } 18598 var fnNo = function() { 18599 GLO.Popup.close($('#pop-confirm-merge-clients').closest('.glopop')); 18600 18601 jpop.find('#isMergeView').prop('checked', true); 18602 jpop.find('#btnProcessMerge > a').click(); 18603 } 18604 18605 var htm = '<p>Merge Cannot be Un-Done</p><p>Would you first like to see your list of duplicates before merging?</p>'; 18606 var ojpop = GLO.Popup.Confirm.open('<div id="pop-confirm-merge-clients">' + htm + '</div>', 'Confirm Merge', fnYes, fnNo); 18607 var jbtns = ojpop.getPopup().find('.pop-buttons').css({ "margin-bottom": "8px" }); 18608 18609 var btnNo = jbtns.find('.btnNo').addClass('btnAdd').removeClass('btnNo').css({ "float": "left", "display": "inline-block", "margin-top": "-6px" }) 18610 var btnYes = jbtns.find('.btnYes').addClass('btnSave').css({ "width": "240px" }); 18611 18612 btnNo.find('>a').css({ "padding": "8px 20px", "font-size": "larger" }).text('Lookup Duplicates'); 18613 btnYes.find(' > a').text('Merge Duplicate Clients'); 18614 18615 if (innerWidth < 600) { 18616 btnNo.css({ "float": "none", "display": "block", "margin-bottom": "24px" }); 18617 btnYes.css({ "float": "none" }); 18618 } else { 18619 jbtns.css({ "width": "600px" }); 18620 } 18621 } else { 18622 _conAHelpClient.processMergeConfirmed(isMerge, isExtreme); 18623 } 18624 } 18625 _conAHelpClient.processMergeConfirmed = function(isMerge, isExtreme) { 18626 if (!_conAdvanced.canSaveChanges()) { _conAdvanced.initReadOnlyCheck(); return; } 18627 18628 var jpopMerge = $('#pop-merge-duplicates').closest('.glopop'); 18629 var url = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedMergeClients?ismerge=' + isMerge + '&isExtreme=' + isExtreme; 18630 18631 GLO.Popup.closeIfExist($('#pop-confirm-merge-clients').closest('.glopop')); 18632 GLO.UI.Form.beginProcessing(jpopMerge.find('#btnProcessMerge')); 18633 18634 _openProcessingMerge(isMerge, isExtreme); 18635 18636 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: {} }) 18637 .success(function(data, textStatus, jqXHR) { 18638 var jd = $(data); 18639 var htm = jd.outerHTML(); 18640 18641 GLO.Popup.closeIfExist($('#pop-processing-merge').closest('.glopop')); 18642 18643 if (UTIL.parseBool(jd.attr('warning_fl'))) { 18644 GLO.UI.Form.resetProcessing(); 18645 var jpopWarn = GLO.Popup.Warning.open(htm, 'Cannot Merge Now').getPopup(); 18646 } else { 18647 GLO.Popup.closeIfExist(jpopMerge); 18648 18649 if (isMerge) { 18650 var h1 = 'Duplicate Clients Merged'; 18651 } else { 18652 var h1 = 'Duplicate Clients Found'; 18653 } 18654 18655 //var htm = '<div><div class="friendly-msg3">' + htm + '</div></div>'; 18656 var jpopResults = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-merge-results'); 18657 GLO.Popup.Custom.singleButton(jpopResults, 'Close'); 18658 } 18659 }) 18660 .error(function(jqXHR, textStatus, errorThrown) { 18661 var htm = '<div><p>Unable to process merge at this time</p><p>Please try again later</p></div>'; 18662 GLO.Popup.Error.open(htm, 'Merge Client List Duplicates'); 18663 GLO.UI.Form.resetProcessing(); 18664 }); 18665 } 18666 function _openProcessingMerge(isMerge, isExtreme) { 18667 if (isMerge) { 18668 var label = 'Merge'; 18669 } else { 18670 var label = 'Duplicate lookup'; 18671 } 18672 18673 var msg1 = label + ' processing, please be patient it typically takes less than 60 seconds to perform, but it might take up to 5 minutes for very large client lists'; 18674 var msg2 = 'Do not attempt another merge or duplicate lookup request until this finishes processing' 18675 18676 var htm = '<div id="pop-processing-merge"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>'; 18677 GLO.Popup.Processing.open(htm, 'Processing ' + label); 18678 } 18679 18680 function _freeTextCount() { 18681 if (GLO.Info.providerPackage == 1) { 18682 return 50; 18683 } else { 18684 return 500; 18685 } 18686 } 18687 18688 _conAHelpClient.openTextReminder2 = function() { 18689 var li1 = '<li><b class="narrow-text">24 hours</b> before appointment</li>'; 18690 var li2 = '<li><b class="narrow-text">2 hours</b> before appointment</li>'; 18691 18692 var msg1 = '<p>Can send clients 2 text reminders for each appointment</p>'; 18693 var msg2 = '<p style="margin-bottom: 0;">
18693A common scenario is to send reminders</p>'; 18694 var ul2 = '<ul>' + li1 + li2 + '</ul>'; 18695 18696 var payAsUse = '<b class="narrow-text">Pay-as-Use</b> plan'; 18697 var aMsgPlan = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=appointment&highlight=advanced-feature-staff-alert-text")\'>Message Plan</a>'; 18698 18699 var msg3 = '<p>The first ' + _freeTextCount() + ' text reminders are free every month</p>'; 18700 var msg4 = '<p>Sign up for a ' + aMsgPlan + ' to send more text messages</p>'; 18701 var msg5 = '<p>With the ' + payAsUse + ' text reminders cost just 1 cent per message</p>'; 18702 18703 var msg6 = '<p style="margin-top: 24px; letter-spacing: 0; font-family: Arial;">The first text reminder and the second text reminder must be sent at least 8 hours apart</p>'; 18704 18705 return _open('Text Reminder #2', '<div id="pop-help-text-reminder2">' + msg1 + msg2 + ul2 + msg3 + msg4 + msg5 + msg6 + '</div>'); 18706 } 18707 18708 _conAHelpClient.openSearchDeletedClient = function() { 18709 var label = '<label for="Deleted_Client_vc">Enter Deleted Client\'s Name, Phone, Email, or Street Address</label>'; 18710 var input = '<input id="Deleted_Client_vc" placeholder="Deleted Client Search"/>'; 18711 18712 var htm = '<div id="pop-search-deleted-clients">' + label + input + '</div>'; 18713 var jpop = GLO.Popup.Custom.openSimple(htm, 'Deleted Client Search'); 18714 GLO.Popup.Custom.singleButton(jpop, 'Close'); 18715 18716 var jclient = jpop.find('#Deleted_Client_vc'); 18717 var urlSearch = GLO.Link.Object.Provider.Ajax + 'ClientSearchDeleted'; 18718 18719 var fnSelect = function(event, ui) { 18720 var htm = '<p>Loading ' + ui.item.label + '...</p>'; 18721 var htmCreate = '<p>' + UTIL.coalesceString(ui.item.client_create_vc, 'Client created') + ' on ' + ui.item.create_dt + '</p>'; 18722 //last_login_dt 18723 18724 if (!UTIL.isEmpty(ui.item.merge_client_id)) { 18725 var mergeUrl = GLO.Link.WebsiteDomain + 'provider/clientProfile?cid=' + ui.item.merge_client_id; 18726 var amerge = 'GLO.Uri.gotoUriWithSpinner(\'' + mergeUrl + '\', this, event, true)'; 18727 htm += '<p>Client merged into <a onclick="' + amerge + '">' + ui.item.merge_client_vc + '</a></p>'; 18728 } 18729 18730 GLO.Popup.Processing.open('<div id="pop-processing-delete-client">' + htmCreate + htm + '</div>', 'Loading Deleted Client Profile'); 18731 18732 setTimeout(function() { 18733 document.location = GLO.Link.WebsiteDomain + 'provider/clientProfile?cid=' + ui.item.id; 18734 }, 7500); 18735 } 18736 18737 UI.initAutoComplete2(jclient, urlSearch, fnSelect, 5); 18738 } 18739 18740 return _conAHelpClient; 18741 })(); 18742 18743 18744 _conAdvancedHelp.Location = (function() { 18745 function _conAHelpLocation() { } 18746 18747 _conAHelpLocation.openProvider = function() { 18748 var h1 = 'Manage Locations'; 18749 var msg1 = '<p>Each business location has its own color so you can easily identify what location you are managing</p>'; 18750 var msg2 = '<p>On a computer, iPad, or tablet change the location you are managing by going to the staff filter (in the upper right corner of the screen)</p>'; 18751 var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-filter-change-location.png" style="max-width: 280px; min-height: 120px; width: 60%;"/> </div>'; 18752 18753 var msg3 = '<p>On your phone open the menu and your current location is listed at the top of the menu; just press the location to change it</p>'; 18754 18755 return _open(h1, '<div>' + msg1 + msg2 + img + msg3 + '</div>'); 18756 } 18757 18758 _conAHelpLocation.openClient = function() { 18759 var h1 = 'Easy Client Management'; 18760 var imgOtherLocation = '<img style="float: none; display: inline-block; margin: 0;" src="' + GLO.Data.cdnDirectory + 'image/icon/location-icon-20wh.png"/>'; 18761 var div1 = '<div style="padding: 6px; padding-left: 24px; background-color: pink;">'; 18762 var msg1 = div1 + 'Client profiles are seamlessly shared accross all your bussiness locations</div>'; 18763 18764 var msg2 = '<p>The client profiles display appointments and product purchases at all locations, visits to other locations are displayed with the other location icon ' + imgOtherLocation + ' and the row has that location\'s background color</p>'; 18765 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-profile-multi-location.png" style="max-width: 600px; min-height: 120px; width: 100%;"/> </div>'; 18766 18767 var msg3 = '<p>
18767When you search for clients, ' + GLO.Info.getScheduleAnyoneHtm() + ' first looks at clients in the location you are currently managing; if it does not find any clients that match your search it will look in your other locations, and the clients from your other locations will have that location\'s background color</p>'; 18768 var img2 = '<div style="display: inline-block;"> <img src="' + GLO.Data.cdnDirectory + 'image/help/link-client-search2.png" style="max-width: 180px; min-height: 80px; width: 100%;"/> </div>'; 18769 var img3 = '<div style="display: inline-block;"> <img src="' + GLO.Data.cdnDirectory + 'image/help/link-client-create-appointment.png" style="max-width: 360px; min-height: 200px; min-width: 240px; width: 60%;"/> </div>'; 18770 18771 var msg4 = '<p>No need to export and import client lists across multiple locations ' + GLO.Info.getScheduleAnyoneHtm() + ' takes care of all of that for you'; 18772 18773 return _open(h1, '<div>' + msg1 + msg2 + img1 + msg3 + img2 + img3 + msg4 + '</div>', true); 18774 } 18775 18776 _conAHelpLocation.openStaff = function() { 18777 var h1 = 'Staff At Multiple Locations'; 18778 var msg1 = '<div style="padding: 6px; padding-left: 24px; background-color: pink;">The same staff member can work at more than one location and see appointments at all locations on one calendar</div>'; 18779 var msg2 = '<p>You regular hours at other location(s) are displayed in that location\'s color</p>'; 18780 var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-calendar-multi-location.png" style="max-width: 600px; min-height: 280px; width: 100%;"/> </div>'; 18781 18782 var aAddStaff = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=location#open=add-staff\', this)">Add Staff From Another Location</a>'; 18783 var aLinkStaff = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=location#open=add-staff\', this)">Link Staff At Another Location</a>'; 18784 var msg3 = '<p>You can ' + aAddStaff + ' and ' + aLinkStaff + '</p>'; 18785 18786 return _open(h1, '<div>' + msg1 + msg2 + img1 + msg3 + '</div>', true); 18787 } 18788 18789 return _conAHelpLocation; 18790 })(); 18791 18792 return _conAdvancedHelp; 18793 })(); 18794 18795 return _conAdvanced; 18796})(); 18797 18798 18799GLO.Provider.Discount = (function() { 18800 function _conManageD() { } 18801 var _isAddOnFee = false, _word = 'Discount', _wordLong = 'Discount'; 18802 18803 _conManageD.init = function(isFee) { 18804 GLO.Info.init(); 18805 18806 if (isFee) { 18807 _word = 'Fee'; 18808 _wordLong = 'Add-On Fee'; 18809 _isAddOnFee = true; 18810 } 18811 18812 var jrpt = $('.report-container'); 18813 var jcontainer = jrpt.find('#DiscountList'); 18814 SA.Upgrade.initReadOnly(_word + 's', jcontainer); 18815 GLO.Report.portalName = _word; 18816 18817 var tagOptionList = $(GLO.ClientProfile.Tag.getTagTypeDropDown()).html(); 18818 $('#discount-rules').find('.tag-list').html(tagOptionList); 18819 18820 GLO.Report.enableFullPageCheck(); 18821 _conManageD.initData(jrpt); 18822 18823 _initShortcut(); 18824 _initUri(jrpt); 18825 18826 GLO.Report.hideEmptyColumn(jrpt, 'discount-column-commission-split'); 18827 GLO.Report.setupFastClick(); 18828 } 18829 18830 function _initUri(jrpt) { 18831 var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase(); 18832 18833 if (!UTIL.isEmpty(open)) { 18834 if (open === 'pay-method' || open === 'paymethod' || open === 'paymentmethod') { 18835 GLO.Provider.Discount.openHelpPayMethod(); 18836 } else if (open === 'clienttag' || open === 'client-tag') { 18837 GLO.Provider.TagManager.openReportHelp(); 18838 } else if (open === 'day-time' || open === 'daytime') { 18839 GLO.Provider.Discount.openHelpDayTime(); 18840 } else if (open === 'client-birthday' || open === 'birthday') { 18841 GLO.Provider.Discount.openHelpBirthday(); 18842 } else if (open === 'loyalty-points' || open === 'points' || open === 'loyalty') { 18843 GLO.Uri.gotoUriWithSpinner('help#tab=pos&id=faq-pos-setup-loyalty'); 18844 } else if (open === 'promo-code' || open === 'promo') { 18845 GLO.Provider.Discount.openPromoHelp(); 18846 } else if (open === 'rule' || open === 'rules' || open === 'more-info') { 18847 GLO.Provider.Discount.openHelpRules();
18848 18849 } else if (open === 'commission-split') { 18850 GLO.Provider.Discount.openCommissionSplit(_isAddOnFee, true); 18851 } else if (open === 'commission-split-custom') { 18852 GLO.Provider.Discount.openCommissionSplit(_isAddOnFee, true); 18853 GLO.Provider.Discount.helpCommissionSplitCustom(); 18854 } else if (open === 'commission-split-by-type') { 18855 GLO.Provider.Discount.helpCommissionSplitByType(); 18856 18857 } else if (open === 'add') { 18858 var ruleType = GLO.Uri.query('ruletype'); 18859 var ruleVal = GLO.Uri.query('ruleval'); 18860 18861 GLO.Provider.Discount.openEdit(null, null, null, ruleType, ruleVal); 18862 } else if (open === 'discount' || open === 'fee') { 18863 var id = GLO.Uri.query('id'); 18864 jrpt.find('#DiscountList').find('tr[provider_discount_id="' + id + '"]').find('td.discount-column-name a').click(); 18865 } 18866 } 18867 } 18868 18869 _conManageD.initData = function(jrpt) { 18870 UI.initTableSorter($('.tablesorter')); 18871 GLO.Report.CellSummary.initReport(jrpt, false, true); 18872 _initTagName(jrpt); 18873 } 18874 18875 function _initTagName(jrpt) { 18876 var jtags = jrpt.find('tbody').find('.rule-tag'); 18877 _initTagNameForTags(jtags) 18878 } 18879 18880 function _initTagNameForTags(jtags) { 18881 for (var i=0; i < jtags.length; i++) { 18882 var jtag = jtags.eq(i); 18883 var tagTypeId = jtag.attr('discount_type_id'); 18884 var tag = GLO.ClientProfile.Tag.getTagType(tagTypeId); 18885 var tagName = UTIL.maxString(tag.name, 24); 18886 jtag.find('b').text(tagName); 18887 } 18888 } 18889 18890 function _initShortcut() { 18891 $(document).keydown(function(event) { 18892 if (event.altKey) { 18893 if (event.which === 82) { //R: refresh report 18894 GLO.Provider.Discount.search(); 18895 } 18896 } 18897 }); 18898 $(window).bind('keypress', function(e) { 18899 if (e.altKey) { 18900 if (e.which === 82) { //R: refresh report 18901 e.preventDefault(); 18902 } 18903 } 18904 }); 18905 } 18906 18907 _conManageD.openEdit = function(thisLink, highlightRuleNumber, isFee, addRuleType, addRuleValue) { 18908 if (SA.Upgrade.initReadOnly(_word + 's')) { return; } 18909 18910 var tr, jPop = $('#manage-discount-popup'); 18911 var ojpop = new GLO.Popup.Custom(jPop, GLO.Provider.Discount.save); 18912 18913 jPop = ojpop.getPopup().addClass('pop-discount-edit'); 18914 jPop.find('a.modalClose').css({ "top": "3px", "right": "3px" }); 18915 jPop.find('h2').css({ "margin": 0 }); 18916 jPop.find('.msg').append('<style> .ui-datepicker { z-index: 9999 !important; } </style>'); 18917 jPop.find("#Start_dt, #End_dt").datepicker({ minDate: 0 }); 18918 18919 UI.timeMask('#Restrict_Start_tm'); 18920 UI.timeMask('#Restrict_End_tm', '11:59 am'); 18921 18922 var jbtns = jPop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "480px" }); 18923 jbtns.find('.btnSave').css({ "margin": "0", "text-align": "center" }); 18924 18925 if (thisLink) { 18926 tr = $(thisLink).closest('tr'); 18927 var isFee = _openEditPopulate(jPop, tr); 18928 _openDiscountStatus(jPop); 18929 } 18930 18931 _openDayTimeRestriction(jPop, tr); 18932 _openHighlightRuleNumber(jPop, highlightRuleNumber); 18933 18934 if (isFee) { 18935 _openEditFee(jPop); 18936 } 18937 18938 if (GLO.Provider.isManagerCheck(_word, jPop, tr)) { 18939 jPop.find('input, select, textarea').change( function() { 18940 $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" }); 18941 }); 18942 } 18943 18944 if (!UTIL.isEmpty(addRuleType)) { 18945 GLO.Provider.Discount.addRule(); 18946 var tr = jPop.find('.discount-rule:last'); 18947 tr.find('.select-discount-type').val(addRuleType).change(); 18948 tr.find('.discount-rule-option select:visible').val(addRuleValue).focus(); 18949 } 18950 18951 ojpop.realign(); 18952 jPop.css({ "top": "32px" }); 18953 $(window).scrollTop(0); 18954 } 18955 function _openEditFee(jpop) { 18956 jpop.find('#manage-discount-popup').addClass('is-fee'); 18957 } 18958 function _openEditPopulate(jPop, tr) { 18959 var pdid = tr.attr('provider_discount_id');
18960 var start = tr.find('.start-date').attr('dt'); 18961 var end = tr.find('.end-date').attr('dt'); 18962 18963 var jamt = tr.find('.discount-column-amount'); 18964 var minPurchase = tr.find('.min-purchase').text().replace('$', ''); 18965 var discountType = tr.attr('discount_type1_cd'), maxAllowed = tr.attr('max_allowed_sr'); 18966 var jname = tr.find('.discount-column-name'); 18967 var split = tr.find('.discount-column-commission-split').attr('commission_split_cd'); 18968 var splitPercent = tr.find('.discount-column-commission-split').attr('commission_split_pct'); 18969 18970 if (maxAllowed > 10) { maxAllowed = 99; } 18971 18972 jPop.find('#Provider_Discount_id').val(pdid); 18973 jPop.find('#Discount_Name_vc').val($.trim(UTIL.coalesce(jname.attr('title'), jname.text()))); 18974 jPop.find('#Max_Allowed_sr').val(maxAllowed); 18975 jPop.find('#Commission_Split_cd').val(split).change(); 18976 jPop.find('#Commission_Split_pct').val(splitPercent); 18977 18978 _openEditPopulatePromo(jPop, tr); 18979 18980 if (UTIL.isDate(start)) { 18981 start = new Date(start).toGloDate(); 18982 jPop.find('#Start_dt').val(start); 18983 } 18984 18985 if (UTIL.isDate(end)) { 18986 end = new Date(end).toGloDate(); 18987 jPop.find('#End_dt').val(end); 18988 } 18989 18990 var dpct = UTIL.coalesceFloat(jamt.attr('discount_pct')), dmn = UTIL.coalesceMoney(jamt.attr('discount_mn')); 18991 18992 if (UTIL.coalesceMoney(dpct, 0) + UTIL.coalesceMoney(dmn, 0) < 0) { 18993 var isFee = true; 18994 18995 if (UTIL.coalesceMoney(dpct) < 0) { dpct = -dpct; } 18996 if (UTIL.coalesceMoney(dmn) < 0) { dmn = -UTIL.coalesceMoney(dmn); } 18997 } else { 18998 var isFee = false; 18999 } 19000 19001 if (dpct > 0) { 19002 jPop.find('#Discount_pct').val(dpct); 19003 } 19004 19005 if (dmn > 0) { 19006 jPop.find('#Discount_mn').val(dmn); 19007 } 19008 19009 if (!UTIL.isEmpty(minPurchase)) { 19010 jPop.find('#require-min-purchase').prop('checked', true); 19011 jPop.find('#Minimum_Purchase_mn').val(minPurchase); 19012 } 19013 19014 if (!UTIL.isEmpty(discountType)) { 19015 _openRuleRow(tr, jPop, 1, true); 19016 _openRuleRow(tr, jPop, 2, true); 19017 _openRuleRow(tr, jPop, 3, true); 19018 } 19019 19020 if (tr.find('.always .check-mark').length === 1 || UTIL.isEmpty(pdid)) { 19021 jPop.find('#Always_fl').prop('checked', true); 19022 } 19023 19024 return isFee; 19025 } 19026 function _openEditPopulatePromo(jPop, tr) { 19027 var tdPromo = tr.find('.discount-column-promo-code'); 19028 var promoCode = $.trim(tr.attr('promo_code_vc')); // $.trim(tdPromo.find('i').text()); 19029 19030 if (!UTIL.isEmpty(promoCode)) { 19031 jPop.find('#Promo_Code_vc').val(promoCode).change(); 19032 jPop.find('#Require_Promo_Code_fl').prop('checked', tdPromo.find('.is-require-promo').length); 19033 jPop.find('#Promo_Message_vc').val(tdPromo.find('.discount-promo-message').text()); 19034 } 19035 } 19036 19037 function _openDiscountStatus(jpop) { 19038 var dt1 = jpop.find('#Start_dt').val(), dt2 = jpop.find('#End_dt').val(); 19039 var msg = null; 19040 19041 if (UTIL.isDate(dt2) && new Date(dt2) < new Date()) { 19042 msg = _word + ' Expired on ' + new Date(dt2).toSADate(true); 19043 } else if (UTIL.isDate(dt1) && new Date(dt1) > new Date()) { 19044 msg = _word + ' Not Active Until ' + new Date(dt1).toSADate(true); 19045 } 19046 19047 if (!UTIL.isEmpty(msg)) { 19048 var htm = '<div id="pop-discount-status">' + msg + '</div>'; 19049 jpop.find('#manage-discount-popup').prepend(htm); 19050 } 19051 } 19052 19053 function _openHighlightRuleNumber(jpop, highlightRuleNumber) { 19054 jpop.find('.discount-rule').eq(highlightRuleNumber-1).find('.discount-rule-option select').focus(); 19055 } 19056 19057 function _openDayTimeRestriction(jpop, tr) { 19058 var jrestrict = jpop.find('#discount-daytime-restriction'); 19059 19060 if (innerWidth < 760) {
19061 var jlabels = jrestrict.find('#discount-restrict-day-row2').find('label'); 19062 19063 for (var i=0; i < jlabels.length; i++) { 19064 jlabels.eq(i).text(jlabels.eq(i).text().substring(0,3)); 19065 } 19066 } 19067 19068 if (tr) { 19069 var tm1 = tr.attr('restrict_start_tm'), tm2 = tr.attr('restrict_end_tm'); 19070 var jcheck = jrestrict.find(':checkbox'); 19071 19072 if (UTIL.isValidTime(tm1)) { jpop.find('#Restrict_Start_tm').val(tm1); } 19073 if (UTIL.isValidTime(tm2)) { jpop.find('#Restrict_End_tm').val(tm2); } 19074 19075 for (var i=0; i < jcheck.length; i++) { 19076 var isChecked = UTIL.parseBool(tr.attr(jcheck.eq(i).attr('id'))); 19077 jcheck.eq(i).prop('checked', isChecked); 19078 } 19079 } 19080 } 19081 19082 function _openRuleRow(tr, jpop, ruleNumber, isLoading) { 19083 var discountType = tr.attr('discount_type' + ruleNumber + '_cd'); 19084 19085 if (UTIL.isNumber(discountType)) { 19086 discountType = parseInt(discountType); 19087 19088 if (discountType > 3) { 19089 var ruleTR = _conManageD.addRule(isLoading); 19090 19091 if (ruleTR) { 19092 var stype = null, ruleDID; 19093 19094 if (discountType === 4 || discountType === 8 || discountType === 9 || discountType === 10) { 19095 stype = 'p'; 19096 ruleDID = ruleTR.find('.product-list'); 19097 } else if (discountType === 5 || discountType === 6 || discountType === 7) { 19098 stype = 's'; 19099 ruleDID = ruleTR.find('.service-list'); 19100 } else if (discountType === 20) { 19101 stype = 't'; 19102 ruleDID = ruleTR.find('.tag-list'); 19103 } else if (discountType === 30) { 19104 stype = 'r'; 19105 jpop.find('#discount-daytime-restriction').removeClass('hide'); 19106 } else if (discountType === 50) { 19107 stype = 'l'; 19108 ruleDID = ruleTR.find('.discount-loyalty-points').removeClass('hide'); 19109 } else if (discountType === 60) { 19110 stype = '$'; 19111 ruleDID = _getPayMethodDD(ruleTR).removeClass('hide').find('.payment-method'); 19112 } else if (discountType === 70) { 19113 stype = 'b'; 19114 ruleDID = ruleTR.find('.birthday-list-container').removeClass('hide').find('.birthday-list'); 19115 } else if (discountType === 80) { 19116 stype = 'm'; 19117 ruleDID = ruleTR.find('.membership-list-container').removeClass('hide').find('.membership-list'); 19118 } 19119 19120 if (stype !== null) { 19121 ruleTR.find('.select-discount-type').val(stype).change(); 19122 19123 var discountId = tr.attr('discount_type' + ruleNumber + '_id'); 19124 19125 if (!UTIL.isEmpty(discountId)) { 19126 var did = null; 19127 19128 if (discountType === 6 || discountType === 8 || discountType === 20 || discountType === 40 || discountType === 50 || discountType === 60) { 19129 did = discountId; 19130 } else if (discountType === 7) { 19131 did = 'sg' + discountId; 19132 } else if (discountType === 9) { 19133 did = 'pl' + discountId; 19134 } else if (discountType === 10) { 19135 did = 'v' + discountId; 19136 } else if (discountType === 70) { 19137 did = discountId; 19138 } else if (discountType === 80) { 19139 did = discountId; 19140 } 19141 19142 if (did !== null) { 19143 ruleDID.val(did); 19144 } 19145 } 19146 } 19147 } 19148 } 19149 } 19150 } 19151 19152 _conManageD.changeCommissionSplit = function() { 19153 var jpop = $('#manage-discount-popup'); 19154 var split = jpop.find('#Commission_Split_cd').val(); 19155 19156 if (split == 4) { 19157 jpop.addClass('is-custom-split'); 19158 } else { 19159 jpop.removeClass('is-custom-split'); 19160 } 19161 } 19162 19163 _conManageD.removeRule = function(thisIcon) { 19164 var tr = $(thisIcon).closest('tr'); 19165 19166 if ( $('#discount-rules').find('tr.discount-rule:visible').length === 1 ) { 19167 tr.addClass('hide'); 19168 } else { 19169 tr.remove(); 19170 } 19171 19172 _hideDayTimeRestriction(); 19173 } 19174 19175 _conManageD.addRule = function(isLoading) { 19176 var jpop = $('#manage-discount-popup').closest('.glopop').css({ "height": "" }); 19177 var jtbl = jpop.find('#discount-rules table'); 19178 var newTR, trs = jtbl.find('tr.discount-rule'); 19179 19180 if (trs.length === 1 && trs.eq(0).hasClass('hide')) { 19181 jtbl.find('#discount-always-apply').removeClass('hide'); 19182 trs.removeClass('hide'); 19183 19184 if (!isLoading) { 19185 trs.find('.select-discount-type').focus(); 19186 } 19187 19188 newTR = trs; 19189 } else if (!isLoading && trs.length === 3) { 19190 new GLO.Popup.Warning(SA.Resource.ThreeRuleLimitWarning); 19191 return; 19192 } else { 19193 newTR = trs.eq(0).clone(); 19194 newTR.find('select').val('').change(); 19195 19196 trs.eq(trs.length - 1).after(newTR); 19197 19198 if (!isLoading) { 19199 jtbl.find('.select-discount-type:last').focus(); 19200 } 19201 } 19202 19203 return newTR; 19204 } 19205 _conManageD.displayMaxAllowed = function() { 19206 var isDisplay = false, isProduct = false, isService = false; 19207 var jpop = $('#manage-discount-popup'); 19208 var dmn = UTIL.coalesceMoney(jpop.find('#Discount_mn').val()); 19209 var jselect = jpop.find('select.select-discount-type'); 19210 19211 for (var i=0; i < jselect.length; i++) { 19212 var rule = jselect.eq(i).val(); 19213 19214 if (rule == 'p' || rule == 's') { // && dmn > 0 // && rule > 3 && rule < 11 19215 isDisplay = true; 19216 19217 if (rule == 'p') { 19218 isProduct = true; 19219 } else if (rule == 's') { 19220 isService = true 19221 } 19222 } 19223 } 19224 19225 isDisplay = true; 19226 19227 if (isDisplay) { 19228 var jdd = jpop.find('#max-allowed-container').removeClass('hide').find('#Max_Allowed_sr'); 19229 19230 if (isProduct && isService) { 19231 jdd.addClass('has-product-and-service-option').find('option[value="99"]').text('per service / product'); 19232 } else if (isProduct) { 19233 jdd.removeClass('has-product-and-service-option').find('option[value="99"]').text('per product'); 19234 } else if (isService) { 19235 jdd.removeClass('has-product-and-service-option').find('option[value="99"]').text('per service'); 19236 } else { 19237 jdd.addClass('has-product-and-service-option').find('option[value="99"]').text('per service / product'); 19238 } 19239 } else { 19240 jpop.find('#max-allowed-container').addClass('hide'); 19241 } 19242 } 19243 _conManageD.selectRuleType = function(thisDD) { 19244 var jdd = $(thisDD), jPop = $('#manage-discount-popup'), newDD = null; 19245 var tr = jdd.closest('tr'); 19246 19247 _hideDayTimeRestriction(); 19248 tr.find('.product-list, .service-list, .tag-list-container, .discount-loyalty-points, .payment-method-container, .birthday-list-container, .membership-list-container').addClass('hide'); 19249 19250 if (jdd.val() === 'p') { 19251 newDD = tr.find('.product-list').removeClass('hide'); 19252 } else if (jdd.val() === 's') { 19253 newDD = tr.find('.service-list').removeClass('hide'); 19254 } else if (jdd.val() === 't') { 19255 var jtaglist = tr.find('.tag-list-container').removeClass('hide').find('.tag-list'); 19256 19257 if (jtaglist.find('option').length > 0) { 19258 newDD = jtaglist.removeClass('hide'); 19259 } else { 19260 var aClientTag = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Setup <i>Client Tags</i></a>'; 19261 var htm = '<b id="goto-client-tag-manager" class="tag-list"><span>No client tags found</span> ' + aClientTag + '</b>'; 19262 newDD = jtaglist.replaceWith(htm); 19263 } 19264 } else if (jdd.val() === 'r') {
19265 jPop.find('#discount-daytime-restriction').removeClass('hide').find('#Restrict_Start_tm').focus(); 19266 } else if (jdd.val() === 'l') { 19267 tr.find('.discount-loyalty-points').removeClass('hide').focus(); 19268 } else if (jdd.val() === '$') { 19269 var jpm = _getPayMethodDD(tr); 19270 19271 jpm.removeClass('hide').find('.payment-method').focus(); 19272 } else if (jdd.val() === 'b') { 19273 tr.find('.birthday-list-container').removeClass('hide').find('.birthday-list').focus(); 19274 } else if (jdd.val() === 'm') { 19275 newDD = tr.find('.membership-list-container').removeClass('hide').find('.membership-list'); 19276 } 19277 19278 if (newDD !== null && !GLO.Info.isIPad) { newDD.focus(); } 19279 _conManageD.displayMaxAllowed(); 19280 } 19281 function _getPayMethodDD(tr) { 19282 var jpm = tr.find('.payment-method-container'); 19283 19284 if (jpm.length === 0) { 19285 var htmPayMeth = UserPortal.Price.getPricePopHtm().find('#appt-price-payment-table .Payment_Method_cd').html(); 19286 var dd = '<select class="payment-method" style="max-width: 210px; padding-right: 0;">' + htmPayMeth + '</select>'; 19287 var helpIcon = '<b class="question-icon" onclick="GLO.Provider.Discount.openHelpPayMethod(this)" style="margin-left: 4px;">?</b>'; 19288 19289 tr.find('.discount-rule-option').append('<span class="payment-method-container">' + dd + helpIcon + '</span>'); 19290 jpm = tr.find('.payment-method-container'); 19291 jpm.find('.payment-method option:first').text('(any payment)'); 19292 } 19293 19294 return jpm; 19295 } 19296 function _hideDayTimeRestriction() { 19297 var jpop = $('#manage-discount-popup').closest('.glopop'); 19298 19299 if (jpop.find('#discount-rules').find('.select-discount-type:visible option:selected[value="r"]').length === 0) { 19300 jpop.find('#discount-daytime-restriction').addClass('hide'); 19301 } 19302 } 19303 19304 _conManageD.remove = function(thisTD) { 19305 if (!GLO.Provider.isManagerCheck(_word)) { return; } 19306 19307 var tr = $(thisTD).closest('tr'); 19308 var discount = tr.find('.discount-column-name span').text(); 19309 19310 GLO.Popup.Confirm(SA.Resource.RemoveConfirmQuestion + ' ' + discount + '?', function() { GLO.Provider.Discount.removeConfirmed(tr); }); 19311 } 19312 19313 _conManageD.removeConfirmed = function(tr) { 19314 if (!GLO.Provider.isManagerCheck(_word)) { return; } 19315 19316 var url = GLO.Link.Page.Provider.Home + 'manage/RemoveDiscount'; 19317 var pdId = tr.attr('provider_discount_id'); 19318 19319 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_discount_id": pdId } }) 19320 .success(function(data, textStatus, jqXHR) { 19321 var tbl = $('#DiscountList tbody'); 19322 tbl.find('tr[provider_discount_id="' + pdId + '"]').remove(); 19323 }) 19324 .error(function(jqXHR, textStatus, errorThrown) { 19325 new GLO.Popup.Error('Unable to remove this ' + _word + ' at this time. Please try again later.'); 19326 }); 19327 } 19328 19329 function _populateDiscountTypes(jpop, jsonDiscount) { 19330 var rules = jpop.find('tr.discount-rule:visible'); 19331 var always = jpop.find('#Always_fl:visible'); 19332 19333 if (rules.length > 0) { 19334 var jdd, jopt, optVal, cdColumnName, idColumnName, discountType; 19335 19336 if (always.prop('checked')) { jsonDiscount.always_fl = "1" } 19337 19338 for (var i=0; i < rules.length; i++) { 19339 discountType = null; 19340 jdd = rules.eq(i).find('.product-list:visible'); 19341 19342 cdColumnName = "discount_type" + (i + 1) + "_cd"; 19343 idColumnName = "discount_type" + (i + 1) + "_id"; 19344 19345 if (jdd.length === 1) { 19346 jopt = jdd.find('option:selected'); 19347 optVal = jopt.attr('value'); 19348 19349 if (UTIL.isEmpty(optVal)) { 19350 jsonDiscount[cdColumnName] = 4; 19351 } else { 19352 if (jopt.hasClass('v-option')) { 19353 jsonDiscount[cdColumnName] = 10; 19354 jsonDiscount[idColumnName] = optVal.replace('v', ''); 19355 } else if (jopt.hasClass('pl-option')) { 19356 jsonDiscount[cdColumnName] = 9; 19357 jsonDiscount[idColumnName] = optVal.replace('pl', ''); 19358 } else { 19359 jsonDiscount[cdColumnName] = 8; 19360 jsonDiscount[idColumnName] = optVal; 19361 } 19362 } 19363 } else { 19364 jdd = rules.eq(i).find('.service-list:visible'); 19365 19366 if (jdd.length === 1) { 19367 jopt = jdd.find('option:selected'); 19368 optVal = jopt.attr('value'); 19369 19370 if (UTIL.isEmpty(optVal)) { 19371 jsonDiscount[cdColumnName] = 5; 19372 } else { 19373 if (jopt.hasClass('sg-option')) { 19374 jsonDiscount[cdColumnName] = 7; 19375 jsonDiscount[idColumnName] = optVal.replace('sg', ''); 19376 } else { 19377 jsonDiscount[cdColumnName] = 6; 19378 jsonDiscount[idColumnName] = optVal; 19379 } 19380 } 19381 } else { 19382 var dtid = rules.eq(i).find('.select-discount-type').val(); 19383 var tagId = rules.eq(i).find('.tag-list:visible').val(); 19384 19385 if (dtid == 't' && !UTIL.isEmpty(tagId)) { 19386 jsonDiscount[cdColumnName] = 20; 19387 jsonDiscount[idColumnName] = tagId; 19388 } else if (dtid === 'r') { 19389 if (_populateRestrictDayTime(jpop, jsonDiscount)) { 19390 jsonDiscount[cdColumnName] = 30; 19391 //jsonDiscount[idColumnName] = 1; 19392 } 19393 } else if (dtid === 'l') { 19394 jsonDiscount[cdColumnName] = 50; 19395 jsonDiscount[idColumnName] = jsonDiscount.loyalty_points_nr = rules.eq(i).find('.discount-loyalty-points').val(); 19396 } else if (dtid === '$') { 19397 jsonDiscount[cdColumnName] = 60; 19398 jsonDiscount[idColumnName] = rules.eq(i).find('.payment-method').val(); 19399 } else if (dtid === 'b') { 19400 jsonDiscount[cdColumnName] = 70; 19401 jsonDiscount[idColumnName] = rules.eq(i).find('.birthday-list:visible').val(); 19402 } else if (dtid === 'm') { 19403 jsonDiscount[cdColumnName] = 80; 19404 jsonDiscount[idColumnName] = rules.eq(i).find('.membership-list').val(); 19405 } 19406 } 19407 } 19408 } 19409 } 19410 } 19411 19412 function _populateRestrictDayTime(jpop, jsonDiscount) { 19413 var hasValid = false, hasDay = false;
19414 var jrestrict = jpop.find('#discount-daytime-restriction'); 19415 var tm1 = jpop.find('#Restrict_Start_tm').val(), tm2 = jpop.find('#Restrict_End_tm').val(); 19416 var jcheck = jrestrict.find(':checkbox:checked'); 19417 19418 if (UTIL.isValidTime(tm1)) { jsonDiscount.restrict_start_tm = tm1; hasValid = true; } 19419 if (UTIL.isValidTime(tm2)) { jsonDiscount.restrict_end_tm = tm2; hasValid = true; } 19420 19421 for (var i=0; i < jcheck.length; i++) { 19422 hasValid = true; 19423 hasDay = true; 19424 jsonDiscount[jcheck.eq(i).attr('id')] = 1; 19425 } 19426 19427 if (hasValid && !hasDay) { //= check all days (if time is set, but no day) 19428 jsonDiscount.Restrict_Sun_fl = jsonDiscount.Restrict_Mon_fl = jsonDiscount.Restrict_Tue_fl = jsonDiscount.Restrict_Wed_fl = 1; 19429 jsonDiscount.Restrict_Thu_fl = jsonDiscount.Restrict_Fri_fl = jsonDiscount.Restrict_Sat_fl = 1; 19430 } 19431 19432 return hasValid; 19433 } 19434 19435 function _validPromo(jpop, jsonDiscount, promo) { 19436 if (!UTIL.isEmpty(promo)) { 19437 var firstOccurrance = UTIL.indexOfNonAlphaNumeric(promo); 19438 19439 if (firstOccurrance >= 0) { 19440 var badLetter = promo.substring(firstOccurrance, firstOccurrance + 1); 19441 var htm = '<div>Promo code can only be letters and numbers</div> <div>The character <b style="font-size: 150%;">' + badLetter + '</b> is not allowed</div>'; 19442 GLO.Popup.Warning.open('<div class="friendly-msg2">' + htm + '</div>', 'Invalid Promo Code'); 19443 return false; 19444 } 19445 19446 jsonDiscount.promo_code_vc = promo; 19447 jsonDiscount.require_promo_code_fl = jpop.find('#Require_Promo_Code_fl').prop('checked'); 19448 jsonDiscount.promo_message_vc = UTIL.htmlEncode(jpop.find('#Promo_Message_vc').val()); 19449 } 19450 19451 return true; 19452 } 19453 19454 _conManageD.save = function() { 19455 if (!GLO.Provider.isManagerCheck(_word)) { return; } 19456 if (!GLO.Info.isRequireGold()) { return false; } 19457 19458 var jpop = $('#manage-discount-popup'); 19459 var discount = jpop.find('#Discount_Name_vc').val(); 19460 var maxAllowed = UTIL.coalesceInt(jpop.find('#Max_Allowed_sr:visible').val(), 0); 19461 var alwaysApply = jpop.find('#Always_fl').prop('checked'); 19462 var split = jpop.find('#Commission_Split_cd').val(); 19463 var isFee = jpop.hasClass('is-fee'); 19464 var promo = $.trim(jpop.find('#Promo_Code_vc').val()); 19465 19466 if (UTIL.isEmpty(discount)) { 19467 var fnFocus = function() { $('#manage-discount-edit').find('#Discount_Name_vc').focus(); }; 19468 19469 if (isFee) { 19470 var msg = 'Please Enter Fee Name', word = 'Fee'; 19471 } else { 19472 var msg = SA.Resource.PleaseEnterDiscountName, word = 'Discount'; 19473 } 19474 19475 GLO.Popup.Warning.open(msg, 'Missing ' + word + ' Name', fnFocus); 19476 return; 19477 } 19478 19479 var discountNm = jpop.find('#Discount_Name_vc').val(); 19480 var pdId = jpop.find('#Provider_Discount_id').val(); 19481 19482 var start = jpop.find('#Start_dt').val(); 19483 var end = jpop.find('#End_dt').val(); 19484 19485 var pctDiscount = jpop.find('#Discount_pct').val(); 19486 var mnDiscount = jpop.find('#Discount_mn').val(); 19487 19488 if (isFee) { 19489 if (UTIL.coalesceInt(pctDiscount) > 0) { 19490 if (pctDiscount.indexOf('.') !== -1) { 19491 pctDiscount = -UTIL.coalesceFloat(pctDiscount); 19492 } else { 19493 pctDiscount = -UTIL.coalesceInt(pctDiscount); 19494 } 19495 } 19496 19497 if (UTIL.coalesceMoney(mnDiscount) > 0) { 19498 mnDiscount = -UTIL.coalesceMoney(mnDiscount); 19499 } 19500 } 19501 19502 if (_isEmptyAmount(pctDiscount, mnDiscount, isFee)) { 19503 return; 19504 } 19505 19506 var jsonDiscount = { "discount_name_vc": discountNm, "provider_discount_id": pdId, "start_dt": start, "end_dt": end, "discount_pct": pctDiscount, "discount_mn": mnDiscount 19507 , "always_fl": alwaysApply, "fee_fl": isFee }; 19508 19509 if (maxAllowed > 0) { jsonDiscount.max_allowed_sr = maxAllowed; } 19510 19511 if (!UTIL.isEmpty(split)) { 19512 jsonDiscount.commission_split_cd = split; 19513 19514 if (split == 4) { 19515 jsonDiscount.commission_split_pct = jpop.find('#Commission_Split_pct').val(); 19516 } 19517 } 19518 19519 if (!_validPromo(jpop, jsonDiscount, promo)) { return; } 19520
19521 if (jpop.find('#require-min-purchase').prop('checked')) { 19522 jsonDiscount.minimum_purchase_mn = jpop.find('#Minimum_Purchase_mn').val(); 19523 } 19524 19525 _populateDiscountTypes(jpop, jsonDiscount); 19526 19527 if (!_displayInfoAndVerify(jsonDiscount)) { 19528 return; 19529 } 19530 19531 var url = GLO.Link.Page.Provider.Home + 'manage/discountSave'; 19532 GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btnSave') ); 19533 19534 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jsonDiscount }) 19535 .success(function(data, textStatus, jqXHR) { 19536 GLO.UI.Form.resetProcessing(); 19537 GLO.Popup.close( $('#manage-discount-popup').closest('.pop-custom') ); 19538 19539 var tr = $(data); 19540 var tbl = $('#DiscountList tbody'); 19541 var jtags = tr.find('.rule-tag'); 19542 _initTagNameForTags(jtags) 19543 19544 tbl.find('tr[provider_discount_id="' + tr.attr('provider_discount_id') + '"]').remove(); 19545 tbl.prepend(tr); 19546 tbl.find('#no-discount-row').remove(); 19547 19548 GLO.Provider.Discount.refresh(); 19549 }) 19550 .error(function(jqXHR, textStatus, errorThrown) { 19551 GLO.UI.Form.resetProcessing(); 19552 new GLO.Popup.Error('Unable to edit this ' + _word + ' at this time. Please try again later.'); 19553 }); 19554 } 19555 19556 function _displayInfoAndVerify(jsonDiscount) { 19557 if (jsonDiscount.fee_fl && jsonDiscount.discount_type1_cd == 60 && jsonDiscount.discount_type1_id == 10) { 19558 _conManageD.displayConvenienceFeeOverview(); 19559 19560 if (Math.abs(jsonDiscount.discount_pct) > 3) { 19561 var jpop = $('#pop-discount-row-amount').closest('.glopop'); 19562 jpop.find('#Discount_pct').val(3); 19563 jpop.find('#Discount_mn').val(''); 19564 19565 var msg = '<p>The government restricts credit card fees to a maximum of 3%</p>'; 19566 GLO.Popup.Warning.open(msg, 'Maximum Credit Card Fee Warning'); 19567 return false; 19568 } 19569 } 19570 19571 return true; 19572 } 19573 _conManageD.displayConvenienceFeeOverview = function() { 19574 var uriPayOnline = 'provider/manage/ClientPayOnline'; 19575 var btnIfEnabled = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriPayOnline + '\', this, event, true)">Setup Payments When Clients Book Online</a></span>'; 19576 19577 var htm = '<p>If full payment required when booking online then this fee will be charged when client books online</p>'; 19578 //htm += '<div style="text-align: center;"><small>(bonus for pre-paying online)</small></div>'; 19579 htm += '<div style="margin-top: 8px; margin-bottom: 32px; text-align: center;">' + btnIfEnabled + '</div>'; 19580 19581 var urlMoreInfo = 'https://merchants.fiserv.com/content/dam/firstdata/us/en/documents/pdf/Understanding_Surcharging_Convenience_Service_Fees.pdf'; 19582 var aMoreInfo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlMoreInfo + '\', this, event, true, \'ccfeeinfo\')">Understanding Card Fees</a>'; 19583 var css = 'margin-top: 8px; line-height: 1.4; text-align: left; font-size: 14px;'; 19584 19585 htm += '<div style="' + css + '">The credit card convenience fee must be clearly displayed at the point of sale</div>'; 19586 htm += '<div style="' + css + '">As of March 2023, credit card surchage fees are not allowed in: Connecticut, Massachusetts, and Puerto Rico</div>'; 19587 htm += '<div style="' + css + ' margin-bottom: 36px;">To verify you are following all state and federal laws as well as best practices visit ' + aMoreInfo + '</div>'; 19588 19589 return GLO.Popup.Info.open(htm, 'Credit Card Add-On Fee'); 19590 } 19591 19592 function _isEmptyAmount(pctDiscount, mnDiscount, isFee) { 19593 if (UTIL.coalesceMoney(pctDiscount, 0) === 0 && UTIL.coalesceMoney(mnDiscount, 0) === 0) { 19594 var fnFocus = function() { $('#manage-discount-popup').find('#Discount_pct').focus(); }; 19595 19596 if (isFee) { 19597 var msg = 'Please Enter Fee Amount <small style="white-space: nowrap;">(percent or dollar amount)</small>', word = SA.Resource.Fee; 19598 } else { 19599 var msg = SA.Resource.DiscountHelp, word = SA.Resource.Discount; 19600 } 19601 19602 GLO.Popup.Warning.open(msg, 'Missing ' + word + ' Amount', fnFocus); 19603 return true; 19604 } 19605 } 19606
19607 _conManageD.openDateFilter = function(start, end) { 19608 var htmStart = '<input type="text" id="Start_d" name="Start_d" class="filter-date" pattern="[0-9]*" placeholder="Start" onclick="GLO.UI.displayDatePicker(this)"/>'; 19609 var htmEnd = '<input type="text" id="End_d" name="End_d" class="filter-date" pattern="[0-9]*" placeholder="End" onclick="GLO.UI.displayDatePicker(this)"/>'; 19610 19611 var css = '<style> #ui-datepicker-div { z-index: 6000 !important; } </style>'; 19612 var msg = '<p style="padding: 0 8px; text-align: center;">Filter by date the ' + _wordLong + ' was added to the ticket</p>'; 19613 var htm = '<div id="pop-report-filter-date-range">' + css + msg + '<div id="pop-report-filter-date-range-input">' + htmStart + htmEnd + '</div>'; 19614 19615 var jpop = GLO.Popup.Custom.openSimple(htm, _wordLong + ' Report', GLO.Provider.Discount.filterByDate); 19616 jpop.find('.btnSave').addClass('btnAdd').removeClass('btnSave').css({ "position": "absolute", "right": "8px" }).find('>a').text('Search'); 19617 19618 //jWaitEdit.find("#Wait_Request_d").datepicker({ showWeek: true, beforeShowDay: UserPortal.setDatePickerDays, calculateWeek: UTIL.datePickerCalculateWeek }); 19619 var jstart = jpop.find('#Start_d').datepicker({ showButtonPanel: true, maxDate: 0, changeYear: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(1480) }); 19620 var jend = jpop.find('#End_d').datepicker({ showButtonPanel: true, maxDate: 0, changeYear: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(1080) }); 19621 19622 if (UTIL.isDate(start)) { 19623 jstart.val(start); 19624 } 19625 19626 if (UTIL.isDate(end)) { 19627 jend.val(end); 19628 } 19629 } 19630 _conManageD.filterByDate = function() { 19631 var jpop = $('#pop-report-filter-date-range').closest('.glopop'); 19632 var start = jpop.find('#Start_d').val(); 19633 var end = jpop.find('#End_d').val(); 19634 19635 _conManageD.search(start, end); 19636 19637 var word = 'Discount'; 19638 19639 if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) { 19640 word = 'Add-On Fee'; 19641 } 19642 19643 var htm = '<span>Displaying ' + word + ' used</span>'; 19644 var dayStart = new Date(start).toGloDate(); 19645 var dayEnd = new Date(end).toGloDate(); 19646 19647 if (UTIL.isDate(start) && UTIL.isDate(end)) { 19648 document.title = word + ' Report ' + dayStart + ' - ' + dayEnd; 19649 var fn = 'GLO.Provider.Discount.openDateFilter(\'' + dayStart + '\', \'' + dayEnd + '\')'; 19650 19651 htm += '<span>between</span>' 19652 + '<a class="filter-start-date" onclick="' + fn + '">' + dayStart + '</a>' 19653 + '<i> - </i>' 19654 + '<a class="filter-end-date" onclick="' + fn + '">' + dayEnd + '</a>'; 19655 } else if (UTIL.isDate(start)) { 19656 document.title = word + ' Report After' + dayStart 19657 var fn = 'GLO.Provider.Discount.openDateFilter(\'' + dayStart + '\')'; 19658 htm += '<span>after</span>' + '<a class="filter-start-date" onclick="' + fn + '">' + dayStart + '</a>'; 19659 } else if (UTIL.isDate(end)) { 19660 document.title = word + ' Report Before' + dayEnd; 19661 var fn = 'GLO.Provider.Discount.openDateFilter(null, \'' + dayEnd + '\')'; 19662 htm += '<span>before</span>' + '<a class="filter-end-date" onclick="' + fn + '">' + dayEnd + '</a>'; 19663 } else { 19664 document.title = word + ' Report'; 19665 htm = '<div><span class="btnAdd"><a onclick="GLO.Provider.Discount.openDateFilter()">Filter ' + word + ' used by date</a></span></div>'; 19666 } 19667 19668 $('#manage-discount-container-top-filter, #manage-discount-container-top-help').replaceWith('<div id="manage-discount-container-top-filter">' + htm + '</div>'); 19669 } 19670 _conManageD.refresh = function() { 19671 /* 19672 var j = $('#manage-discount-container-top-filter'); 19673 var start = j.find('.filter-start-date').text(); 19674 var end = j.find('.filter-end-date').text(); 19675 19676 _conManageD.search(start, end); 19677 */ 19678 19679 var word = 'Discount'; 19680 19681 if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) { 19682 word = 'Add-On Fee'; 19683 } 19684 19685 var htm = '<div><span class="btnAdd">
19685<a onclick="GLO.Provider.Discount.openDateFilter()">Filter ' + word + ' used by date</a></span></div>'; 19686 $('#manage-discount-container-top-filter, #manage-discount-container-top-help').replaceWith('<div id="manage-discount-container-top-filter">' + htm + '</div>'); 19687 _conManageD.search(); 19688 } 19689 19690 _conManageD.search = function(start, end) { 19691 var jbutton = $('#manage-discount-header .fa-refresh'); 19692 var jd = {}; 19693 19694 if (jbutton.hasClass('fa-spin')) { 19695 return; 19696 } else if (!GLO.Report.hasReportPassword(jd)) { 19697 return; 19698 } 19699 19700 jbutton.addClass('fa-spin'); //GLO.UI.Form.beginProcessing(jbutton); 19701 19702 var jrpt = $('.report-container'); 19703 var isExpired = $('#manage-discount-container #Include_Inactive_fl').prop('checked'); 19704 var page = 'discount', word = 'Discount', hasDateRange = false; 19705 19706 if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) { 19707 page = 'addon'; 19708 word = 'Add-On Fee'; 19709 } 19710 19711 var uri = GLO.Link.WebsiteDomain + 'provider/manage/' + page + '?display-expired=' + isExpired; 19712 19713 if (UTIL.isDate(start)) { 19714 uri += '&start=' + new Date(start).toGloDate(); 19715 hasDateRange = true; 19716 } 19717 if (UTIL.isDate(end)) { 19718 uri += '&end=' + new Date(end).toGloDate(); 19719 hasDateRange = true; 19720 } 19721 19722 if (hasDateRange) { 19723 GLO.Popup.closeIfExist($('#pop-report-filter-date-range').closest('.glopop')); 19724 } 19725 19726 var jqxhr = $.ajax({ "type": "POST", "url": (uri + '&ispartial=1'), "cache": false, "data": jd }) 19727 .success(function(data, textStatus, jqXHR) { 19728 jbutton.removeClass('fa-spin'); //GLO.UI.Form.resetProcessing(); 19729 19730 jrpt.html($(data).html()); 19731 _conManageD.initData(jrpt); 19732 19733 if (!hasDateRange) { 19734 document.title = word + ' Report'; 19735 } 19736 19737 window.history.pushState('', '', uri); 19738 }) 19739 .error(function(jqXHR, textStatus, errorThrown) { 19740 jbutton.removeClass('fa-spin'); 19741 //jrpt.html('<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>'); 19742 }); 19743 } 19744 19745 _conManageD.changePromoCode = function() { 19746 var jpop = $('#manage-discount-popup').closest('.glopop').css({ "height": "" }); 19747 var promo = jpop.find('#Promo_Code_vc').val(); 19748 19749 if (!UTIL.isEmpty(promo)) { 19750 var promoUrl = GLO.Data.provider.websiteuri + 'client#promo=' + promo; 19751 var promoLink = '<a href="' + promoUrl.replace('http://', '').replace('https://', '') + '">' + promoUrl + '</a>'; 19752 19753 //jpop.find('#Require_Promo_Code_fl').prop('checked', true); 19754 //jpop.find('#Always_fl').prop('checked', true); 19755 19756 jpop.find('#pop-discount-promo-message').removeClass('hide'); 19757 jpop.find('#pop-discount-promo-link').removeClass('hide').find('a').replaceWith(promoLink); 19758 } else { 19759 jpop.find('#pop-discount-promo-message').addClass('hide'); 19760 jpop.find('#pop-discount-promo-link').addClass('hide').find('a').replaceWith('<a/>'); 19761 } 19762 } 19763 19764 _conManageD.openCommissionSplitHelp = function() { 19765 var jpop = $('#manage-discount-popup'); 19766 var isFee = jpop.hasClass('is-fee'); 19767 19768 _conManageD.openCommissionSplit(isFee, false); 19769 } 19770 _conManageD.openCommissionSplit = function(isFee, isAllowEdit) { 19771 GLO.Popup.closeIfExist($('#pop-provider-commission-split').closest('.glopop')); 19772 19773 var split = $('#btnCommissionSplit').attr('commission_split_cd'); 19774 var msg = 'How Service Commission is affected by ' 19775 var btnLabel = 'Save'; 19776 var word = 'Discount', btnOther = null; 19777 19778 if (isFee) { 19779 msg += 'Fees'; 19780 word = 'Add-On Fee'; 19781 var pct = GLO.Data.provider.commission_split_fee_pct; 19782 19783 var text1 = 'staff gets 100% of fee'; 19784 var text2 = 'default; fee added to price, <small>
19784then commission calculated normally</small>'; 19785 var text3 = 'entire fee goes to business\'s profit <small>(staff does not get fee)</small>'; 19786 var text4 = 'percent of fee added to staff\'s commission'; 19787 } else { 19788 msg += 'Discounts'; 19789 var pct = GLO.Data.provider.commission_split_discount_pct; 19790 19791 var text1 = 'discount subtracted from staff\'s commission <small>(entire discount taken out of staff commision)</small>'; 19792 var text2 = 'default; price discounted, <small>then commission calculated normally</small>'; 19793 var text3 = 'discount subtracted from business\'s profit <small>(staff commission same as if there was no discount)</small>'; 19794 var text4 = 'percent of discount added to staff\'s commission'; 19795 } 19796 19797 var rdo1 = '<input type="radio" name="Commission_Split_cd" id="Split_Staff_cd" value="1"/>'; 19798 var label1 = '<label for="Split_Staff_cd"><b>Staff</b></label>'; 19799 19800 var rdo2 = '<input type="radio" name="Commission_Split_cd" id="Split_Proportional_cd" value="0"/>'; 19801 var label2 = '<label for="Split_Proportional_cd"><b>Split</b></label>'; 19802 19803 var rdo3 = '<input type="radio" name="Commission_Split_cd" id="Split_Business_cd" value="2"/>'; 19804 var label3 = '<label for="Split_Business_cd"><b>Business</b></label>'; 19805 19806 if (isAllowEdit) { 19807 var rdo0 = ''; 19808 } else { 19809 var htmArrow = ' <b style="display: inline-block; padding-left: 6px; padding-right: 6px;">➜</b> '; 19810 var btnSeeDefault = '<span class="btnAdd btnAction2"><a onclick="GLO.Provider.Discount.helpCommissionSplitSeeDefault(' + isFee + ')">See Default</a></span>'; 19811 var text0 = 'default commission split set on <b>' + word + ' Report</b> ' + htmArrow + btnSeeDefault; 19812 var label0 = '<label for="Use_Default_cd"><b>Use Default</b></label>'; 19813 var rdo0 = '<li> <span class="commission-split-type">' + label0 + '</span> <span class="commission-split-text">' + text0 + '</span> </li>'; 19814 19815 rdo1 = ''; rdo2 = ''; rdo3 = ''; 19816 btnLabel = 'Close'; 19817 var btnPage = GLO.Report.portalName.toLowerCase(); 19818 19819 if (btnPage != 'discount' && btnPage != 'fee') { 19820 if (isFee) { 19821 btnOther = '<span id="btnViewSplitOther" class="btnAdd" onclick="GLO.Provider.Discount.openCommissionSplit(0, false)"><a>How Works for Discounts</a></span>'; 19822 } else { 19823 btnOther = '<span id="btnViewSplitOther" class="btnAdd" onclick="GLO.Provider.Discount.openCommissionSplit(1, false)"><a>How Works for Add-On Fees</a></span>'; 19824 } 19825 } 19826 } 19827 19828 if (GLO.Info.isGold()) { 19829 var helpIcon = '<b class="question-icon" onclick="GLO.Provider.Discount.helpCommissionSplitCustom()" style="margin: 0 8px; border-width: 2px;">?</b>'; 19830 19831 if (pct == 0) { 19832 pct = ''; 19833 } 19834 19835 if (isAllowEdit) { 19836 var rdo4 = '<input type="radio" name="Commission_Split_cd" id="Split_Custom_cd" value="4" onclick="UI.changeFocus(this, \'Commission_Split_pct\')" style="margin: 0 4px;"/>'; 19837 var htmPercent = '<input id="Commission_Split_pct" type="number" value="' + pct + '" min="5" max="95" onchange="UI.markCheckbox(this, \'Split_Custom_cd\')"/>'; 19838 } else { 19839 var rdo4 = '', htmPercent = ''; 19840 } 19841 19842 var percentSign = '<b class="percent-sign">%</b>'; 19843 var label4 = '<label for="Split_Custom_cd"><b>Custom</b>' + htmPercent + percentSign + helpIcon + '</label>'; 19844 rdo4 = '<li> <span class="commission-split-type">' + rdo4 + label4 + '</span> <span class="commission-split-text">' + text4 + '</span> </li>'; 19845 } else { 19846 var rdo4 = ''; 19847 } 19848 19849 rdo1 = '<li> <span class="commission-split-type">' + rdo1 + label1 + '</span> <span class="commission-split-text">' + text1 + '</li>'; 19850 rdo2 = '<li> <span class="commission-split-type">' + rdo2 + label2 + '</span> <span class="commission-split-text">' + text2 + '</li>'; 19851 rdo3 = '<li> <span class="commission-split-type">' + rdo3 + label3 + '</span> <span class="commission-split-text">' + text3 + '</li>'; 19852 19853 var htm = '<div id="pop-provider-commission-split"> <p>' + msg + '</p><ul>' + rdo0 + rdo1 + rdo2 + rdo3 + rdo4 + '</ul></div>'; 19854 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Service Discount Commission', null, null, true); 19855 var jpop = ojpop.getPopup().addClass('no-persist').addClass('pop-commission-split').attr('is_fee_fl', isFee); 19856 19857 GLO.Popup.Custom.singleButtonNew(jpop, btnLabel).find('> a').css({ "background-color": "rgb(0, 240, 0)", "color": "blue" }); 19858 19859 if (btnOther) { 19860 jpop.append(btnOther); 19861 } 19862 19863 ojpop.realign(); 19864 19865 if (isAllowEdit) { 19866 if (split == 1) { 19867 jpop.find('#Split_Staff_cd').prop('checked', true); 19868 } else if (split == 2) { 19869 jpop.find('#Split_Business_cd').prop('checked', true); 19870 } else if (split == 4) { 19871 jpop.find('#Split_Custom_cd').prop('checked', true); 19872 } else { 19873 jpop.find('#Split_Proportional_cd').prop('checked', true); 19874 } 19875 } 19876 19877 if (isAllowEdit && GLO.Provider.isManagerCheck('Commission Split')) { 19878 //jpop.find('input[type="radio"]').change(GLO.Provider.Discount.saveCommissionSplit); 19879 jpop.find('.btn').click(GLO.Provider.Discount.saveCommissionSplit); 19880 } else { 19881 jpop.find('input[type="radio"]').prop('disabled', true); 19882 } 19883 } 19884 19885 _conManageD.helpCommissionSplitSeeDefault = function(isFee) { 19886 GLO.Popup.closeIfExist( $('#pop-provider-commission-split').closest('.glopop') ); 19887 GLO.Popup.closeIfExist( $('#manage-discount-popup').closest('.glopop') ); 19888 19889 var jbtn = $('#btnCommissionSplit'); 19890 19891 if (jbtn.length) { 19892 UI.highlight(jbtn, null, null, true); 19893 19894 setTimeout(function() { 19895 $('#btnCommissionSplit > a').click(); 19896 }, 2500); 19897 19898 return; 19899 } else if (isFee) { 19900 var label = 'Add-On Fee'; 19901 var url = GLO.Link.WebsiteDomain + 'provider/manage/addon?open=commission-split'; 19902 } else { 19903 var label = 'Discount'; 19904 var url = GLO.Link.WebsiteDomain + 'provider/manage/discount?open=commission-split'; 19905 } 19906 19907 GLO.Popup.Processing.open('Loading ' + label + ' Report so you can set the default commission split for ' + label + '...', 'Loading ' + label + ' Report'); 19908 19909 setTimeout(function() { 19910 document.location = url; 19911 }, 200); 19912 } 19913 19914 _conManageD.helpCommissionSplitByType = function() { 19915 _conManageD.helpCommissionSplitCustom(true); 19916 }
19917 _conManageD.helpCommissionSplitCustom = function(isViewOnly) { 19918 var htm = _helpCommissionSplitCustomHtm(isViewOnly); 19919 19920 var h1b = '<b style="display: block; padding: 4px;">'; 19921 var h1 = h1b + 'Custom Commission Example</b>' + h1b + 'Service ' + _word + '</b>'; 19922 var ojpop = GLO.Popup.Info.openSimple(htm, h1, null, true); 19923 19924 ojpop.getPopup().css({ "max-width": "900px" }); 19925 ojpop.realign(); 19926 } 19927 function _helpCommissionSplitCustomHtm() { 19928 if (_isAddOnFee) { 19929 var action = 'increased by an add-on fee'; 19930 var verb = 'added to'; 19931 } else { 19932 var action = 'discounted'; 19933 var verb = 'taken from'; 19934 } 19935 19936 var htmArrow = ' ➜ '; 19937 /* 19938 var bstart = '<b style="letter-spacing: 0;">'; 19939 var bsplit = bstart + 'Commission Split = "Split"</b>'; 19940 var pSplit = '<p style="margin-bottom: 48px;">By default, when a service price is ' + action + ' the price after ' + _word + ' will receive the staff\'s normal commission percent, this is ' + bsplit + '</p>'; 19941 19942 var pPay = '<p>You can also pay a custom commission on the actual ' + _wordLong + ' amount</p>'; 19943 var pCustom = '<p>To pay a different commission on the action ' + _wordLong + ' amount, select ' + bstart + 'Commission Split = "Custom"</b></p>'; 19944 */ 19945 19946 if (_isAddOnFee) { 19947 var htmExample = _helpCommissionSplitCustomFeeHtm(htmArrow); 19948 } else { 19949 var htmExample = _helpCommissionSplitCustomDiscountHtm(htmArrow); 19950 } 19951 19952 //return '<div id="pop-help-custom-discount-split">' + pSplit + pPay + pCustom + htmExample + '</div>'; 19953 return '<div id="pop-help-custom-discount-split">' + htmExample + '</div>'; 19954 } 19955 function _helpCommissionSplitCustomDiscountHtm(htmArrow) { 19956 var h5 = '<h5 style="margin: 2px;">Example Scenario</h5>'; 19957 19958 var ex1 = '<li>Staff Commission = <b>60%</b></li>'; 19959 var ex2 = '<li>Service Price = <b>$110</b></li>'; 19960 var ex3 = '<li>Service Discount = <b>$10</b></li>'; 19961 var ex4 = '<li>Service Discount Commission = <b>Custom 40%</b></li>'; 19962 19963 var svcPrice = '<i style="letter-spacing: 0;">So the service price for the client is <b>$100</b></i>'; 19964 var htmFinalPrice = '<p style="margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid black; color: black;">' + htmArrow + svcPrice + '</p>'; 19965 var htmExample = h5 + '<ul style="margin-bottom: 0;">' + ex1 + ex2 + ex3 + ex4 + '</ul>' + htmFinalPrice; 19966 19967 var smallCustom = '<small style="padding-left: 6px; letter-spacing: 0;">($10 * 40%)</small>'; 19968 var btotal = '<b style="display: inline-block; padding: 4px 8px; line-height: 1; font-size: larger; border-radius: 8px; background-color: rgb(0,240,0);">$64</b>'; 19969 19970 var li1 = '<li><b>Service Commission = $60</b> <small style="padding-left: 6px; letter-spacing: 0;">($100 * 60%)</small></li>'; 19971 var li2 = '<li><b>Discount Commission = $4</b> ' + smallCustom + '</li>'; 19972 var li3 = '<li>So total commission on the service ' + htmArrow + btotal + '</li>'; 19973 19974 return htmExample + '<ol>' + li1 + li2 + li3 + '</ol>'; 19975 } 19976 function _helpCommissionSplitCustomFeeHtm(htmArrow) { 19977 var h5 = '<h5 style="margin: 2px;">Example Scenario</h5>'; 19978 19979 var ex1 = '<li>Staff Commission = <b>60%</b></li>'; 19980 var ex2 = '<li>Service price = <b>$100</b></li>'; 19981 var ex3 = '<li>Service Add-On Fee = <b>$10</b></li>'; 19982 var ex4 = '<li>Service Discount Commission = <b>Custom 40%</b></li>'; 19983 19984 var svcPrice = '<i style="letter-spacing: 0;">So the service price for the client is <b>$110</b></i>'; 19985 var htmFinalPrice = '<p style="margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid black; color: black;">' + htmArrow + svcPrice + '</p>'; 19986 var htmExample = h5 + '<ul style="margin-bottom: 0;">' + ex1 + ex2 + ex3 + ex4 + '</ul>' + htmFinalPrice; 19987 19988 var smallCustom = '<small style="padding-left: 6px; letter-spacing: 0;">($10 * 40%)</small>'; 19989 var btotal = '<b style="display: inline-block; padding: 4px 8px; line-height: 1; font-size: larger; border-radius: 8px; background-color: rgb(0,240,0);">$64</b>'; 19990 19991 var li1 = '<li><b>Service Commission = $60</b> <small style="padding-left: 6px; letter-spacing: 0;">($100 * 60%)</small></li>'; 19992 var li2 = '<li><b>Add-On Fee Commission = $4</b> ' + smallCustom + '</li>'; 19993 var li3 = '<li>So total commission on the service is ' + btotal + '</li>'; 19994 19995 return htmExample + '<ol>' + li1 + li2 + li3 + '</ol>'; 19996 } 19997 19998 function _isAllowSaveSplit() { 19999 var jpop = $('.pop-commission-split').closest('.glopop'); 20000 var split = jpop.find('input[name="Commission_Split_cd"]:checked').val(); 20001 var pct = UTIL.coalesceInt(jpop.find('#Commission_Split_pct').val(), 0); 20002 20003 if (split == 4 && (pct < 5 || pct > 95)) { 20004 var msg = '<p>Custom Split percent must be between 5% - 95%</p>'; 20005 var isFee = UTIL.parseBool($('.pop-commission-split').attr('is_fee_fl')); 20006 var htmArrow = '<b class="arrow-right">➜</b>'; 20007 20008 if (pct < 5) { 20009 if (isFee) { 20010 msg += '<p>To have all the add-on fee go to the staff ' + htmArrow + ' select <b>Staff</b> as the <i>Service Discount Commission</i></p>'; 20011 } else { 20012 msg += '<p>To have all the discount taken out of the staff commission ' + htmArrow + ' select <b>Staff</b> as the <i>Service Discount Commission</i></p>'; 20013 } 20014 } else if (pct > 95) { 20015 if (isFee) { 20016 msg += '<p>To have all the add-on fee go to the business ' + htmArrow + ' select <b>Business</b> as the <i>Service Discount Commission</i></p>'; 20017 } else { 20018 msg += '<p>To have all the discount taken out of the business ' + htmArrow + ' select <b>Business</b> as the <i>Service Discount Commission</i></p>'; 20019 } 20020 } 20021 20022 GLO.Popup.Warning.open(msg, 'Invalid Custom Split %'); 20023 return false; 20024 } 20025 20026 return true; 20027 } 20028 20029 _conManageD.saveCommissionSplit = function() { 20030 if (!_isAllowSaveSplit()) { 20031 return; 20032 } 20033 20034 var msg = '<p>Would you like to back date this change and re-calculate commissions?</p>'; 20035 var htm = $('<div id="pop-commission-split-start"> <h1 class="friendly-msg4">Commission Split Effective Date</h1>' 20036 + '<div class="friendly-msg4" style="padding: 20px;">' 20037 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 20038 + msg
20039 + '<label for="Commission_Start_dt">Start Date</label>' 20040 + '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>' 20041 + '</div> </div>'); 20042 20043 var fnSave = function () { 20044 var dt = $('#pop-commission-split-start #Commission_Start_dt').val() 20045 GLO.Provider.Discount.saveCommissionSplitConfirmed(dt); 20046 } 20047 20048 var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist'); 20049 20050 var dtToday = new Date().toGloDate(); 20051 jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-1M", maxDate: 0 }); 20052 jpop.find('#Commission_Start_dt').val(dtToday); 20053 20054 jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" }); 20055 jpop.find('#Commission_Start_dt').blur(); 20056 } 20057 _conManageD.saveCommissionSplitConfirmed = function(startDate) { 20058 if (!GLO.Provider.isManagerCheck('Commission Split')) { 20059 return; 20060 } 20061 20062 var jpop = $('.pop-commission-split'); 20063 var isFee = jpop.attr('is_fee_fl'); 20064 var split = jpop.find('input[name="Commission_Split_cd"]:checked').val(); 20065 var pct = jpop.find('#Commission_Split_pct').val(); 20066 20067 var jpopConfirm = $('#pop-commission-split-start').closest('.glopop'); 20068 var url = GLO.Link.Page.Provider.Home + 'manage/CommissionSplit'; 20069 20070 GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btn') ); 20071 GLO.UI.Form.beginProcessing(jpopConfirm.find('.btnSave')); 20072 20073 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "startDate": startDate, "split": split, "percent": pct, "isfee": isFee } }) 20074 .success(function(data, textStatus, jqXHR) { 20075 //GLO.UI.Form.resetProcessing(); 20076 GLO.Popup.closeIfExist(jpop); 20077 GLO.Popup.closeIfExist(jpopConfirm); 20078 20079 var btn = $('#btnCommissionSplit'); 20080 btn.attr('commission_split_cd', split); 20081 20082 if (split == 1) { 20083 label = 'Staff'; 20084 } else if (split == 2) { 20085 label = 'Business'; 20086 } else if (split == 4) { 20087 label = 'Custom'; 20088 } else { 20089 label = 'Split'; 20090 } 20091 20092 btn.find('b').text(label); 20093 20094 if (UTIL.parseBool(isFee)) { 20095 GLO.Data.provider.commission_split_fee_cd = split; 20096 GLO.Data.provider.commission_split_fee_pct = pct; 20097 } else { 20098 GLO.Data.provider.commission_split_discount_cd = split; 20099 GLO.Data.provider.commission_split_discount_pct = pct; 20100 } 20101 }) 20102 .error(function(jqXHR, textStatus, errorThrown) { 20103 GLO.UI.Form.resetProcessing(); 20104 GLO.Popup.Error.open('<p>Unable to change commission split at this time</p><p>Please try again later</p>', 'Update Commission Split'); 20105 }); 20106 } 20107 20108 _conManageD.openHelpRules = function() { 20109 var p1 = '<p>You can apply a ' + _word + ' to only tickets that have a specific combination of products and/or services by adding rules</p>'; 20110 var p2 = '<p>You can also require the ticket to match other rules like time of day, day of the week, payment method used, client tag, etc...</p>'; 20111 var p3 = '<p>For the ' + _word + ' to apply <b>all rules must match the ticket</b> <small style="letter-spacing: 0;">(for example, if a ' + _word + ' has 2 rules and only 1 rule matches a ticket then the ' + _word + ' cannot be used)</small></p>'; 20112 20113 var p4 = '<p>If any ' + _word + ' matches a ticket <i style="letter-spacing: 0;">(and the ' + _word + ' does not automatically apply)</i> then the ticket will include the option <b>(select discount or fee)</b></p>'; 20114 var img1 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-select-discount.png" style="max-width: 640px;"/>'; 20115 var p5 = '<p>When a ' + _word + ' is selected it will be displayed on the ticket</p>'; 20116 20117 if (_isAddOnFee) { 20118 var img2 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-fee-selected.png" style="max-width: 640px;"/>'; 20119 } else { 20120 var img2 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-discount-selected.png" style="max-width: 640px;"/>'; 20121 } 20122 20123 var small6 = '<small style="letter-spacing: 0;">(and do not <b>Require</b> a promo code and leave the <b>Require Minimum Purchase</b> empty)</small>'; 20124 var p6 = '<p style="margin-bottom: 16px;">If you want to be able to apply a ' + _word + ' to any ticket, when creating the ' + _word + ' ➜ leave the rule section empty ' + small6 + '</p>'; 20125 //var p7 = '<p></p>'; 20126 20127 if (_isAddOnFee) { 20128 var img3 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/edit-discount-type.png" style="max-width: 640px;"/>'; 20129 } else { 20130 var img3 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/edit-add-on-fee-type.png" style="max-width: 640px;"/>'; 20131 } 20132 20133 var htm = '<div id="pop-help-discount-rules">' + p1 + p2 + p3 + p4 + img1 + p5 + img2 + p6 + img3 + '</div>'; 20134 var ojpop = GLO.Popup.Info.openSimple(htm, _wordLong + ' Rules', null, true); 20135 GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false); 20136 } 20137 20138 _conManageD.openPromoHelp = function() { 20139 var imgOnlineBookingPromo = GLO.Data.cdnDirectory + 'image/faq/appointment/create/online-booking-create-appointment-with-note.png'; //image/faq/website/online-booking-create-appointment.png 20140 var imgOnlineBooking = '<div style="text-align: center;"><img src="' + imgOnlineBookingPromo + '" style="max-width: 480px;"/></div>'; 20141 var imgApptNotePopup = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit/appointment-notes-popup.png" style="max-width: 420px;"/></div>'; 20142 20143 var chkRequired = '<input type="checkbox" id="example-require-promo" checked="checked" readonly="readonly" style="height: 18px; width: 18px; margin-top: -3px; margin-right: 2px; margin-left: 8px;">'; 20144 var lblRequired = '<b style="margin-right: 6px; font-size: 16px; color: #4F81BD;">Require</b></span>'; 20145 var htmRequired = 'if you check ' + chkRequired + lblRequired + ' <i style="letter-spacing: 0;">(next to the promo code field)</i>'; 20146 20147 var smallRequired = '<small style="display: block; margin-left: 24px; letter-spacing: 0;">(even staff must enter promo code to use discount on client ticket)</small>'; 20148 var htmArrow = '<b class="arrow-right">➜</b>'; 20149 20150 var p1 = '<p>You can create a discount with a promo code for coupons and other specials</p>'; 20151 var p2 = '<p style="margin-top: 0;">Clients can enter the promo code in the special requests note field when they book online</p>'; 20152 var p3 = '<p style="margin-top: 32px;">Staff can also enter the promo code in the special requests note field or in the <b style="color: #4F81BD;">Appointment Notes</b> popup</p>'; 20153 var p4 = ''; // '<p style="margin-top: 32px;">When creating a discount, ' + htmRequired + ' then ' + htmArrow + ' promo code is <b>Required</b> to use the discount' + smallRequired + '</p>'; 20154 20155 var htm = '<div id="pop-help-discount-promo-code">' + p1 + p2 + imgOnlineBooking + p3 + imgApptNotePopup + p4 + '</div>'; 20156 var ojpop = GLO.Popup.Info.openSimple(htm, 'Discount Promo Code', null, true); 20157 20158 GLO.Popup.Custom.singleButton(ojpop, 'Close'); 20159 GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false); //ojpop.getPopup().css({ "max-width": "900px" }); 20160 } 20161 20162 _conManageD.openHelpDayTime = function() { 20163 var p1 = '<p>Can setup the ' + _wordLong + ' to only occur on specific day(s) of the week and/or time of day <i class="narrow-text">(based on the appointment start time)</i></p>'; 20164 20165 if (_isAddOnFee) { 20166 var p2 = '<p>For example, if you want to charge more on the weekends</p>'; 20167 var p3 = '<p>You could also stay open an hour later - then just charge an extra fee for those late appointments</p>'; 20168 } else { 20169 var p2 = '<p>For example, you could setup a <b>Happy Hour</b> where appointments are cheaper during slower times of the day</p>'; 20170 var p3 = '<p></p>'; 20171 } 20172 20173 var htm = '<div id="pop-help-discount-daytime">' + p1 + p2 + p3 + '</div>'; 20174 var ojpop = GLO.Popup.Info.openSimple(htm, _word + ' by Day / Time', null, true); 20175 GLO.Popup.Custom.singleButton(ojpop, 'Close'); 20176 //GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false); 20177 } 20178 20179 _conManageD.openHelpPayMethod = function(element) { 20180 var p1 = '<p>Setup a ' + _wordLong + ' when a client pays with a specific payment method</p>'; 20181 20182 if (_isAddOnFee) { 20183 var aMoreInfo = ' <b>➜</b> <a onclick="GLO.Provider.Discount.displayConvenienceFeeOverview()">More Information</a>'; 20184 var p2 = '<p>For example, you can charge a <i>Convenience Fee</i> <small>(to re-imburse your credit card merchant fees)</small> when a client pays with a credit card' + aMoreInfo + '</p>'; 20185 } else { 20186 var p2 = '<p>For example, you can offer a ' + _wordLong + ' when a client pays with cash</p>'; 20187 } 20188 20189 var htm = '<div id="pop-help-discount-paymethod">' + p1 + p2 + '</div>'; 20190 var ojpop = GLO.Popup.Info.openSimple(htm, 'Payment Method ' + _word, null, true); 20191 GLO.Popup.Custom.singleButton(ojpop, 'Close'); 20192 } 20193 20194 _conManageD.openHelpBirthday = function() { 20195 var imgBdayHelloBar = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/hello-bar/hello-bar-birthday2.png" style="max-width: 480px;"/></div>'; 20196 var htmArrow = ' <b>➜</b> '; 20197 var aBdayEmail = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'message/Birthday?helloback=discount\'' + ', this, event, true)">Birthday Email Setup</a>'; 20198 20199 var p1 = '<p>When a client has a birthday <i>within a month of the current day</i>, then a bar is displayed at the top of the <b>Create Appointment</b> and <b>Edit Appointment</b>
20199 popup indicating that the client just recently had a birthday or has an upcoming birthday</p>'; 20200 var p2 = '<p>You can have a birthday discount automatically be given to a client on their birthday, within days of their birthday, or within weeks of their birthday</p>'; 20201 var p3 = '<p>You can also have <b>Happy Birhday Emails</b> automatically be sent to clients' + htmArrow + aBdayEmail + '</p>'; 20202 //var p4 = '<p></p>'; 20203 20204 var htm = '<div id="pop-help-discount-birthday">' + p1 + imgBdayHelloBar + p2 + p3 + '</div>'; 20205 var ojpop = GLO.Popup.Info.openSimple(htm, 'Birthday ' + _word, null, true); 20206 GLO.Popup.Custom.singleButton(ojpop, 'Close'); 20207 //GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, true); //ojpop.getPopup().css({ "max-width": "900px" }); 20208 } 20209 20210 return _conManageD; 20211})(); 20212 20213 20214GLO.Provider.Commission = (function() { 20215 function _conCommission() { } 20216 var _serviceCommissionTypeTimeout = null, _dtCommissionStart = null; 20217 var _minCommissionPopupHtm = null; 20218 20219 _conCommission.initStaffService = function(minCommissionStart, maxCommissionStart) { 20220 var jtbl = $('#commission-by-staff-service').find('.tablesorter'); 20221 UI.initTableSorter(jtbl); 20222 20223 GLO.Staff.Filter.isReportFilterEasyQuery = true; 20224 20225 jStaffFilter = $('#staff-filter'); 20226 jStaffFilter.find('#staff-filter-custom-group #staff-filter-custom').remove(); 20227 jStaffFilter.find('#staff-filter-sg').remove(); 20228 20229 var sfilter = GLO.Uri.query('sfilter'); 20230 20231 if (!UTIL.isEmpty(sfilter)) { 20232 jStaffFilter.val(sfilter); 20233 } 20234 20235 jtbl.find('input').on('keyup', GLO.Provider.Commission.onChangeCommission); 20236 WIZ.page = 5; 20237 GLO.Info.helloBarCheck(); 20238 20239 if (UTIL.isDate(minCommissionStart) && UTIL.isDate(maxCommissionStart)) { 20240 if (new Date(minCommissionStart).toGloDate() == new Date(maxCommissionStart).toGloDate()) { 20241 _dtCommissionStart = new Date(maxCommissionStart).toGloDate(); 20242 } 20243 } 20244 } 20245 20246 _conCommission.initStaffServiceReport = function() { 20247 GLO.Info.init(); 20248 _conCommission.initStaffService(); 20249 GLO.Report.enableFullPageCheck(); 20250 GLO.Report.initReportPassword(); 20251 20252 $('#commission-by-staff-service-more').find('#Overtime_Type_cd').change(); 20253 $('#commission-by-staff-service-more').find('.btnSave').addClass('hide'); 20254 20255 _conCommission.initPayrollSchedule(); 20256 _initEarly(); 20257 _initUrlActions(); 20258 } 20259 function _initEarly() { 20260 var jCommissionType = $('#service-commission-type-setup'); 20261 var earlyPercent = UTIL.coalesceMoney(jCommissionType.find('#Service_Commission_Type1_pct').val()); 20262 var hasStaffEarly = false; 20263 var tdEarly = $('#report-commission-staff-list').find('tbody td.commission-column-staff-early-percent'); 20264 20265 for (var i=0; i < tdEarly.length; i++) { 20266 var pct = UTIL.coalesceMoney(tdEarly.eq(i).text().replace('%', '')); 20267 20268 if (pct > 0) { 20269 hasStaffEarly = true; 20270 } 20271 } 20272 20273 if (hasStaffEarly || earlyPercent > 0) { 20274 jCommissionType.find('#early-commission-container2').removeClass('hide'); 20275 } 20276 } 20277 _conCommission.initPayrollSchedule = function() { 20278 var jrange = $('#report-payroll-date-range'); 20279 var dateRange = UTIL.coalesceInt(jrange.attr('value')); 20280 20281 if (dateRange > 0) { 20282 if (dateRange == 10) { 20283 var label = 'Twice Monthly'; 20284 } else if (dateRange == 20) { 20285 var label = 'Monthly'; 20286 } else if (dateRange >= 30 && dateRange <= 39) { 20287 var label = 'Every 2 weeks'; 20288 20289 if (dateRange > 30) { 20290 var day = dateRange % 10; 20291 label += ' <span class="narrow-text">(starts ' + GLO.Provider.Advanced.Help.Calendar.getStartDayOfWeek(day, true) + ')</span>'; 20292 } 20293 } else if (dateRange >= 40 && dateRange <= 49) { 20294 var label = 'Every week'; 20295 20296 if (dateRange > 40) { 20297 var day = dateRange % 10; 20298 label += ' <span class="narrow-text">(starts ' + GLO.Provider.Advanced.Help.Calendar.getStartDayOfWeek(day, true) + ')</span>'; 20299 } 20300 } 20301 20302 jrange.find('label').html(label); 20303 } 20304 } 20305 _conCommission.loadCommissionReport = function() { 20306 var frm = $('#commission-report-password').attr('action', window.location.href).attr('method', 'post'); 20307 var pass = frm.find('#Report_Password_vc').val(); 20308 20309 if (UTIL.isEmpty(pass)) { 20310 var fnFocus = function() { frm.find('#Report_Password_vc').focus(); } 20311 GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus); 20312 return false; 20313 } 20314 20315 GLO.Popup.Processing.open('Looking up password...', 'Processing...'); 20316 20317 setTimeout(function() {
20318 frm.submit(); 20319 }, 100); 20320 } 20321 20322 function _initUrlActions() { 20323 var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase(); 20324 var highlight = UTIL.cleanString(GLO.Uri.query('highlight')); 20325 20326 if (open === 'help') { 20327 var page = UTIL.coalesceInt(GLO.Uri.hash('page'), 0); 20328 GLO.Provider.Commission.openReportHelp(page); 20329 } else if (open === 'wage') { 20330 var sid = UTIL.cleanString(GLO.Uri.hash('staff')).toLowerCase(); 20331 20332 if (sid > 1) { 20333 $('#report-commission-staff-list').find('tr[staff_id=' + sid + ']').find('.commission-column-hourly-wage a').click(); 20334 } else { 20335 $('#report-commission-staff-list').find('tbody tr:first').find('.commission-column-hourly-wage a').click(); 20336 } 20337 } else if (open === 'range' || open === 'date-range' || open === 'schedule') { 20338 $('#report-payroll-date-range #btnPayrollDateRange > a').click(); 20339 } 20340 20341 if (highlight.toLowerCase() === 'early') { 20342 var jelement = $('#service-commission-type-setup #Service_Commission_Type1_pct'); 20343 UI.highlight(jelement, null, null, true); 20344 jelement.focus(); 20345 } else if (highlight.toLowerCase() === 'normal') { 20346 var jelement = $('#service-commission-type-setup #Service_Commission_Type2_pct'); 20347 UI.highlight(jelement, null, null, true); 20348 jelement.focus(); 20349 } else if (!UTIL.isEmpty(highlight)) { 20350 var jhigh = $('#commission-by-staff-service .' + highlight); 20351 20352 if (jhigh.length && !jhigh.is(':visible') && !$('body').hasClass('report-full-page')) { 20353 GLO.Report.enableFullPage(true); 20354 } else if (jhigh.length === 0) { 20355 jhigh = $('#' + highlight); 20356 } 20357 20358 UI.highlight(jhigh, null, null, true); 20359 } 20360 20361 GLO.Info.displayHelloBarBackToAdvanced(); 20362 } 20363 20364 _conCommission.changeOvertimeType = function(element) { 20365 if (!GLO.Report.allowReportChange()) { return false; } 20366 20367 var overtimeType = element.value; 20368 var jcontainer = $(element).closest('fieldset, div'); 20369 20370 $('#commission-setup-container-max-hr-per-week-label1').removeClass('hide'); 20371 20372 if (overtimeType == 10) { 20373 jcontainer.find('#commission-setup-container-max-hr-per-day').removeClass('hide'); 20374 jcontainer.find('#commission-setup-container-max-hr-per-week').addClass('hide'); 20375 } else if (overtimeType == 20) { 20376 jcontainer.find('#commission-setup-container-max-hr-per-day').addClass('hide'); 20377 jcontainer.find('#commission-setup-container-max-hr-per-week').removeClass('hide'); 20378 } else if (overtimeType == 30) { 20379 jcontainer.find('#commission-setup-container-max-hr-per-day').removeClass('hide'); 20380 jcontainer.find('#commission-setup-container-max-hr-per-week').removeClass('hide').find('#commission-setup-container-max-hr-per-week-label1').addClass('hide'); 20381 } else { 20382 jcontainer.find('#commission-setup-container-max-hr-per-day').addClass('hide'); 20383 jcontainer.find('#commission-setup-container-max-hr-per-week').addClass('hide'); 20384 } 20385 20386 jcontainer.find('.btnSave').removeClass('hide'); 20387 } 20388 _conCommission.changeCommissionSetup = function(element) { 20389 if (!GLO.Report.allowReportChange()) { return false; } 20390 20391 var jcontainer = $(element).closest('fieldset, div'); 20392 20393 if (jcontainer.hasClass('sub-container')) { 20394 jcontainer = jcontainer.closest('fieldset, div'); 20395 } 20396 20397 jcontainer.find('.btnSave').removeClass('hide'); 20398 return true; 20399 } 20400 _conCommission.changeServiceCommissionType = function(element, event) { 20401 UI.verifyNumberInput(element); 20402 clearTimeout(_serviceCommissionTypeTimeout); 20403 20404 _serviceCommissionTypeTimeout = setTimeout(function() { 20405 GLO.Provider.Commission.changeServiceCommissionType2(element); 20406 }, 100); 20407 } 20408 _conCommission.changeMinHourly = function() { 20409 if (!GLO.Report.allowReportChange()) { return; } 20410 20411 var j = $('#min-hourly-rate'); 20412 j.find('.btnSave').removeClass('hide'); 20413 } 20414 _conCommission.changeServiceCommissionType2 = function(element) { 20415 var j = $('#service-commission-type-setup'); 20416 var jt1 = j.find('#Service_Commission_Type1_pct'); 20417 var jt2 = j.find('#Service_Commission_Type2_pct'); 20418 20419 j.find('.btnSave').removeClass('hide'); 20420 20421 if ($(element).attr('id') === 'Service_Commission_Type1_pct') { 20422 var amt = 100 - UTIL.coalesceInt(jt1.val(), 0); 20423 jt2.val(amt); 20424 } else { 20425 var amt = 100 - UTIL.coalesceInt(jt2.val(), 0); 20426 jt1.val(amt); 20427 } 20428 } 20429 _conCommission.onChangeCommission = function() { 20430 $('.ss-commission-buttons .btnSave > a').addClass('unsaved'); 20431 } 20432 _conCommission.saveServiceCommissionType = function() { 20433 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveCommissionType'; 20434 var j = $('#service-commission-type-setup'); 20435 var btnSave = j.find('.btnSave'); 20436 20437 var t1 = j.find('#Service_Commission_Type1_pct').val(); 20438 var t2 = j.find('#Service_Commission_Type2_pct').val(); 20439 var up = j.find('#Early_Commission_Roundup_fl').prop('checked'); 20440 20441 GLO.UI.Form.beginProcessing(btnSave); 20442
20443 $.ajax({ type: "POST", url: uri, "cache": false, data: { "type1": t1, "type2": t2, "up": up } }) 20444 .success(function(data, textStatus, jqXHR) { 20445 var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Service Commission Type Changed!</div></div>'; 20446 new GLO.Popup.Success(htm); 20447 20448 GLO.UI.Form.resetProcessing(); 20449 btnSave.addClass('hide'); 20450 20451 if (t2 != 100) { 20452 $('#service-commission-type-setup #early-commission-container2').removeClass('hide'); 20453 } 20454 }) 20455 .error(function(jqXHR, textStatus, errorThrown) { 20456 GLO.Popup.Error('Unable to save. Please try again'); 20457 GLO.UI.Form.resetProcessing(); 20458 }); 20459 } 20460 _conCommission.saveMinHourly = function() { 20461 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveMinHourly'; 20462 var j = $('#min-hourly-rate'); 20463 var m1 = j.find('#Min_Hourly_Wage_mn').val(); 20464 var m2 = j.find('#Min_Hourly_Overtime_mn').val(); 20465 var btnSave = j.find('.btnSave'); 20466 20467 GLO.UI.Form.beginProcessing(btnSave); 20468 20469 $.ajax({ type: "POST", url: uri, "cache": false, data: { "minHourly": m1, "minOvertime": m2 } }) 20470 .success(function(data, textStatus, jqXHR) { 20471 var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Minimum Hourly Rates Changed!</div></div>'; 20472 new GLO.Popup.Success(htm); 20473 20474 GLO.UI.Form.resetProcessing(); 20475 btnSave.addClass('hide'); 20476 }) 20477 .error(function(jqXHR, textStatus, errorThrown) { 20478 GLO.Popup.Error('Unable to save. Please try again'); 20479 GLO.UI.Form.resetProcessing(); 20480 }); 20481 } 20482 _conCommission.saveOvertimeDefault = function() { 20483 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveOvertimeDefault'; 20484 var j = $('#commission-overtime-default'); 20485 var btnSave = j.find('.btnSave'); 20486 var day = '', week = '', ot = j.find('#Overtime_Type_cd').val(); 20487 var perHr = j.find('#Hourly_Overtime_mn').val(); 20488 20489 if (ot == 10 || ot == 30) { 20490 day = j.find('#Overtime_Day_Max_sr').val(); 20491 } 20492 20493 if (ot == 20 || ot == 30) { 20494 var week = j.find('#Overtime_Week_Max_sr').val(); 20495 } 20496 20497 GLO.UI.Form.beginProcessing(btnSave); 20498 20499 $.ajax({ type: "POST", url: uri, "cache": false, data: { "otype": ot, "day": day, "week": week, "hourly": perHr } }) 20500 .success(function(data, textStatus, jqXHR) { 20501 var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Overtime Defaults Updated!</div></div>'; 20502 new GLO.Popup.Success(htm); 20503 20504 setTimeout(function() { 20505 location.reload(); 20506 }, 250); 20507 20508 //GLO.UI.Form.resetProcessing(); 20509 //btnSave.addClass('hide'); 20510 }) 20511 .error(function(jqXHR, textStatus, errorThrown) { 20512 GLO.Popup.Error('Unable to save. Please try again'); 20513 GLO.UI.Form.resetProcessing(); 20514 }); 20515 } 20516
20517 _conCommission.changePayrollLastPeriodEnd = function() { 20518 var jpop = $('#pop-payroll-date-rate').closest('.glopop'); 20519 var dtLastEnd = jpop.find('#Last_Payroll_Period_End_dt').val(); 20520 20521 if (UTIL.isDate(dtLastEnd)) { 20522 var dayOfWeek = new Date(dtLastEnd).getDay() + 1 + 1; //getDay() is zero indexed, so add 1 to get day of the week for dtLastEnd; then add 1 for next day 20523 20524 if (dayOfWeek == 8) { 20525 dayOfWeek = 1; 20526 } 20527 20528 jpop.find('#payroll-date-range-days').find(':radio[value=' + dayOfWeek + ']').prop('checked', true); 20529 } 20530 } 20531 _conCommission.openPayrollDateRange = function() { 20532 GLO.Popup.closeIfExist($('#pop-save-payroll-history').closest('.glopop')); 20533 20534 var aPayroll = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/payroll\', this, event, true)">Payroll report</a>'; 20535 var aTimesheet = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/timesheet\', this, event, true)">Timesheet report</a>'; 20536 //var aStaffGoals = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/StaffGoal\', this, event, true)">Staff Goals</a>'; 20537 var msg = '<p style="text-align: center; font-size: larger; font-weight: bold;">When do you pay payroll?</p>' 20538 + '<p>Conveniently sets the default date range on the ' + aTimesheet + ' and ' + aPayroll + '</p>'; 20539 20540 var dd = '<select id="Payroll_Date_Range_cd" name="Payroll_Date_Range_cd" onchange="GLO.Provider.Commission.changePayrollDateRange(this)">' 20541 + '<option value=""></option>' 20542 + '<option value="20">Once per month</option>' 20543 + '<option value="10">Twice per month</option>' 20544 + '<option value="30">Every 2 weeks</option>' 20545 + '<option value="40">Every week</option>' 20546 + '</select>'; 20547 20548 if (innerWidth > 900) { 20549 var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 20550 } else { 20551 var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 20552 } 20553 20554 var htmDays = '<fieldset id="payroll-date-range-days" class="hide">' 20555 + '<legend>Payroll starts on</legend>' 20556 + '<label for="payroll-day-sun"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-sun" value="1"/>' + days[0] + '</label>' 20557 + '<label for="payroll-day-mon"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-mon" value="2"/>' + days[1] + '</label>' 20558 + '<label for="payroll-day-tue"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-tue" value="3"/>' + days[2] + '</label>' 20559 + '<label for="payroll-day-wed"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-wed" value="4"/>' + days[3] + '</label>' 20560 + '<label for="payroll-day-thu"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-thu" value="5"/>' + days[4] + '</label>' 20561 + '<label for="payroll-day-fri"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-fri" value="6"/>' + days[5] + '</label>' 20562 + '<label for="payroll-day-sat"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-sat" value="7"/>' + days[6] + '</label>' 20563 + '</fieldset>'; 20564 20565 var htmTwicePerMonth = '<div id="payroll-date-range-twice-month">' 20566 //+ '<p style="margin-bottom: 0;">Default Payroll Schedule</p>' 20567 + '<ul>' 20568 + '<li>1st - 15th</li>' 20569 + '<li>16th - end of month</li>' 20570 + '</ul>' 20571 + '</div>'; 20572 20573 var htmEveryOtherWeek = '<div id="payroll-date-range-every2weeks">' 20574 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 20575 + '<label for="Last_Payroll_Period_End_dt">Last Payroll Period End</label>' 20576 + '<input id="Last_Payroll_Period_End_dt" type="text" onchange="GLO.Provider.Commission.changePayrollLastPerio
20576dEnd()"/>' 20577 + '</div>'; 20578 20579 var htm = '<div id="pop-payroll-date-rate">' + msg + dd + htmDays + htmTwicePerMonth + htmEveryOtherWeek + '</div>'; 20580 var jpop = GLO.Popup.Custom.openSimple(htm, 'Payroll Date Range', GLO.Provider.Commission.savePayrollDateRange); 20581 20582 var jrange = $('#report-payroll-date-range'); 20583 var startDay = 0, dateRange = jrange.attr('value'), lastPeriodEnd = jrange.attr('last_period_end_dt'); 20584 20585 if (dateRange > 0) { 20586 if ((dateRange > 30 && dateRange < 38) || (dateRange > 40 && dateRange < 48)) { 20587 startDay = UTIL.coalesceInt(dateRange % 10); 20588 dateRange = parseInt(dateRange/10) * 10; 20589 } 20590 20591 jpop.find('#Payroll_Date_Range_cd').val(dateRange).change(); 20592 20593 if (startDay > 0) { 20594 jpop.find('input[name="Payroll_Date_Range_Days_sr"][value="' + startDay + '"]').prop('checked', true); 20595 } 20596 } else { 20597 jpop.find('#Payroll_Date_Range_cd').change(); 20598 } 20599 20600 jpop.find('#Last_Payroll_Period_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 20601 , numberOfMonths: UI.getDatepickerMonths(), minDate: "-1M", maxDate: 0 }); 20602 20603 if (UTIL.isDate(lastPeriodEnd)) { 20604 jpop.find('#Last_Payroll_Period_End_dt').val(lastPeriodEnd); 20605 } 20606 } 20607 _conCommission.changePayrollDateRange = function(dd) { 20608 var jdays = $('#pop-payroll-date-rate #payroll-date-range-days').addClass('hide'); 20609 var jtwiceMonth = $('#pop-payroll-date-rate #payroll-date-range-twice-month').addClass('hide'); 20610 var jEvery2Weeks = $('#pop-payroll-date-rate #payroll-date-range-every2weeks').addClass('hide'); 20611 20612 if (dd.value == 30 || dd.value == 40) { 20613 jdays.removeClass('hide'); 20614 20615 if (dd.value == 30) { 20616 jEvery2Weeks.removeClass('hide'); 20617 } 20618 } else if (dd.value == 10) { 20619 jtwiceMonth.removeClass('hide'); 20620 } 20621 } 20622 _conCommission.savePayrollDateRange = function() { 20623 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SavePayrollDateRange?range='; 20624 var jpop = $('#pop-payroll-date-rate').closest('.glopop'); 20625 var range = UTIL.coalesceInt(jpop.find('#Payroll_Date_Range_cd').val()); 20626 var jdays = jpop.find('#payroll-date-range-days'); 20627 var lastPeriod = '', jLastPeriod = jpop.find('#Last_Payroll_Period_End_dt'); 20628 20629 if (jdays.is(':visible')) { 20630 var day = UTIL.coalesceInt(jdays.find('input[name="Payroll_Date_Range_Days_sr"]:checked').val(), GLO.Data.firstWeekDay, 2); 20631 range = UTIL.coalesceInt(range + day); 20632 } 20633 20634 if (jLastPeriod.is(':visible') && UTIL.isDate(jLastPeriod.val())) { 20635 //dtLastPeriodEnd = new Date(lastPeriod); 20636 lastPeriod = jLastPeriod.val(); 20637 } 20638 20639 var btnSave = jpop.find('.btnSave'); 20640 GLO.UI.Form.beginProcessing(btnSave); 20641 20642 $.ajax({ type: "POST", url: uri, "cache": false, data: { "range": range, "lastPayrollEnd": lastPeriod } }) 20643 .success(function(data, textStatus, jqXHR) { 20644 var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Payroll Date Rate Changed!</div></div>'; 20645 new GLO.Popup.Success(htm); 20646 20647 $('#report-payroll-date-range').attr('value', range).attr('last_period_end_dt', lastPeriod); 20648 _conCommission.initPayrollSchedule(); 20649 20650 GLO.UI.Form.resetProcessing(); 20651 GLO.Popup.close(jpop); 20652 20653 if (GLO.Report.portalName == 'payroll') { 20654 GLO.Popup.Processing.open('Loading Payroll Schedule Setting...', 'Re-Loading Payroll Report'); 20655 20656 setTimeout(function() { 20657 location.reload(); 20658 }, 250) 20659 } 20660 }) 20661 .error(function(jqXHR, textStatus, errorThrown) { 20662 GLO.Popup.Error('Unable to save. Please try again'); 20663 GLO.UI.Form.resetProcessing(); 20664 }); 20665 } 20666 20667 _conCommission.openSetAllServices = function() { 20668 var numberInputType = "text"; 20669 if (GLO.Info.isAndroid) { numberInputType = "number"; } 20670 20671 var htm = $('<div id="pop-commission-set-all-services"> <h1 class="friendly-msg2">
20671Set Commission For All Services</h1>' 20672 + '<div class="friendly-msg2" style="min-width: 300px; margin-top: 12px;">' 20673 + '<label for="All_Commission_mn">Commission</label>' 20674 + '<input id="All_Commission_mn" type="' + numberInputType + '" style="width: 50px; letter-spacing: 1px;"/> %' 20675 + '</div> </div>'); 20676 20677 var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.setAllServices); 20678 var jpop = ojpop.getPopup().addClass('no-persist'); 20679 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" }); 20680 } 20681 20682 _conCommission.setAllServices = function(element) { 20683 var jpop = $('#pop-commission-set-all-services').closest('.glopop'); 20684 var commission = jpop.find('#All_Commission_mn').val(); 20685 var jtr = $('#commission-by-staff-service').find('.tablesorter tbody').find('tr'); 20686 20687 for (var i=0; i < jtr.length; i++) { 20688 jtr.eq(i).find('.svc-commission input').val(commission); 20689 } 20690 20691 GLO.Popup.close(jpop); 20692 $('.ss-commission-buttons:first').find('.btnSave > a ').click(); 20693 } 20694 20695 function _upgradeToGoldPopup(msg) { 20696 var msg = '<p>Upgrade to the Gold Package ' + msg + '</p>'; 20697 var btnLearn = '<span class="btnAdd" href="/provider/profile/6"><a>Learn More</a></span>'; 20698 var htm = '<div>' + msg + btnLearn + '</div>'; 20699 20700 GLO.Popup.Info.open(htm, 'Gold Package'); 20701 } 20702 20703 _conCommission.openEditMinAndFeeFromReport = function() { 20704 if (!GLO.Report.allowReportChange()) { return; } 20705 20706 var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr'); 20707 var sid = tr.attr('staff_id'); 20708 var sname = tr.find('.staff-column').text(); 20709 var feeSupply = tr.attr('day_supply_fee_mn'), feeClean = tr.attr('day_clean_fee_mn'); 20710 20711 //var minWeekly = tr.find('.min-weekly-column').text().replace('$', ''); 20712 //var minDays = tr.find('.required-days-column').text(); 20713 var minWeek = UTIL.coalesceMoney(tr.attr('minWeek')); 20714 var minWeekDays = UTIL.coalesceInt(tr.attr('minWeekDays')); 20715 20716 var minDay = UTIL.coalesceMoney(tr.attr('minDay')); 20717 var minDayHours = UTIL.coalesceInt(tr.attr('minDayHours')); 20718 var minDayHalfHours = UTIL.coalesceInt(tr.attr('minDayHalfHours')); 20719 20720 var minHour = UTIL.coalesceMoney(tr.attr('minHour')); 20721 var minIncludeTip = UTIL.parseBool(tr.attr('minIncludeTip')); 20722 var minOvertimePerHour = UTIL.coalesceMoney(tr.attr('minOvertimePerHour')); 20723 20724 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 20725 _conCommission.openEditMinAndFee2(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour); 20726 } 20727 _conCommission.openEditMinAndFee = function(element) { 20728 if (!GLO.Report.allowReportChange()) { return; } 20729 20730 var tr = $(element).closest('tr'); 20731 var sid = tr.attr('staff_id'); 20732 var sname = tr.find('td.commission-column-staff').text(); 20733 20734 var feeSupply = UTIL.coalesceMoney(tr.find('td.commission-column-daily-fee-supply').text().replace('$', '')); 20735 var feeClean = UTIL.coalesceMoney(tr.find('td.commission-column-daily-fee-clean').text().replace('$', '')); 20736 20737 var minWeek = UTIL.coalesceMoney(tr.attr('minWeek')); 20738 var minWeekDays = UTIL.coalesceInt(tr.attr('minWeekDays')); 20739 20740 var minDay = UTIL.coalesceMoney(tr.attr('minDay')); 20741 var minDayHours = UTIL.coalesceInt(tr.attr('minDayHours')); 20742 var minDayHalfHours = UTIL.coalesceInt(tr.attr('minDayHalfHours')); 20743 20744 var minHour = UTIL.coalesceMoney(tr.attr('minHour')); 20745 var minIncludeTip = UTIL.parseBool(tr.attr('minIncludeTip')); 20746 var minOvertimePerHour = UTIL.coalesceMoney(tr.attr('minOvertimePerHour')); 20747 20748 _conCommission.openEditMinAndFee2(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour); 20749 } 20750 _conCommission.openEditMinAndFee2 = function(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) { 20751 if (_minCommissionPopupHtm === null) { 20752 if (UTIL.coalesceMoney($('#service-commission-type-setup #Service_Commission_Type1_pct').val()) == 0) { 20753 $('#pop-edit-min-and-fee').find('#pop-fee-early-normal').remove(); 20754 } 20755 20756 _minCommissionPopupHtm = $('#pop-edit-min-and-fee').outerHTML(); 20757 $('#pop-edit-min-and-fee').remove(); 20758 } 20759 20760 var jpop = GLO.Popup.Custom.openSimple(_minCommissionPopupHtm, sname, GLO.Provider.Commission.saveMinAn
20760dFees); 20761 var jtabs = jpop.find('#min-period-tabs'); 20762 var jmin = null, jtab = jtabs.find('#min-period-tab-hourly'); 20763 20764 jpop.find('#Day_Supply_Fee_mn').val(UTIL.displayMoney(feeSupply, true)); 20765 jpop.find('#Day_Clean_Fee_mn').val(UTIL.displayMoney(feeClean, true)); 20766 jpop.find('#Edit_Staff_id').val(sid); 20767 20768 if (minWeek > 0) { 20769 jmin = jpop.find('#Min_Week_mn').val(UTIL.displayMoney(minWeek, true, false, true)); 20770 jtab = jtabs.find('#min-period-tab-weekly'); 20771 } 20772 if (minDay > 0) { 20773 jmin = jpop.find('#Min_Day_mn').val(UTIL.displayMoney(minDay, true, false, true)); 20774 jtab = jtabs.find('#min-period-tab-daily'); 20775 } 20776 if (minHour > 0) { 20777 jmin = jpop.find('#Min_Hour_mn').val(UTIL.displayMoney(minHour, true, false, true)); 20778 jtab = jtabs.find('#min-period-tab-hourly'); 20779 } 20780 20781 if (minWeekDays) { 20782 jpop.find('#Min_Days_Week_sr').val(minWeekDays); 20783 } 20784 if (minDayHours) { 20785 jpop.find('#Min_Hours_Day_sr').val(minDayHours); 20786 } 20787 if (minDayHalfHours) { 20788 jpop.find('#Min_Hours_Half_Day_sr').val(minDayHalfHours); 20789 } 20790 if (UTIL.parseBool(minIncludeTip)) { 20791 jpop.find('#Min_Includes_Tip_fl').prop('checked', true); 20792 } 20793 20794 if (minOvertimePerHour > 0) { 20795 jpop.find('#Min_Overtime_mn').val(UTIL.displayMoney(minOvertimePerHour, true, false, true)); 20796 } 20797 20798 jtab.find('>a').click(); 20799 } 20800 _conCommission.displayMinPeriod = function(tabElement, periodName) { 20801 var jmin = $('#pop-edit-min-data'); 20802 var jpop = jmin.closest('.glopop'); 20803 jpop.find(':focus').blur(); 20804 20805 jmin.removeClass('min-period-hour').removeClass('min-period-day').removeClass('min-period-week').addClass(periodName); 20806 jpop.find('.min-period-tab.active-tab').removeClass('active-tab'); 20807 $(tabElement).closest('.min-period-tab').addClass('active-tab'); 20808 20809 if (!GLO.Info.isMobile(true)) { 20810 jmin.find('.min-per-period-value:visible').focus(); 20811 } 20812 } 20813 20814 function _getPayrollGuideLink(page, label) { 20815 return '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="GLO.Provider.Commission.openReportHelp(' + page + ')">' + label + '</a>'; 20816 } 20817 20818 _conCommission.helpMinPeriod = function() { 20819 var aMinHr = _getPayrollGuideLink(18, 'Hourly Minimum'); 20820 var aMinDay = _getPayrollGuideLink(19, 'Daily Minimum'); 20821 var aMinWk = _getPayrollGuideLink(20, 'Weekly Minimum'); 20822 20823 var arrow = '<b class="arrow-right">➜</b>'; 20824 var plusMin = '<b class="narrow-text">+ Min column</b>'; 20825 //var aPayrollRpt = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/payroll?highlight=plus-min-column&helloback=commission&openback=help&pageback=20\', true)">Payroll report</a>'; 20826 var aPayrollRpt = '<a onclick="GLO.Provider.Commission.openReportHelp(24)">Payroll report</a>'; 20827 20828 var msgHr = '<p>' + aMinHr + ': setup to guarantee staff make at least a minimum amount per hour</p>'; 20829 var msgDay = '<p>' + aMinDay + ': can now set how many hours/day count as a full day or a half day</p>'; 20830 var msgWk = '<p>' + aMinWk + ': gurantee staff make a minimum amount per week. Require a minimum days worked per work to receive weekly minimum? Can set how many hours/day count as a full day or a half day.</p>'; 20831 20832 var msg1 = '<p style="margin-top: 40px;">If the ' + aMinHr + ', ' + aMinDay + ', or ' + aMinWk + ' is used on a staff\'s payroll period then the ' + plusMin + ' is populated on the ' 20833 + aPayrollRpt + ' with the amount that is added to the <b>Service Commission</b></p>'; 20834 20835 var msg2 = '<p style="margin-top: 24px;">If ' + aMinHr + ', ' + aMinDay + ', or ' + aMinWk + ' are all setup ' + arrow + ' then will use the highest minimum for each staff during the payroll period</p>'; 20836 20837 var htm = '<div id="pop-help-min-commission">' + msgHr + msgDay + msgWk + msg1 + msg2 + '</div>'; 20838 GLO.Popup.Info.openSimple(htm, 'Staff Minimums').css({ "max-width": "900px" }); 20839 } 20840 _conCommission.changeMinPeriod = function(radio) { 20841 var jmin = $('#pop-edit-min-data').removeClass('min-period-hour').removeClass('min-period-day').removeClass('min-period-week'); 20842 //jmin.find('.pop-edit-field').addClass('hide'); 20843 20844 if (radio.value == 'hour') { 20845 jmin.addClass('min-period-hour'); //jmin.find('.pop-min-period-hour').removeClass('hide'); 20846 } else if (radio.value == 'day') { 20847 jmin.addClass('min-period-day'); 20848 } else if (radio.value == 'week') { 20849 jmin.addClass('min-period-week'); 20850 } 20851 20852 if (!GLO.Info.isMobile(true)) { 20853 jmin.find('.min-per-period-value:visible').focus(); 20854 } 20855 } 20856 function _isValidMin(jpop, minWeek, minDay, minDayHours, minWeekDays) { 20857 if ((minDay > 0 || minWeek > 0) && UTIL.coalesceInt(minDayHours, 0) == 0) { 20858 var fn = function() { 20859 var jday = jpop.find('#Min_Hours_Day_sr').focus(); 20860 UI.highlight(jday); 20861 }; 20862 20863 GLO.Popup.Warning.open('Please set how many hours are required in a day (minimum must be 1 or more)', 'Min Hours for a Full Day', fn); 20864 return false; 20865 } else if (minWeek > 0 && UTIL.coalesceInt(minWeekDays, 0) == 0) { 20866 var fn = function() { 20867 var jweek = jpop.find('#Min_Days_Week_sr').focus(); 20868 UI.highlight(jweek); 20869 }; 20870 20871 GLO.Popup.Warning.open('Please set how many days are required in a week (minimum must be 1 or more)', 'Min Days for a Full Week', fn); 20872 return false; 20873 } 20874 20875 return true; 20876 }
20877 _conCommission.saveMinAndFees = function() { 20878 var jpop = $('#pop-edit-min-and-fee').closest('.glopop'); 20879 var sid = jpop.find('#Edit_Staff_id').val(); 20880 20881 var feeSupply = jpop.find('#Day_Supply_Fee_mn').val().replace(',', ''); 20882 var feeClean = jpop.find('#Day_Clean_Fee_mn').val().replace(',', ''); 20883 //var minOption = jpop.find('input[name="Min_Period_cd"]:checked').val(); 20884 20885 var minWeek = jpop.find('#Min_Week_mn').val().replace(',', ''); 20886 var minWeekDays = jpop.find('#Min_Days_Week_sr').val(); 20887 //var minDayHours = jpop.find('#Min_Hours_Day_sr').val(); 20888 20889 var minDay = jpop.find('#Min_Day_mn').val().replace(',', ''); 20890 var minDayHours = jpop.find('#Min_Hours_Day_sr').val(); 20891 var minDayHalfHours = jpop.find('#Min_Hours_Half_Day_sr').val(); 20892 20893 var minHour = jpop.find('#Min_Hour_mn').val().replace(',', ''); 20894 var minOvertimePerHour = jpop.find('#Min_Overtime_mn').val(); 20895 var minIncludeTip = jpop.find('#Min_Includes_Tip_fl').val(); 20896 20897 var htm = $('<div id="pop-edit-start"> <h1 class="friendly-msg4">Effective Start Date</h1>' 20898 + '<div class="friendly-msg4" style="padding: 20px;">' 20899 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 20900 + '<label for="Min_Fee_Start_dt">Start Date</label>' 20901 + '<input id="Min_Fee_Start_dt" type="text" style="width: 110px; letter-spacing: 1px; text-align: center;"/>' 20902 + '</div> </div>'); 20903 20904 if (!_isValidMin(jpop, minWeek, minDay, minDayHours, minWeekDays)) { 20905 return; 20906 } 20907 20908 var fnSave = function () { 20909 var dt = $('#pop-edit-start #Min_Fee_Start_dt').val() 20910 GLO.Provider.Commission.saveMinAndFeesConfirmed(sid, dt, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour); 20911 }; 20912 20913 var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist'); 20914 20915 var dtToday = new Date().toGloDate(); 20916 jpop.find('#Min_Fee_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 }); 20917 jpop.find('#Min_Fee_Start_dt').val(dtToday); 20918 20919 jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" }); 20920 jpop.find('#Min_Fee_Start_dt').blur(); 20921 } 20922 _conCommission.saveMinAndFeesConfirmed = function(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) { 20923 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveMinAndFees?sid=' + sid; 20924 20925 var jdata = { "startDate": confirmDate, "feeSupply": feeSupply, "feeClean": feeClean 20926 , "minWeek": minWeek, "minWeekDays": minWeekDays 20927 , "minDay": minDay, "minDayHours": minDayHours, "minDayHalfHours": minDayHalfHours 20928 , "minHour": minHour, "minIncludeTip": minIncludeTip, "minOvertime": minOvertimePerHour }; 20929 20930 var jpop1 = $('#pop-edit-start').closest('.glopop'); 20931 var jpop2 = $('#pop-edit-min-and-fee').closest('.glopop'); 20932 20933 GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') ); 20934 GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') ); 20935 20936 $.ajax({ type: "POST", url: uri, "cache": false, data: jdata }) 20937 .success(function(data, textStatus, jqXHR) { 20938 GLO.Popup.close(jpop1); 20939 GLO.Popup.close(jpop2); 20940 GLO.Popup.Success.open('Weekly Minimum and Fees Updated', 'Save Successful'); 20941 20942 if ($('#bd #report-payroll').length) { 20943 GLO.Report.Payroll.search(); 20944 } else { 20945 _setMinAndFees(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour); 20946 } 20947 }) 20948 .error(function(jqXHR, textStatus, errorThrown) { 20949 GLO.Popup.Error.open('Unable to save<br/><br/>Please try again', 'Save Un-Successful'); 20950 GLO.UI.Form.resetProcessing(); 20951 }); 20952 } 20953 function _setMinAndFees(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) { 20954 var tr = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]'); 20955 tr.attr('minWeek', minWeek).attr('minWeekDays', minWeekDays);
20956 tr.attr('minDay', minDay).attr('minDayHours', minDayHours).attr('minDayHalfHours', minDayHalfHours); 20957 tr.attr('minHour', minHour).attr('minIncludeTip', minIncludeTip).attr('minOvertimePerHour', minOvertimePerHour); 20958 20959 feeSupply = UTIL.displayMoney(feeSupply); 20960 feeClean = UTIL.displayMoney(feeClean); 20961 20962 if (minWeek > 0) { 20963 var minText = UTIL.displayMoney(minWeek, false, false, true) + '/week'; 20964 20965 if (minWeekDays > 0) { 20966 minText += '<small>' + minWeekDays + ' days</small>'; 20967 } 20968 } else if (minDay > 0) { 20969 var minText = UTIL.displayMoney(minDay, false, false, true) + '/day'; 20970 20971 if (minDayHalfHours > 0 && minDayHours > 0) { 20972 minText += '<small>' + minDayHours + ' hrs / ' + minDayHalfHours + ' hrs</small>'; 20973 } else if (minDayHours > 0) { 20974 minText += '<small>' + minDayHours + ' hours</small>'; 20975 } 20976 } else if (minHour > 0) { 20977 var minText = UTIL.displayMoney(minHour, false, false, true) + '/hour'; 20978 20979 if (UTIL.parseBool(minIncludeTip)) { 20980 minText += '<small class="narrow-text">include Tips</small>'; 20981 } 20982 20983 if (minOvertimePerHour > 0) { 20984 minText += '<small class="narrow-text">Min Overtime = ' + UTIL.displayMoney(minOvertimePerHour) + '/hr</small>'; 20985 } 20986 } else { 20987 var minText = 'none'; 20988 } 20989 20990 tr.find('td.commission-column-min').css({ "color": "rgb(0, 200, 80)" }).html(minText); 20991 //tr.find('td.commission-column-min-days').css({ "color": "rgb(0, 200, 80)" }).text(minDays); 20992 tr.find('td.commission-column-daily-fee-supply').css({ "color": "rgb(0, 200, 80)" }).text(feeSupply); 20993 tr.find('td.commission-column-daily-fee-clean').css({ "color": "rgb(0, 200, 80)" }).text(feeClean); 20994 } 20995 20996 _conCommission.openEditStaffEarlyPercent = function(element) { 20997 if (!GLO.Report.allowReportChange()) { return; } 20998 20999 var tr = $(element).closest('tr'); 21000 var sid = tr.attr('staff_id'); 21001 var sname = tr.find('.commission-column-staff').text(); 21002 var earlyPercent = UTIL.coalesceInt($.trim(tr.find('td.commission-column-staff-early-percent').text()).replace('%', ''), 0); 21003 21004 if (earlyPercent == 0) { earlyPercent = ''; } 21005 21006 _openEditStaffEarlyPercent2(sid, sname, earlyPercent); 21007 } 21008 function _openEditStaffEarlyPercent2(sid, sname, earlyPercent) { 21009 var inputStyle = 'width: 50px; letter-spacing: 1px; text-align: center; font-size: 18px; font-weight: bold;'; 21010 21011 var ex1 = '<i class="narrow-text" style="display: inline;">(and then the remaining amount normally)</i>'; 21012 var p1 = '<p style="padding-bottom: 16px; line-height: 1.4; font-size: 16px; opacity: .8;">'; 21013 var p2 = '<p style="margin-top: 40px; padding-bottom: 8px; line-height: 1.4; font-size: 16px; opacity: .8;">'; 21014 var msg1 = p1 + 'You can pay this staff a percent of the service commission + adjusted amount early ' + ex1 + '</p>'; 21015 21016 //var iBottom = '<i class="narrow-text" style="display: inline;">(if early or normal amount is less than $10, then rounded to the nearest dollar)</i>'; 21017 var msgBottom = ''; //var msgBottom = p2 + 'Starting July 1, 2025 early commission rounded up to the nearest $10 ' + iBottom + '</p>'; 21018 21019 var inputHide = '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'; 21020 var label = '<label for="Service_Commission_Early_pct">Staff Early Commission</label>'; 21021 var inputPct = '<input id="Service_Commission_Early_pct" type="text" value="' + earlyPercent + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3" style="' + inputStyle + '"/>'; 21022 var pctSymbol = '<b class="display-percent" style="padding-left: 1px;">%</b>'; 21023 var htmInput = '<div>' + inputHide + label + inputPct + pctSymbol + '</div>'; 21024 21025 var htm = '<div id="pop-edit-staff-early-percent" style="max-width: 640px; padding-top: 0; padding-left: 12px; padding-right 6px; padding-bottom: 16px;">' 21026 + msg1 + htmInput + msgBottom 21027 + '</div>'; 21028 21029 var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveStaffEarlyPercent); 21030 } 21031 _conCommission.saveStaffEarlyPercent = function() { 21032 var jpop = $('#pop-edit-staff-early-percent').closest('.glopop'); 21033 var sid = jpop.find('#Edit_Staff_id').val(); 21034 var earlyPercent = jpop.find('#Service_Commission_Early_pct').val(); 21035 21036 //var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>'; 21037 var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveStaffServiceCommissionEarly?staff=' + sid + '&earlyPercent=' + earlyPercent; 21038 21039 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 21040
21041 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 21042 .success(function(data, textStatus, jqXHR) { 21043 GLO.Popup.close(jpop); 21044 21045 if (earlyPercent > 0) { 21046 earlyPercent = UTIL.roundNumber(UTIL.coalesceMoney(earlyPercent, 0), 2) + '%'; 21047 } else { 21048 earlyPercent = '<small>use default</small>'; 21049 } 21050 21051 $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-staff-early-percent').html(earlyPercent); 21052 }) 21053 .error(function(jqXHR, textStatus, errorThrown) { 21054 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 21055 }); 21056 } 21057 21058 _conCommission.openEditStaffTipPercent = function(element) { 21059 if (!GLO.Report.allowReportChange()) { return; } 21060 21061 var tr = $(element).closest('tr'); 21062 var sid = tr.attr('staff_id'); 21063 var sname = tr.find('.commission-column-staff').text(); 21064 21065 var td = tr.find('td.commission-column-staff-tip-percent'); 21066 var tipCommission = UTIL.coalesceInt(td.attr('tip_pct'), 0); 21067 var tipCommissionCredit = UTIL.coalesceInt(td.attr('tip_credit_pct'), 0); 21068 21069 if (tipCommission == 0) { tipCommission = ''; } 21070 if (tipCommissionCredit == 0) { tipCommissionCredit = ''; } 21071 21072 _openEditStaffTipPercent2(sid, sname, tipCommission, tipCommissionCredit); 21073 } 21074 function _openEditStaffTipPercent2(sid, sname, tipCommission, tipCommissionCredit) { 21075 var ex1 = '<i class="narrow-text" style="display: inline;">(like more commission paid early, higher commission percent, or a daily/weekly minimum)</i>'; 21076 var ex2 = '<i class="narrow-text" style="display: inline;">(for example paying 97% or 98% of tips paid with a card)</i>'; 21077 21078 var p1 = '<p style="line-height: 1.4; font-size: 14px; opacity: .8;">'; 21079 var msg1 = p1 + 'Sometimes staff have special negotiated commission ' + ex1 + ' so to offset this, you can pay staff a percent of tips</p>'; 21080 var msg2 = p1 + 'To offset credit card charges you can pay staff a percent of tips paid with a card ' + ex2 + '</p>'; 21081 var msg3 = '<p></p>'; 21082 21083 var htm = '<div id="pop-edit-staff-tip-percent" style="max-width: 720px; padding: 8px; padding-top: 0; padding-left: 16px;">' 21084 + '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>' 21085 + msg1 + msg2 + msg3 21086 21087 + '<div id="pop-edit-staff-tip-percent-all">' 21088 + '<label for="Tip_Commission_pct" style="margin-right: 69px;">Tip Commission</label>' 21089 + '<input id="Tip_Commission_pct" type="text" value="' + tipCommission + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3"/>' 21090 + '<b class="display-percent" style="padding-left: 1px;">%</b>' 21091 + '</div>' 21092 21093 + '<div id="pop-edit-staff-tip-percent-credit" title="Tip commission percentage when client pays with credit or debit card">' 21094 + '<label for="Tip_Commission_Credit_pct">Tip Commission Credit</label>' 21095 + '<input id="Tip_Commission_Credit_pct" type="text" value="' + tipCommissionCredit + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3"/>' 21096 + '<b class="display-percent" style="padding-left: 1px;">%</b>' 21097 + '</div>' 21098 + '</div>'; 21099 21100 var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveStaffTipPercent); 21101 } 21102 _conCommission.saveStaffTipPercent = function() { 21103 var jpop = $('#pop-edit-staff-tip-percent').closest('.glopop'); 21104 var sid = jpop.find('#Edit_Staff_id').val(); 21105 var tipCommission = jpop.find('#Tip_Commission_pct').val(); 21106 var tipCommissionCredit = jpop.find('#Tip_Commission_Credit_pct').val(); 21107 21108 //var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>'; 21109 var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveStaffTipCommission?staff=' + sid + '&commission=' + tipCommission + '&commissionCredit=' + tipCommissionCredit; 21110 21111 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 21112
21113 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 21114 .success(function(data, textStatus, jqXHR) { 21115 GLO.Popup.close(jpop); 21116 21117 21118 var td = $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-staff-tip-percent'); 21119 td.attr('tip_pct', tipCommission).attr('tip_credit_pct', tipCommissionCredit); 21120 td.html(data); 21121 }) 21122 .error(function(jqXHR, textStatus, errorThrown) { 21123 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 21124 }); 21125 } 21126 21127 _conCommission.openEditTaxWithheld = function(element) { 21128 if (!GLO.Report.allowReportChange()) { return; } 21129 21130 var tr = $(element).closest('tr'); 21131 var sid = tr.attr('staff_id'); 21132 var sname = tr.find('.commission-column-staff').text(); 21133 var withheld = $.trim(tr.find('td.commission-column-tax-withheld').text()).replace('%', ''); 21134 21135 if (withheld == 0) { withheld = ''; } 21136 21137 _conCommission.openEditTaxWithheld2(sid, sname, withheld); 21138 } 21139 _conCommission.openEditTaxWithheld2 = function(sid, sname, withheld) { 21140 var htm = '<div id="pop-edit-tax-withheld">' 21141 + '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>' 21142 + '<label for="Tax_Withheld_pct">Tax Withheld</label>' 21143 + '<input id="Tax_Withheld_pct" type="text" value="' + withheld + '" onkeypress="UI.numberOnly(event)" pattern="[0-9]*" maxlength="5"/>' 21144 + '<b class="display-percent" style="padding-left: 1px;">%</b>' 21145 + '</div>'; 21146 21147 var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveTaxWithheld); 21148 } 21149 _conCommission.saveTaxWithheld = function() { 21150 var jpop = $('#pop-edit-tax-withheld').closest('.glopop'); 21151 var sid = jpop.find('#Edit_Staff_id').val(); 21152 var withheld = jpop.find('#Tax_Withheld_pct').val(); 21153 21154 //var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>'; 21155 var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveTaxWithheld?sid=' + sid + '&withheld=' + withheld; 21156 21157 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 21158 21159 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 21160 .success(function(data, textStatus, jqXHR) { 21161 GLO.Popup.close(jpop); 21162 withheld = UTIL.roundNumber(UTIL.coalesceMoney(withheld, 0), 2) + '%'; 21163 $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-tax-withheld').text(withheld); 21164 }) 21165 .error(function(jqXHR, textStatus, errorThrown) { 21166 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 21167 }); 21168 } 21169 21170 _conCommission.openEditWage = function(element) { 21171 if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) { 21172 return _upgradeToGoldPopup('to Enable Clock/In Out, Timesheet Management, and track wages for hourly staff'); 21173 } else if (!GLO.Report.allowReportChange()) { 21174 return; 21175 } 21176 21177 var jwage = $('#ss-commission-hourly-wage').find('#Hourly_Wage_mn'); 21178 21179 if (jwage.length > 0) { 21180 var wage = jwage.text(); 21181 var sid = $('#commission-by-staff-service').attr('staff_id'); 21182 var sname = $('#commission-by-staff-service h2').attr('staff_name_vc'); 21183 } else { 21184 var jelement = $(element); 21185 var tr = jelement.closest('tr'); 21186 21187 var wage = jelement.text(); 21188 var sid = tr.attr('staff_id'); 21189 var sname = tr.find('.commission-column-staff').text(); 21190 } 21191 21192 _conCommission.openEditWage2(sid, sname, wage); 21193 } 21194 _conCommission.openEditWageOnPayroll = function() { 21195 var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr'); 21196 var sid = tr.attr('staff_id'); 21197 var sname = tr.find('.staff-column').text(); 21198 var wage = tr.find('.hourly-rate-column').text().replace('$', ''); 21199 21200 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 21201 _conCommission.openEditWage2(sid, sname, wage); 21202 } 21203 _conCommission.openEditWage2 = function(sid, sname, wage, password) { 21204 if (!GLO.Report.allowReportChange()) { return; } 21205 21206 if (UTIL.isEmpty(sid)) { 21207 sid = $('#simplemodal-container').find('#Staff_id').val(); 21208 } 21209 21210 if (innerWidth > 600) { 21211 var minWidth = '400px'; 21212 } else { 21213 var minWidth = '300px'; 21214 } 21215 21216 var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>'; 21217 var htm = '<div id="pop-edit-wage" style="min-width: ' + minWidth + '; margin-bottom: 16px;">' 21218 + '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>' 21219 + '<div style="margin-bottom: 12px;"><label for="Edit_Hourly_Wage_mn" style="font-weight: bold; font-size: larger; color: #4F81BD;">' + sname + '</label></div>' 21220 + throbber 21221 + '</div>'; 21222 21223 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Edit Hourly Wage', GLO.Provider.Commission.saveEditWage, null, true); 21224 var jpop = ojpop.getPopup(); 21225 var url = GLO.Link.WebsiteDomain + 'provider/manage/GetWage?sid=' + sid; 21226
21227 var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": { "report_password_vc": password } }) 21228 .success(function(data, textStatus, jqXHR) { 21229 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 21230 jpop.find('.btnSave').remove(); 21231 jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" }); 21232 } 21233 21234 jpop.find('#pop-wage-throbber').replaceWith(data); 21235 jpop.find('#Staff_Overtime_Start_dt').datepicker({ minDate: "-3M", maxDate: "+1M", calculateWeek: UTIL.datePickerCalculateWeek }); 21236 jpop.find('#Report_Password_vc').focus(); 21237 ojpop.realign(); 21238 }) 21239 .error(function(jqXHR, textStatus, errorThrown) { 21240 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 21241 }); 21242 } 21243 21244 _conCommission.openEditCommissionOnPayroll = function() { //= called by Payroll Report 21245 var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr'); 21246 21247 var sid = tr.attr('staff_id'); 21248 var sname = tr.find('.staff-column').text(); 21249 21250 var commission = tr.find('.commission-percent-column').text().replace('%', ''); 21251 var hasDiffCommissionPerService = (commission.indexOf('-') !== -1); 21252 21253 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 21254 21255 _conCommission.openEditCommission2(sid, sname, commission, null, event, hasDiffCommissionPerService); 21256 } 21257 _conCommission.openEditCommission = function(element, event, hasDiffCommissionPerService) { //= called by Commission Report 21258 if (!GLO.Report.allowReportChange()) { return; } 21259 21260 var jelement = $(element); 21261 var tr = jelement.closest('tr'); 21262 21263 var commission = jelement.text().replace('%', '').replace('none', ''); 21264 var sid = tr.attr('staff_id'); 21265 var sname = tr.find('.commission-column-staff').text(); 21266 var currentCommissionStartDescription = tr.find('td.svc-price').attr('title'); 21267 21268 _conCommission.openEditCommission2(sid, sname, commission, jelement, event, hasDiffCommissionPerService, currentCommissionStartDescription); 21269 } 21270 21271 _conCommission.openEditCommission2 = function(sid, sname, commission, jelement, event, hasDiffCommissionPerService, currentCommissionStartDescription) { 21272 var uri = '', setByService = '', numberInputType = "text"; 21273 21274 if (GLO.Info.isAndroid) { numberInputType = "number"; } 21275 21276 if (GLO.Info.isGold()) { 21277 uri = GLO.Link.WebsiteDomain + 'provider/manage/CommissionByStaffService?sfilter=' + sid; 21278 setByService = '<div style="margin: 20px; margin-bottom: 32px; text-align: center;"> <a href="' + uri + '">Set By Service</a> </div>'; 21279 21280 if (hasDiffCommissionPerService) { 21281 UI.openLink(uri, event, jelement) 21282 return; 21283 } 21284 } 21285 21286 if (!UTIL.isEmpty(currentCommissionStartDescription)) { 21287 var css = 'margin: 0 6px 24px; text-align: center; letter-spacing: 0; font-family: arial; font-stretch: condensed;'; 21288 currentCommissionStartDescription = '<div style="' + css + '">' + currentCommissionStartDescription + '</div>'; 21289 } else { 21290 currentCommissionStartDescription = ''; 21291 } 21292 21293 var htm = $('<div id="pop-edit-commission"> <h1 class="friendly-msg2">Edit Commission</h1> <div class="friendly-msg2" style="min-width: 300px;">' 21294 + '<label for="Edit_Commission_pct" style="display: block; margin: 8px; margin-bottom: 2px; text-align: center;">' + sname + ' Commission</label>' 21295 + '<input id="Edit_Commission_pct" original_commission_pct="' + commission + '" type="' + numberInputType + '" value="' + commission + '" pattern="[0-9+\.]+" maxlength="5" onkeypress="UI.numberOnly(event, true)" style="width: 60px; letter-spacing: 1px;"/> %' 21296 + '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>' 21297 + setByService + currentCommissionStartDescription 21298 + '</div> </div>'); 21299 21300 var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveEditCommission); 21301 var jpop = ojpop.getPopup().addClass('no-persist'); 21302 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" }); 21303 } 21304 21305 _conCommission.saveEditCommission = function() { 21306 var jpop = $('#pop-edit-commission').closest('.glopop'); 21307 var sid = jpop.find('#Edit_Staff_id').val(); 21308 21309 var jcommission = jpop.find('#Edit_Commission_pct'); 21310 var commission = jcommission.val(); 21311 21312 if (false && jcommission.attr('original_commission_pct') == commission) { 21313 _conCommission.saveEditCommissionConfirmed(sid, commission); 21314 } else { 21315 var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>' 21316 + '<div class="friendly-msg4" style="padding: 20px;">' 21317 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 21318 + '<label for="Commission_Start_dt">Commission Start Date</label>' 21319 + '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>' 21320 + _getCurrentCommissionStart() 21321 + '</div> </div>'); 21322 21323 var fnSave = function () { 21324 var dt = $('#pop-commission-start #Commission_Start_dt').val() 21325 GLO.Provider.Commission.saveEditCommissionConfirmed(sid, commission, dt); 21326 } 21327 21328 var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist'); 21329
21330 var dtToday = new Date().toGloDate(); 21331 jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 }); 21332 jpop.find('#Commission_Start_dt').val(dtToday); 21333 21334 jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" }); 21335 jpop.find('#Commission_Start_dt').blur(); 21336 } 21337 } 21338 21339 _conCommission.saveEditCommissionConfirmed = function(sid, commission, confirmDate) { 21340 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveCommission?sid=' + sid; 21341 21342 var jpop1 = $('#pop-commission-start').closest('.glopop'); 21343 var jpop2 = $('#pop-edit-commission').closest('.glopop'); 21344 21345 GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') ); 21346 GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') ); 21347 21348 $.ajax({ type: "POST", url: uri, "cache": false, data: { "commission": commission, "commissionStartDate": confirmDate } }) 21349 .success(function(data, textStatus, jqXHR) { 21350 GLO.Popup.close(jpop1); 21351 GLO.Popup.close(jpop2); 21352 GLO.Popup.Success.open('Service Commission Updated', 'Commission Saved'); 21353 21354 if ($('#bd #report-payroll').length) { 21355 GLO.Report.Payroll.search(); 21356 } else { 21357 _setCommission(sid, commission); 21358 } 21359 }) 21360 .error(function(jqXHR, textStatus, errorThrown) { 21361 GLO.Popup.Error('Unable to save. Please try again'); 21362 GLO.UI.Form.resetProcessing(); 21363 }); 21364 } 21365 21366 _conCommission.gotoCommissionReport_IsEmployee = function() { 21367 _conCommission.gotoCommissionReport('commission-column-is-employee', 'Set which staff are employees'); 21368 } 21369 _conCommission.gotoCommissionReport_StaffFee = function(highlight, msg) { 21370 _conCommission.gotoCommissionReport('staff-svc-fee', 'Set which staff are charged staff service fees'); 21371 } 21372 _conCommission.gotoEditEarlyPercent = function() { 21373 _conCommission.gotoCommissionReport('early', 'Change Early Commission Percent', '% Early Commission'); 21374 } 21375 _conCommission.gotoEditNormalPercent = function() { 21376 _conCommission.gotoCommissionReport('normal', 'Change Normal Commission Percent', '% Normal Commission'); 21377 } 21378 _conCommission.gotoEditMinHourly = function() { 21379 _conCommission.gotoCommissionReport('min-hourly-rate', 'Change Minimum Hourly Rate', 'Hourly Rate'); 21380 } 21381 _conCommission.gotoCommissionReport = function(highlight, msg, title) { 21382 var url = 'provider/manage/CommissionByStaffService?highlight=' + highlight; 21383 21384 title = UTIL.coalesce(title, 'Payroll Setup'); 21385 21386 GLO.Popup.Processing.open(msg + '<br/><br/>Loading Payroll Setup...', title); 21387 GLO.Report.CellSummary.gotoReport(url, null, event); 21388 } 21389 _conCommission.gotoServiceFee = function() { 21390 var url = 'provider/profile/4?goto=fee'; 21391 21392 GLO.Popup.Processing.open('Loading Manage Staff Service Fees...', 'Staff Service Fees'); 21393 GLO.Report.CellSummary.gotoReport(url, null, event); 21394 } 21395 _conCommission.gotoCreditFee = function() { 21396 var url = 'provider/profile/4?goto=fee&highlight=creditfee'; 21397 21398 GLO.Popup.Processing.open('Loading Manage Staff Credit Card Fee...', 'Staff Credit Card Fee'); 21399 GLO.Report.CellSummary.gotoReport(url, null, event); 21400 } 21401 _conCommission.gotoEditDefaultProductCommission = function(element, event) { 21402 var url = 'provider/inventory#action=inventory-options'; 21403 21404 GLO.Popup.Processing.open('Loading Manage Inventory to allow you to change the default product commission %...', 'Edit Product Commission'); 21405 GLO.Report.CellSummary.gotoReport(url, null, event); 21406 } 21407 _conCommission.openEditProductCommissionOnReport = function() {
21408 var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr'); 21409 var sid = tr.attr('staff_id'); 21410 var sname = tr.find('.staff-column').text(); 21411 var commission = tr.find('.commission-percent-column').text().replace('%', ''); 21412 21413 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 21414 21415 _conCommission.openEditProductCommission2(sid, sname, commission); 21416 } 21417 _conCommission.openEditProductCommission = function(element, event) { 21418 if (!GLO.Report.allowReportChange()) { return; } 21419 21420 var commission = '', jelement = $(element); 21421 var tr = jelement.closest('tr'); 21422 21423 if (jelement.find('b').length > 0) { 21424 commission = jelement.find('b').text().replace('%', ''); 21425 } 21426 21427 var sid = tr.attr('staff_id'); 21428 var sname = tr.find('.commission-column-staff').text(); 21429 21430 _conCommission.openEditProductCommission2(sid, sname, commission); 21431 } 21432 _conCommission.openEditProductCommission2 = function(sid, sname, commission) { 21433 var numberInputType = "text"; 21434 if (GLO.Info.isAndroid) { numberInputType = "number"; } 21435 21436 var htm = $('<div id="pop-edit-product-commission"> <h1 class="friendly-msg2">Product Commission</h1> <div class="friendly-msg2" style="min-width: 300px;">' 21437 + '<label for="Product_Commission_pct" style="display: block; margin: 8px; margin-bottom: 2px; text-align: center;">' + sname + ' Product Commission</label>' 21438 + '<input id="Product_Commission_pct" original_commission_pct="' + commission + '" type="' + numberInputType + '" value="' + commission + '" pattern="[0-9+\.]+" maxlength="5" onkeypress="UI.numberOnly(event, true)" style="width: 50px; letter-spacing: 1px;"/> %' 21439 + '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>' 21440 + '</div> </div>'); 21441 21442 var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveProductCommission); 21443 var jpop = ojpop.getPopup().addClass('no-persist'); 21444 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" }); 21445 } 21446 21447 _conCommission.printPayroll = function() { 21448 var tbl = $('#report-payroll-summary'); 21449 var dateRange = tbl.attr('start_d') + ' - ' + tbl.attr('end_d'); 21450 21451 var tr = tbl.find('td.cell-summary-selected').closest('tr'); 21452 var sid = tr.attr('staff_id'); 21453 var sname = tr.find('.staff-column').text(); 21454 var h2 = '<h2>' + sname + ': ' + dateRange + '</h2>'; 21455 //var commission = tr.find('.commission-percent-column').text().replace('%', ''); 21456 21457 var productCommission = UTIL.coalesceMoney(tr.find('.product-dollar-column').text().replace('$', '')); 21458 var serviceCommission = UTIL.coalesceMoney(tr.find('.service-dollar-column').text().replace('$', '')) + UTIL.coalesceMoney(tr.find('.plus-min-column').text().replace('$', '')); 21459 21460 var feeSupply = UTIL.coalesceMoney(tr.find('.supply-fee-column').text().replace('$', '')); 21461 var feeClean = UTIL.coalesceMoney(tr.find('.clean-fee-column').text().replace('$', '')); 21462 21463 var adjust = UTIL.coalesceMoney(tr.find('.adjust-input').val()); 21464 var tips = UTIL.coalesceMoney(tr.find('.tip-column').text().replace('$', '')); 21465 var preTaxTotal = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', '')); 21466 21467 var social = UTIL.coalesceMoney(tr.attr('social_security_mn')); 21468 var medicare = UTIL.coalesceMoney(tr.attr('medicare_mn')); 21469 var employmentInsurance = UTIL.coalesceMoney(tr.attr('employment_insurance_mn')); 21470 21471 var fedWithheld = UTIL.coalesceMoney(tr.attr('federal_tax_mn')); 21472 //var totalWithheld = UTIL.coalesceMoney(tr.attr('total_withheld_mn')); 21473 var totalAfterTax = UTIL.coalesceMoney(tr.attr('wage_after_tax_mn')); 21474 21475 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 21476 21477 var tbl = _printPayrollHtm(productCommission, serviceCommission, feeSupply, feeClean, adjust, tips, preTaxTotal, -social, -medicare, -employmentInsurance, -fedWithheld, totalAfterTax); 21478 var htm = '<div id="payroll-print-staff">' + h2 + tbl + '</div>'; 21479 var css = '#doc3 { visibility: hidden; display: none; } #payroll-print-staff-table { margin: auto; margin-top: 8px; }'; 21480 21481 UI.Print.print(htm, css, true); 21482 //var jpop = GLO.Popup.Info.open(htm, h2).addClass('pop-print-payroll'); 21483 //GLO.Popup.Custom.singleButton(jpop, 'Close'); 21484 } 21485 function _printPayrollHtm(productCommission, serviceCommission, feeSupply, feeClean, adju
21485st, tips, preTaxTotal, social, medicare, employmentInsurance, fedWithheld, totalAfterTax) { 21486 var tbl = _printPayrollHtmRow('Product Commission', productCommission); 21487 tbl += _printPayrollHtmRow('Service Commission', serviceCommission); 21488 tbl += _printPayrollHtmRow('Supply Fees', feeSupply); 21489 tbl += _printPayrollHtmRow('Cleaning Fees', feeClean); 21490 21491 tbl += _printPayrollHtmRow('Ajdustment', adjust); 21492 tbl += _printPayrollHtmRow('Tips', tips); 21493 tbl += _printPayrollHtmRow('Pre-Tax Total', preTaxTotal); 21494 21495 if (GLO.Data.provider.country == "US") { 21496 tbl += _printPayrollHtmRow('Social Security', social); 21497 tbl += _printPayrollHtmRow('Medicare', medicare); 21498 } else if (GLO.Data.provider.country == "CA") { 21499 if (GLO.Data.provider.state == "QC") { 21500 tbl += _printPayrollHtmRow('Quebec Pension Plan (QPP)', social); 21501 } else { 21502 tbl += _printPayrollHtmRow('Canada Pension Plan (CPP)', social); 21503 } 21504 21505 tbl += _printPayrollHtmRow('Employment Insurance (EU)', employmentInsurance); 21506 } 21507 21508 tbl += _printPayrollHtmRow('Federal Tax Withheld', fedWithheld); 21509 tbl += _printPayrollHtmRow('Total After Tax', totalAfterTax); 21510 21511 return '<table id="payroll-print-staff-table">' + tbl + '</table>'; 21512 } 21513 function _printPayrollHtmRow(label, amount) { 21514 if (amount != 0) { 21515 var id = 'print-payroll-' + UTIL.replaceAll($.trim(label).toLowerCase(), ' ', ''); 21516 return '<tr id="' + id + '"><th>' + label + '</th><td>' + UTIL.displayMoney(amount, false, true, true) + '</td></tr>'; 21517 } else { 21518 return ''; 21519 } 21520 } 21521 21522 _conCommission.saveProductCommission = function() { 21523 var jpop = $('#pop-edit-product-commission').closest('.glopop'); 21524 var sid = jpop.find('#Edit_Staff_id').val(); 21525 var commission = jpop.find('#Product_Commission_pct').val(); 21526 21527 var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>' 21528 + '<div class="friendly-msg4" style="padding: 20px;">' 21529 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 21530 + '<label for="Commission_Start_dt">Commission Start Date</label>' 21531 + '<input id="Commission_Start_dt" type="text" style="width: 100px; letter-spacing: 1px;"/>' 21532 + '</div> </div>'); 21533 21534 var fnSave = function () { 21535 var dt = $('#pop-commission-start #Commission_Start_dt').val() 21536 GLO.Provider.Commission.saveProductCommissionConfirmed(sid, commission, dt); 21537 } 21538 21539 var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist'); 21540 21541 var dtToday = new Date().toGloDate(); 21542 jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 }); 21543 jpop.find('#Commission_Start_dt').val(dtToday); 21544 21545 jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" }); 21546 jpop.find('#Commission_Start_dt').blur(); 21547 } 21548 _conCommission.saveProductCommissionConfirmed = function(sid, commission, dt) { 21549 var uri = GLO.Link.WebsiteDomain + 'provider/manage/ProductCommissionByStaff?sid=' + sid; 21550 var jpop1 = $('#pop-commission-start').closest('.glopop'); 21551 var jpop2 = $('#pop-edit-product-commission').closest('.glopop'); 21552 21553 GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') ); 21554 GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') ); 21555 21556 $.ajax({ type: "POST", url: uri, "cache": false, data: { "commission": commission, "commissionStartDate": dt } }) 21557 .success(function(data, textStatus, jqXHR) { 21558 GLO.Popup.close(jpop1); 21559 GLO.Popup.close(jpop2); 21560 GLO.Popup.Success.open('Product Commission Updated', 'Save Product Commission'); 21561 21562 _setProductCommission(sid, commission); 21563 }) 21564 .error(function(jqXHR, textStatus, errorThrown) { 21565 GLO.Popup.Error('Unable to save. Please try again'); 21566 GLO.UI.Form.resetProcessing(); 21567 }); 21568 } 21569 _conCommission.saveEnableStaffFee = function(element, event) { 21570 var jcheckbox = $(element); 21571 var tr = jcheckbox.closest('tr'); 21572 var sid = tr.attr('staff_id'); 21573 var sname = tr.find('.commission-column-staff').text(); 21574 var isEnable = jcheckbox.prop('checked'); 21575 var uri = GLO.Link.WebsiteDomain + 'provider/manage/EnableStaffFee?sid=' + sid + '&enable=' + isEnable; 21576
21577 $.ajax({ type: "POST", url: uri, "cache": false }) 21578 .success(function(data, textStatus, jqXHR) { 21579 var word = 'Disabled', uri = 'provider/profile/4?goto=fee'; 21580 21581 if (isEnable) { word = 'Enabled'; } 21582 21583 var msg = '<p>Staff Service Fee ' + word + ' for ' + sname + '</p>'; 21584 var btn = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uri + '\', this, event, true)">Setup Staff Service Fees</a></span>'; 21585 var htm = '<div id="pop-success-enable-staff-service-fee">' + msg + '<div>' + btn + '</div></div>'; 21586 21587 GLO.Popup.Success.open(htm, 'Staff Service Fees'); 21588 }) 21589 .error(function(jqXHR, textStatus, errorThrown) { 21590 GLO.Popup.Error('Unable to save. Please try again'); 21591 GLO.UI.Form.resetProcessing(); 21592 }); 21593 } 21594 _conCommission.saveEnableEmployee = function(element, event) { 21595 var jcheckbox = $(element); 21596 var tr = jcheckbox.closest('tr'); 21597 var sid = tr.attr('staff_id'); 21598 var sname = tr.find('.commission-column-staff').text(); 21599 var isEnable = jcheckbox.prop('checked'); 21600 var dstype = $('#report-commission-staff-list').attr('default_staff_type_cd') 21601 21602 if (isEnable) { 21603 if (tr.find('td.commission-column-merchant .merchant-personal').length > 0) { 21604 var aemail = '<a href="mailto:[email protected]">[email protected]</a>'; 21605 var msg1 = sname + ' has personal merchant account'; 21606 var msg2 = 'To remove this merchant account and change ' + sname + ' to an employee please send an email to: ' + aemail; 21607 var htm = '<div id="pop-warn-employee-no-merchant"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>'; 21608 21609 GLO.Popup.Warning.open(htm, 'Employee Cannot Have Personal Merchant Account'); 21610 jcheckbox.prop('checked', false); 21611 return false; 21612 } 21613 21614 var svcCommission = tr.find('.svc-price').text().replace('none', '').replace('-', ''); 21615 var productCommission = tr.find('.commission-column-product').text().replace('none', '').replace('-', ''); 21616 var hourlyWage = tr.find('.commission-column-hourly-wage').text().replace('none', '').replace('-', ''); 21617 21618 if (!UTIL.isEmpty(svcCommission)) { 21619 var stype = 20; 21620 } else if (!UTIL.isEmpty(hourlyWage)) { 21621 var stype = 10; 21622 } else if (!UTIL.isEmpty(dstype)) { 21623 var stype = dstype; 21624 } else { //if (!UTIL.isEmpty(productCommission)) 21625 var stype = 20; 21626 } 21627 } else { 21628 var stype = 30; 21629 } 21630 21631 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SetStaffType?sid=' + sid + '&stype=' + stype; 21632 21633 $.ajax({ type: "POST", url: uri, "cache": false }) 21634 .success(function(data, textStatus, jqXHR) { 21635 var msg = sname + ' changed to '; 21636 21637 if (isEnable) { msg += 'an employee'; } else { msg += ' an independent staff'; } 21638 21639 var htm = '<div id="pop-success-staff-staff-type">' + msg + '</div>'; 21640 21641 GLO.Popup.Success.open(htm, 'Staff Type'); 21642 }) 21643 .error(function(jqXHR, textStatus, errorThrown) { 21644 GLO.Popup.Error('Unable to save. Please try again'); 21645 GLO.UI.Form.resetProcessing(); 21646 }); 21647 } 21648 _conCommission.saveEditWage = function() { 21649 var jpop = $('#pop-edit-wage').closest('.glopop'); 21650 var sid = jpop.find('#Edit_Staff_id').val(); 21651 var jwage = jpop.find('#Edit_Hourly_Wage_mn'); 21652 var password = $.trim(jpop.find('#Report_Password_vc').val()); 21653 21654 var jReportRow = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]'); 21655 var jd = { "hourly_wage_mn": $.trim(jwage.val()), "report_password_vc": password }; 21656 var xml = '', trs = jpop.find('.employee-service-row') 21657 21658 if (trs.length) { 21659 for (var i=0; i < trs.length; i++) { 21660 var tr = trs.eq(i), accessType = 0; 21661 var svcid = tr.attr('service_id'), ssid = UTIL.cleanString(tr.attr('staff_service_id')), wage = tr.find('.custom-wage input').val(); 21662 var dsvc = tr.attr('default_service_id'); 21663 21664 if (tr.find('.wiz5-svc-enable').prop('checked')) { 21665 accessType = 4; 21666 } else if (!UTIL.isEmpty(ssid)) { 21667 accessType = 5; 21668 } 21669 21670 if (accessType > 0) { 21671 xml += '<li service_id="' + svcid + '" staff_service_id="' + ssid + '" hourly_mn="' + wage + '" access_type_cd="' + accessType + '"/>'; 21672 21673 if (accessType == 5) { 21674 var swage = '$0'; 21675 } else { 21676 var swage = UTIL.coalesce(UTIL.displayMoney(wage), tr.find('.default-wage').text(), '$0'); 21677 } 21678 21679 if (dsvc == 2330) { 21680 $('#Paid_Vacation_Amount').text(swage); 21681 jReportRow.find('.commission-column-vacation > a').text(swage); 21682 } else if (dsvc == 2331) { 21683 $('#Paid_Sick_Amount').text(swage); 21684 jReportRow.find('.commission-column-sick > a').text(swage); 21685 } 21686 } 21687 } 21688 21689 jd.employee_service_xml = UTIL.htmlEncode('<ol>' + xml + '</ol>'); 21690 } 21691 21692 var jovertime = jpop.find('#Staff_Overtime_mn'); 21693 var newOvertime = UTIL.coalesceMoney(jovertime.val()), currentOvertime = UTIL.coalesceMoney(jovertime.attr('original_value')); 21694 var overtimeStart = jpop.find('#Staff_Overtime_Start_dt').val(); 21695 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveWage?sid=' + sid + '&overtime=' + newOvertime + '&overtimeStart=' + overtimeStart; 21696 21697 if (currentOvertime != newOvertime) { 21698 uri += '&overtimeChange=1'; 21699 } 21700 21701 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 21702
21703 $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 21704 .success(function(data, textStatus, jqXHR) { 21705 if ($(data).find('#report-password-container').length) { 21706 jpop.find('.no-results-report-role').remove(); 21707 jpop.find('#edit-employee-service').before(data); 21708 jpop.find('.btnSearchWithReportPassword').remove(); 21709 21710 jpop.css({ "top": "24px", "height": "inherit" }).find('#Report_Password_vc').focus(); 21711 21712 GLO.UI.Form.resetProcessing(); 21713 return; 21714 } 21715 21716 GLO.Popup.close(jpop); 21717 GLO.Popup.Success.open('Hourly Wage Updated', 'Wage Saved'); 21718 21719 if ($('#bd #report-payroll').length) { 21720 //GLO.Popup.Success.open('Refreshing Wage...', 'Wage Updated'); 21721 GLO.Report.Payroll.search(); 21722 } else { 21723 var summary = $('<div>' + data + '</div>').find('#save-wage-summary').html(); 21724 _setWage(sid, summary, newOvertime); 21725 } 21726 }) 21727 .error(function(jqXHR, textStatus, errorThrown) { 21728 GLO.Popup.Error('Unable to save. Please try again'); 21729 GLO.UI.Form.resetProcessing(); 21730 }); 21731 } 21732 21733 function _setProductCommission(sid, productCommission) { 21734 if (!UTIL.isEmpty(productCommission)) { 21735 var pc = productCommission + '%'; 21736 } else { 21737 var pc = 'use default'; 21738 } 21739 21740 var j = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.commission-column-product > a'); 21741 21742 if (j.length > 0) { 21743 j.css({ "border-color": "rgb(0, 200, 80)" }); 21744 21745 if (pc !== 'use default') { 21746 if (j.find('>b').length > 0) { 21747 j = j.find('>b'); 21748 } else { 21749 j = j.html('<b></b>').find('>b'); 21750 } 21751 } 21752 21753 j.text(pc); 21754 j.css({ "color": "rgb(0, 200, 80)" }); 21755 } 21756 } 21757 21758 function _setWage(sid, summary, newOvertime) { 21759 summary = UTIL.coalesceString(summary, 'none'); 21760 var jwage = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.commission-column-hourly-wage > a'); 21761 21762 if (jwage.length > 0) { 21763 jwage.css({ "border-color": "rgb(0, 200, 80)" }); 21764 21765 if (summary !== 'none') { 21766 if (jwage.find('>b').length > 0) { 21767 jwage = jwage.find('>b'); 21768 } else { 21769 jwage = jwage.html('<b></b>').find('>b'); 21770 } 21771 } 21772 21773 jwage.text(summary); 21774 jwage.css({ "color": "rgb(0, 200, 80)" }); 21775 21776 var bUpdated = '<b style="display: inline-block; padding: 2px 8px 0px; border-radius: 12px; font-family: arial; background-color: rgb(0,255,0);">Updated</b>'; 21777 var tr = jwage.closest('tr'); 21778 21779 tr.attr('overtimePerHour', newOvertime); 21780 tr.find('.commission-column-hourly-service').find('span').html(bUpdated); 21781 } else { 21782 var j = $('#ss-commission-hourly-wage'); 21783 21784 if (j.length) { 21785 j.find('#Hourly_Wage_mn').text(summary).css({ "color": "rgb(0, 200, 80)" }); 21786 j.find('#ss-commission-edit-hourly-wage').text('(edit)').css({ "border-color": "rgb(0, 200, 80)", "color": "rgb(0, 200, 80)" }); 21787 } else { 21788 $('#wiz5-popupStaffConfig #wiz5-hourly-row > a').text(summary); 21789 } 21790 } 21791 } 21792 21793 function _setCommission(sid, commission) { 21794 var jcommission = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.svc-price > a').css({ "color": "rgb(0, 200, 80)" }); 21795 21796 if (commission > 0) { 21797 var strCommission = commission + '%'; 21798 } else { 21799 var strCommission = 'none'; 21800 } 21801 21802 if (jcommission.find('>b').length > 0) { 21803 jcommission = jcommission.find('>b'); 21804 } else { 21805 jcommission = jcommission.html('<b></b>').find('>b'); 21806 } 21807 21808 if (commission > 0 && UTIL.coalesceInt(jcommission.text().replace('none', '').replace('%', ''), 0) === 0) { 21809 jcommission.closest('tr').find('td.staff-svc-fee input').prop('checked', true).change(); 21810 } 21811 21812 jcommission.css({ "border-color": "rgb(0, 200, 80)" }) 21813 jcommission.text(strCommission); 21814 } 21815 21816 _conCommission.canEditStaffCommission = function() { 21817 if (GLO.Info.roleType < 220) { 21818 var msg = '<div> <h1 class="friendly-msg4">Permission Warning</h1> <div class="friendly-msg4">Please login as a manager or admin to update the service commission</div></div>'; 21819 new GLO.Popup.Warning(msg); 21820 return false; 21821 } else { 21822 return true; 21823 } 21824 } 21825 21826 _conCommission.gotoStaffService = function(event) { 21827 if (!_conCommission.canEditStaffCommission()) { return; } 21828 21829 var sid = $('#wiz5-popupStaffConfig #Staff_id').val(); 21830 var uri = GLO.Link.Page.Provider.Home + 'manage/CommissionByStaffService?sfilter=' + sid; 21831 21832 if (event.ctrlKey) { 21833 var childWindow = UI.openChildWindow(uri, '', true); 21834 } else { 21835 document.location = uri; 21836 } 21837 } 21838 21839 function _getCurrentCommissionStart() { 21840 if (UTIL.isDate(_dtCommissionStart)) { 21841 var day = new Date(_dtCommissionStart).toGloDateString(true, false, true, true) + ', ' + new Date(_dtCommissionStart).getFullYear(); 21842 21843 var label = '<label style="padding-right: 8px; letter-spacing: 0;">Current Commission Start</label>'; 21844 var value = '<b style="font-size: large; color: #4F81BD;">' + day + '</b>'; 21845 21846 return '<div style="margin-top: 24px; text-align: center;">' + label + value + '</div>'; 21847 } else { 21848 return ''; 21849 } 21850 } 21851 21852 _conCommission.saveStaffService = function() { 21853 if (false && $('.ss-commission-buttons .btnSave a.unsaved').length === 0) { 21854 _conCommission.saveStaffServiceConfirmed(); 21855 return; 21856 } 21857 21858 var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>' 21859 + '<div class="friendly-msg4" style="padding: 20px;">' 21860 + '<style> .ui-datepicker { z-index: 9999 !important; } </style>' 21861 + '<label for="Commission_Start_dt">Commission Start Date</label>' 21862 + '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>' 21863 + _getCurrentCommissionStart() 21864 + '</div> </div>'); 21865 21866 var jpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveStaffServiceConfirmed).getPopup().addClass('no-persist'); 21867
21868 var dtToday = new Date().toGloDate(); 21869 jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 }); 21870 jpop.find('#Commission_Start_dt').val(dtToday); 21871 21872 jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" }) 21873 jpop.find('#Commission_Start_dt').blur(); 21874 } 21875 21876 _conCommission.saveStaffServiceConfirmed = function() { 21877 var j = $('#commission-by-staff-service'); 21878 var sid = j.attr('staff_id'); 21879 var commission, dcommission = j.attr('default_commission_pct'); 21880 21881 var jpop = $('#pop-commission-start').closest('.glopop'); 21882 var start = UTIL.cleanString(jpop.find('#Commission_Start_dt').val()); 21883 21884 var tr = j.find('.tablesorter > tbody > tr'); 21885 var xml = '<table>'; 21886 21887 for (var i=0; i < tr.length; i++) { 21888 commission = tr.eq(i).find('.svc-commission input').val(); 21889 //if (dcommission == commission) { commission = '0'; } 21890 21891 xml += '<tr staff_service_id="' + tr.eq(i).attr('staff_service_id') + '" commission_pct="' + commission + '"/>'; 21892 } 21893 21894 xml = UTIL.htmlEncode(xml + '</table>'); 21895 21896 var uri = GLO.Link.WebsiteDomain + 'provider/manage/CommissionByStaffServiceUpdate?sfilter=' + sid; 21897 GLO.UI.Form.beginProcessing( j.find('.btnSave') ); 21898 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 21899 21900 $.ajax({ type: "POST", url: uri, "cache": false, data: { "input_xml": xml, "commission_start_dt": start } }) 21901 .success(function(data, textStatus, jqXHR) { 21902 new GLO.Popup.Success('Commission Saved'); 21903 21904 setTimeout(function() { 21905 document.location = GLO.Link.Page.Provider.Home + $('#commission-by-staff-service h2').attr('back_url_vc'); 21906 }); 21907 }) 21908 .error(function(jqXHR, textStatus, errorThrown) { 21909 GLO.Popup.Error('Unable to save. Please try again'); 21910 GLO.UI.Form.resetProcessing(); 21911 }); 21912 } 21913 21914 _conCommission.openReportHelp = function(stepNumber) { 21915 if (UTIL.coalesceInt(GLO.Info.roleType, 201) > 200) { 21916 SA.Help.openReportHelp('#help-commission', stepNumber, 'info/CommissionHelp'); 21917 } else { 21918 GLO.Popup.Warning.open('Please login as a receptionist, manager, or admin to access the Payroll Guide', 'Access Issue'); 21919 } 21920 } 21921 21922 return _conCommission; 21923})(); 21924 21925 21926GLO.Provider.Resource = (function() { 21927 function _conResourceAdmin() { } 21928 var _jsonResource, _jsonIndustry, _rgNameAutoSave = null; 21929 21930 _conResourceAdmin.init = function(jsonResource, jsonIndustry) { 21931 _jsonResource = jsonResource; 21932 _jsonIndustry = jsonIndustry; 21933 21934 var j = $('#manage-resource-group-container'); 21935 var tblSvc = j.find('#manage-resource-type-service'); 21936 var tblResource = j.find('#manage-resource-list'); 21937 21938 var jmsg = $('#resource-type-message'); 21939 GLO.Provider.Advanced.initClientOptions(jmsg); 21940 21941 if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 20) == 20) { 21942 $('#resource-type-message, #manage-resource-type-service').addClass('hideX'); 21943 } 21944 21945 _initUrl(); 21946 _initSortResourceGroup(); 21947 _displayAutoAssign(); 21948 $('#throbber-still-loading').remove(); 21949 } 21950 21951 function _initUrl() { 21952 var open = UTIL.coalesceString(UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(), 'help'); 21953 21954 if (!UTIL.isEmpty(open) && open != 'no') { 21955 //var highlight = UTIL.cleanString(GLO.Uri.hash('highlight')); 21956 var id = UTIL.cleanString(GLO.Uri.hash('id')).toLowerCase(); 21957 //var help = UTIL.cleanString(GLO.Uri.hash('help')).toLowerCase(); 21958 21959 if (open === 'add-resource' || open === 'addresource') { 21960 setTimeout(function() { 21961 $('#btnAddResource > a').click() 21962 }, 100); 21963 } else if (open === 'resource') { 21964 setTimeout(function() { 21965 $('#resource-group-list').find('tr[resource_group_id="' + id + '"]').click() 21966 }, 100); 21967 } else if (open === 'help') { 21968 setTimeout(function() { 21969 $('#manage-resource-add-button').find('.helpIcon2').click(); 21970 }, 100); 21971 } else if (open === 'help-per') { 21972 setTimeout(function() {
21973 GLO.Provider.Resource.openHelpResourcePer(); 21974 }, 100); 21975 } 21976 } 21977 } 21978 21979 function _initSortResourceGroup() { 21980 var rglist = $('#resource-group-list'); 21981 21982 rglist.find('tbody').sortable({ 21983 handle: '.drag-handle' 21984 , update: function(event, ui) { 21985 //toDo: save to DB 21986 _updateResourceGroupOrder(); 21987 } 21988 }); 21989 } 21990 21991 function _initSortResource() { 21992 var rlist = $('#manage-resource-list #resource-list') 21993 UI.initTableSorter(rlist, null, true); 21994 21995 rlist.find('tbody').sortable({ 21996 handle: '.drag-handle' 21997 , update: function(event, ui) { 21998 //var trs = $('#manage-resource-list #resource-list').find('tbody > tr'); 21999 //for (var i=0; i < trs.length; i++) { trs.eq(i).attr('order_sr', i+1); } 22000 22001 _updateResourceOrder(); 22002 } 22003 }); 22004 } 22005 22006 function _displayAutoAssign() { 22007 var jAutoAssign = $('#manage-resource-auto-assign'); 22008 var tdBookOnline = $('#manage-resource-container').find('.book_resource_online_fl, .resource-book-online'); 22009 22010 if ($('#manage-resource-per #Resource_Per_cd').val() == 10) { 22011 jAutoAssign.removeClass('hide'); 22012 22013 if (jAutoAssign.find('#Auto_Assign_Resource_fl').prop('checked')) { 22014 tdBookOnline.removeClass('hide'); 22015 } else { 22016 tdBookOnline.addClass('hide'); 22017 } 22018 } else { 22019 jAutoAssign.addClass('hide'); 22020 tdBookOnline.removeClass('hide'); 22021 } 22022 } 22023 function _updateResourceOrder() { 22024 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22025 var trs = $('#manage-resource-list #resource-list').find('tbody > tr'); 22026 var xml = '<ol>'; 22027 22028 for (var i=0; i < trs.length; i++) { 22029 trs.eq(i).attr('order_sr', i+1); 22030 xml += '<li resource_id="' + trs.eq(i).attr('resource_id') + '" order_sr="' + (i+1) + '"/>'; 22031 } 22032 22033 xml = UTIL.htmlEncode(xml + '</ol>'); 22034 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceOrder?rgid=' + rgid; 22035 22036 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } }); 22037 //.success(function(data, textStatus, jqXHR) { }) 22038 //.error(function(jqXHR, textStatus, errorThrown) { }); 22039 } 22040 22041 function _updateResourceGroupOrder() { 22042 var trs = $('#resource-group-list').find('tbody > tr'); 22043 var xml = '<ol>'; 22044 22045 for (var i=0; i < trs.length; i++) { 22046 trs.eq(i).attr('order_sr', i+1); 22047 xml += '<li resource_group_id="' + trs.eq(i).attr('resource_group_id') + '" order_sr="' + (i+1) + '"/>'; 22048 } 22049 22050 xml = UTIL.htmlEncode(xml + '</ol>'); 22051 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroupOrder'; 22052 22053 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } }) 22054 .success(function(data, textStatus, jqXHR) { 22055 //GLO.Popup.Success.open(htm, 'Order Updated'); 22056 }) 22057 .error(function(jqXHR, textStatus, errorThrown) { 22058 //GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 22059 //new GLO.Popup.Error('Unable to order the calendars staff'); 22060 }); 22061 } 22062 22063 _conResourceAdmin.changeAutoAssignResource = function(element) { 22064 _displayAutoAssign(); 22065 22066 var isAutoAssign = $('#manage-resource-auto-assign #Auto_Assign_Resource_fl').prop('checked'); 22067 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceAutoAssign?isauto=' + isAutoAssign; 22068 var msg = 'Auto-Assign Resource Setting '; 22069 22070 if (isAutoAssign) { 22071 msg += 'Enabled'; 22072 } else { 22073 msg += 'Disabled'; 22074 } 22075 22076 $.ajax({ type: "POST", url: uri, "cache": false }) 22077 .success(function(data, textStatus, jqXHR) { 22078 GLO.Popup.Success(msg); 22079 }) 22080 .error(function(jqXHR, textStatus, errorThrown) { 22081 GLO.Popup.Error('Unable to change auto-assign resource setting. Please try again later.'); 22082 GLO.UI.Form.resetProcessing(); 22083 }); 22084 }
22085 _conResourceAdmin.openHelpResourcePer = function(event, element) { 22086 GLO.Popup.closeIfExist($('#pop-setup-service-resource-help').closest('.glopop')); 22087 22088 var arrow = '<b class="arrow-right">➜</b>'; 22089 var perService = '<b class="narrow-text">Per Service</b>'; 22090 var perTicket = '<b class="narrow-text">Per Ticket</b>'; 22091 var aSchedule = '<a onclick="GLO.Uri.gotoUri(\'provider/ResourceView\', this, event, true)">Resource Calendar</a>'; 22092 22093 var msg = '<p style="margin-left: -20px; margin-top: 12px; font-weight: bold;">Can assign resource per service or per ticket, both populate your ' + aSchedule + '</p>'; 22094 22095 var listPerService = '<li>Need to assign different types of resources to different types of services <small>(like massage rooms for massages, pedicure chairs for pedicures, tanning beds for tanning)</small></li>' 22096 + '<li>Need to ensure that a resource does not get double booked (like if have more nail technicians than pedicure chairs)</li>' 22097 + '<li>Need to allow booking resource without a staff (like a tanning bed)</li>' 22098 + '<li>Want to assign resources for limited number of the services you offer</li>'; 22099 22100 var msgPerService = '<h3>Set Resource Per Service</h3>' 22101 + '<p>For services setup with a resource, online booking will only allow booking services if a resource is available</p>' 22102 + '<p>Can allow the client to book the resource or have the resource automatically assigned <span class="narrow-text">(without the client seeing it)</span></p>' 22103 + '<p style="margin-bottom: 0; padding-bottom: 2px;">Best option if</p>' + '<ul>' + listPerService + '</ul>'; 22104 22105 var listPerTicket = '<li>Your client receives all services at same location</li>' 22106 + '<li>Want to assign the resource at check-in</li>' 22107 + '<li>Want to display <i class="narrow-text">Chair, Station, or Room #</i> on ticket</li>'; 22108 22109 var msgPerTicket = '<h3>Set Resource Per Ticket</h3>' 22110 + '<p>' + perTicket + ' is easier to setup</p>' 22111 + '<p>Clients never book resource, staff assign resource on day of appointment <b class="narrow-text">(usually at check-in)</b></p>' 22112 + '<p style="margin-bottom: 0; padding-bottom: 2px;">Best option if</p>' + '<ul>' + listPerTicket + '</ul>'; 22113 22114 var htm = '<div id="pop-help-manage-resource-per">' + msg + msgPerService + msgPerTicket + '</div>'; 22115 var ojInfo = GLO.UI.openHelp(element, htm, 'Manage Resource Per Service or Per Ticket'); 22116 var jpop = ojInfo.getPopup().addClass('pop-info2'); 22117 } 22118 22119 _conResourceAdmin.openHelpResourceName = function(event, element) { 22120 var dragIcon = '<b class="drag-handle ui-sortable-handle" style="font-size: large;"></b>'; 22121 var msg1 = '<p>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></p>'; 22122 var msg2 = '<p>Press and hold the drag icon ' + dragIcon + ' to drag the resource higher or lower in the list of resources</p>'; 22123 22124 if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 10) == 10) { 22125 var arrow = '<b class="arrow-right">➜</b>'; 22126 var aProfileService = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, null, true)">Profile ' + arrow + ' Services</a>' 22127 var bStaffOnly = '<b class="narrow-text">Staff Only</b>', bBookOnline = '<b class="narrow-text">Book Online</b>'; 22128 22129 var msg3 = '<p><b>Staff Only:</b> <ul>' 22130 + '<li>Restrict resource to only staff booking <small>(client cannot book online)</small></li>' 22131 + '<li>If all resources are restricted to ' + bStaffOnly + ' then these services will display no results if a client tries to book online</li>' 22132 + '<li>So, only some resources should be marked ' + bStaffOnly + ' or go to ' + aProfileService + ' to block online booking for these services</li>' 22133 + '</ul></p>'; 22134 var msg4 = '<p><b>Book Online</b> <ul>' 22135 + '<li>Client will see resource listed as an option when booking online</li>' 22136 //+ '<li>Leave both ' + bStaffOnly + ' and ' + bBookOnline + ' un-checked to let ' + GLO.Info.getScheduleAnyoneHtm(
22136) + ' automatically assign resource at time of booking</li>' 22137 + '</ul></p>'; 22138 var msg5 = '<p style="margin-top: 24px;">To have ' + GLO.Info.getScheduleAnyoneHtm() + ' automatically assign resource without allowing client to pick resource leave both ' 22139 + bStaffOnly + ' and ' + bBookOnline + ' un-checked</p>'; 22140 } else { 22141 var msg3 = '', msg4 = '', msg5 = ''; 22142 } 22143 22144 var htm = '<div id="pop-setup-service-resource-name-help">' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>'; 22145 var ojInfo = GLO.UI.openHelp(element, htm, 'Manage Each Resource'); 22146 var jpop = ojInfo.getPopup().addClass('pop-info2'); 22147 } 22148 _conResourceAdmin.openHelpResourceGroup = function(event, element) { 22149 var msg1 = '<p>Select which services use these resources</p>'; 22150 var msg2 = '<p><b>No Staff:</b> Allow appointments with these services that have no staff (only a resource)</p>'; 22151 var msg3 = '<p><b>Book Online</b> Allow client to book this service online</p>'; 22152 var htm = '<div id="pop-setup-service-resource-name-help">' + msg1 + msg2 + msg3 + '</div>'; 22153 22154 var ojInfo = GLO.UI.openHelp(element, htm, 'Which Services Use These Resources?'); 22155 var jpop = ojInfo.getPopup().addClass('pop-info2'); 22156 } 22157 _conResourceAdmin.openHelp = function(event, element) { 22158 if (GLO.Data.provider.resource_per_cd == 20) { 22159 var resourceList = '<span class="resource-list">chair #1, chair #2, etc.., room A, room B, room C, etc..</span>'; 22160 var msg = '<p>Do you want to reserve or assign a resource like ' + resourceList + ' or something similar on appointments?</p>'; 22161 22162 msg += _getCustomHelpMessagePerTicket(); 22163 msg += _getMoreResourceInfo(); 22164 } else { 22165 var msg = _getCustomHelpMessage(); 22166 22167 msg += '<div style="margin-top: 20px;">When clients book online it will automatically verify a resource is available and then reserve the needed resource.</div>' 22168 22169 msg += '<div style="margin-top: 24px;">' 22170 + '<p>When you book an appointment you can specify which resource you want to use or it will automatically select an available resource</p>' 22171 + '<p>If you select a resource that is not available it will warn you that resource is already scheduled</p>' 22172 + '</div>'; 22173 } 22174 22175 msg = '<div id="pop-setup-service-resource-help">' + msg + '</div>'; 22176 22177 var ojInfo = GLO.UI.openHelp(element, msg, 'Setup Service Resources'); 22178 var jpop = ojInfo.getPopup().addClass('pop-info2').css({ "max-width": "900px" }); 22179 22180 //jpop.css({ "background-color": "#275264" }); 22181 //jpop.find('h2').css({ "color": "#4F81BD", "background-color": "#222", "border-radius": "8px", "padding": "9px", "margin-top": "-20px", "margin-bottom": "15px", "margin-left": "-25px" }); 22182 22183 //jpop.find('.msg p').remove(); 22184 //window.setTimeout(function() { ojInfo.realign(); }, 100); 22185 } 22186 22187 function _getHelpResource(isFullList, isResourceGroupNameExample, isResourceNameExample) { 22188 var nm = _jsonIndustry.resource_group_list_vc; 22189 var arr = nm.split(','); 22190 var otherCount = 0; 22191 22192 if (UTIL.isEmpty(nm)) { 22193 if (UTIL.parseBool(_jsonIndustry.resource_other_equipment_fl)) { 22194 nm = 'equipment'; 22195 ++otherCount; 22196 22197 if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) { 22198 nm += ', area'; 22199 ++otherCount; 22200 } 22201 } else if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) { 22202 nm = 'area'; 22203 ++otherCount; 22204 } 22205 } else { 22206 if (UTIL.parseBool(_jsonIndustry.resource_other_equipment_fl)) { nm += ', other equipment'; ++otherCount; } 22207 if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) { nm += ', other area'; ++otherCount; } 22208 } 22209 22210 if (isFullList) { 22211 if (nm.split(',').length > 1) { 22212 if (otherCount > 0) { 22213 var n = nm.lastIndexOf(','); 22214 22215 if (n !== -1) { 22216 nm = nm.substring(0, n) + ' or ' + nm.substring(n + 1); 22217 } 22218 } else { 22219 nm += ', etc'; 22220 } 22221 } 22222 22223 return nm; 22224 } else { 22225 if (isResourceGroupNameExample) { 22226 if (UTIL.isEmpty(arr[0])) { 22227 return ''; 22228 } else { 22229 return ' <span style="text-transform: none; font-size: 100%; font-weight: normal;
22229 color: #333;">such as</span> ' + arr[0] + 's'; 22230 } 22231 } else if (UTIL.isEmpty(arr[0])) { 22232 arr[0] = 'resource'; //arr = UTIL.coalesce(nm, 'resource').split(','); 22233 } 22234 22235 if (isResourceNameExample) { 22236 return arr[0] + ' #1, ' + arr[0] + ' #2, etc'; 22237 } else { 22238 return arr[0]; 22239 } 22240 } 22241 } 22242 22243 function _getCustomHelpMessagePerTicket() { 22244 var msg = '<h3 style="text-align: center;">To Setup Resources below</h3> <ol>'; 22245 var btnAddResourceType = '<span class="btnAdd" onclick="GLO.Provider.Resource.openAddResourceGroup(true)" style="display: inline;"><a style="display: inline-block;">Add Resource Type</a></span>'; 22246 var resourceTypeRows = $('#resource-group-list tbody > tr'); 22247 var msg1 = 'Press the button ' + btnAddResourceType + ' and create a resource type such as<span class="resource-name">' + _getHelpResource(false, true, false) + '</span>'; 22248 22249 if (resourceTypeRows.length > 0) { 22250 var existingResourceList = resourceTypeRows.eq(0).find('.resource-group-name').text(); 22251 22252 for (var i=1; i < resourceTypeRows.length; i++) { 22253 existingResourceList += ', ' + resourceTypeRows.eq(i).find('.resource-group-name').text(); 22254 } 22255 22256 msg1 += ' or select existing <i>Resource Type</i> below like <b class="narrow-text">' + existingResourceList + '</b>'; 22257 } 22258 22259 msg += '<li style="padding: 8px 0;">' + msg1 + '</li>'; //[ Pedicure Chairs ] 22260 msg += '<li>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></li>'; //[ Pedicure Chair #1, Pedicure Chair #2, etc ] 22261 22262 msg += '</ol>'; 22263 return '<div>' + msg + '</div>'; 22264 } 22265 function _getMoreResourceInfo() { 22266 var header = '<h3 style="text-align: center;">Quick Overview</h3>'; 22267 var aResourcePerHelp = '<a onclick="GLO.Provider.Resource.openHelpResourcePer()">decide best option for you</a>'; 22268 22269 var msg1 = '<p>Can reserve resource at time of booking <i class="narrow-text">(then setup to be per service)</i> ' 22270 + 'or assign resource at time of check-in <i class="narrow-text">(then setup to be per ticket)</i> ' 22271 + '<b class="arrow-right">➜</b> ' + aResourcePerHelp + '</p>'; 22272 22273 var msg2 = '<p>Staff can double book a resource, but a warning message will appear encouraging them to assign a different resource</p>'; 22274 22275 var aResourceCal = '<a onclick="GLO.Uri.gotoUri(\'provider/ResourceView\', this, event, true)">Resource Calendar</a>'; 22276 var msg3 = '<p>Easily view resource schedule on the ' + aResourceCal + '</p>'; 22277 22278 return '<div>' + header + msg1 + msg2 + msg3 + '</div>'; 22279 } 22280 function _getCustomHelpMessage() { 22281 var msg = 'Do you need to reserve a <span class="resource-list">' + _getHelpResource(true) + '</span>'; //[ Message room, Waxing room, Cryo chamber, Pedicure chair, etc ] 22282 22283 msg += ' with some services?<br/><br/>'; 22284 msg += 'To Setup: <ol>'; 22285 22286 msg += '<li>Create a resource type<span class="resource-name">' + _getHelpResource(false, true, false) + '</span></li>'; //[ Pedicure Chairs ] 22287 msg += '<li>Select which services use the resource type</span></li>'; 22288 msg += '<li>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></li>'; //[ Pedicure Chair #1, Pedicure Chair #2, etc ] 22289 22290 msg += '</ol>'; 22291 return '<div>' + msg + '</div>'; 22292 } 22293 22294 _conResourceAdmin.openResourceGroup = function(row) { 22295 if ($(row).hasClass('selected')) { 22296 _conResourceAdmin.closeResourceGroup(row); 22297 return; 22298 } 22299 22300 $('#resource-group-list').find('tr').removeClass('selected').addClass('hide'); 22301 row = $(row).addClass('selected').removeClass('hide'); 22302 var rgid = row.attr('resource_group_id'); 22303 var rgname = row.find('.resource-group-name').text(); 22304 22305 var j = $('#manage-resource-container'); 22306 $('#manage-resource-group-container2').addClass('hide').find('.click-to-edit').addClass('hide'); 22307 $('#manage-resource-group-container').addClass('editing-specific-resource-group'); 22308 //j.find('#resource-group-list').addClass('hide'); 22309 22310 var jrg = j.find('#Resource_Group_Name_vc').val(rgname); 22311 var rg = _getJsonObj(rgid); 22312 22313 _populateServices(j, rg); 22314 _populateResources(j, rg); 22315 _initSortResource(); 22316 _displayAutoAssign(); 22317 22318 j.removeClass('hide'); 22319 22320 var saveUrl = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroup?resource_group_id=' + rgid; 22321 _rgNameAutoSave = new UI.AutoSave(jrg, saveUrl, GLO.Provider.Resource.updateResourceGroupComplete); 22322 22323 $('#manage-resource-group-title').addClass('display-back'); 22324 _initSendMessage(rg); 22325 } 22326 22327 function _initSendMessage(rg) { 22328 if ($('#manage-resource-type-service').find('tr.resource-service .no_staff_fl').find('input
22328:checked').length > 0) { 22329 var jmsg = $('#resource-type-message').removeClass('hide'); 22330 } else { 22331 var jmsg = $('#resource-type-message').addClass('hide'); 22332 } 22333 22334 jmsg.off('change', 'input:visible', GLO.Provider.Resource.saveClientMessages); 22335 var emailDays = UTIL.coalesceInt(rg.email_reminder_Hr_sr/24, 0); 22336 22337 if (emailDays === 0) { emailDays = ''; } 22338 22339 jmsg.find('#Send_Confirmation_Email_fl').prop('checked', UTIL.parseBool(rg.send_confirmation_email_fl)).change(); 22340 jmsg.find('#Confirm_On_Update_fl').prop('checked', !UTIL.parseBool(rg.no_confirm_on_update_fl)).change(); 22341 jmsg.find('#Email_Reminder_Day_sr').val(emailDays).change(); 22342 jmsg.find('#Text_Reminder_Hr_sr').val(rg.text_reminder_Hr_sr).change(); 22343 22344 jmsg.on('change', 'input:visible', GLO.Provider.Resource.saveClientMessages); 22345 } 22346 22347 _conResourceAdmin.savePer = function() { 22348 var jper = $('#manage-resource-per-container #Resource_Per_cd'); 22349 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourcePer?per=' + jper.val(); 22350 var msg1 = '<p>Manage Resources changed to per <b>' + jper.find('option:selected').text() + '</b></p>'; 22351 22352 $.ajax({ type: "POST", url: uri, "cache": false }) 22353 .success(function(data, textStatus, jqXHR) { 22354 var msg2 = '<p>Loading Change...</p>'; 22355 var htm = '<div id="pop-success-resource-per">' + msg1 + msg2 + '</div>'; 22356 22357 GLO.Popup.Processing.open(htm, 'Manage Resource Setting Saved'); 22358 22359 setTimeout(function() { 22360 location.reload(); 22361 }, 250) 22362 }); 22363 } 22364 22365 _conResourceAdmin.saveClientMessages = function() { 22366 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22367 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceClientMessage?rgid=' + rgid; 22368 22369 var jmsg = $('#resource-type-message'); 22370 var emailHour = '', emailDay = jmsg.find('#Email_Reminder_Day_sr').val(); 22371 var textHour = jmsg.find('#Text_Reminder_Hr_sr').val(); 22372 var isSendOnCreate = jmsg.find('#Send_Confirmation_Email_fl').prop('checked'); 22373 var isSendOnUpdate = jmsg.find('#Confirm_On_Update_fl').prop('checked'); 22374 22375 if (emailDay > 0) { 22376 emailHour = emailDay * 24; 22377 } 22378 22379 var json = { "texthour": textHour, "emailhour": emailHour, "confirmcreate": isSendOnCreate, "confirmupdate": isSendOnUpdate }; 22380 22381 $.ajax({ type: "POST", url: uri, "cache": false, data: json }) 22382 .success(function(data, textStatus, jqXHR) { 22383 var rg = _getJsonObj(rgid); 22384 22385 if (rg) { 22386 rg.text_reminder_Hr_sr = textHour; 22387 rg.email_reminder_Hr_sr = emailHour; 22388 rg.send_confirmation_email_fl = isSendOnCreate; 22389 rg.no_confirm_on_update_fl = !isSendOnUpdate; 22390 } 22391 }); 22392 } 22393 22394 _conResourceAdmin.saveResourceBookOnline = function(checkbox) { 22395 var jcheckbox = $(checkbox); 22396 var isChecked = jcheckbox.prop('checked'); 22397 var tr = jcheckbox.closest('tr'); 22398 var rid = tr.attr('resource_id'); 22399 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22400 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceBookOnline?rgid=' + rgid + '&rid=' + rid + '&bookonline=' + isChecked; 22401 var resource = _getJsonObjResource(rgid, rid); 22402 22403 resource.book_online_fl = isChecked; 22404 22405 if (isChecked) { 22406 resource.no_client_booking_fl = 0; 22407 tr.find('td.resource-restrict-client-booking input[type="checkbox"]').prop('checked', false); 22408 } 22409 22410 $.ajax({ type: "POST", url: uri, "cache": false }); 22411 //.success(function(data, textStatus, jqXHR) { }); 22412 } 22413 _conResourceAdmin.saveResourceNoClientBooking = function(checkbox) { 22414 var jcheckbox = $(checkbox); 22415 var isChecked = jcheckbox.prop('checked'); 22416 var tr = jcheckbox.closest('tr');
22417 var rid = tr.attr('resource_id'); 22418 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22419 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceNoClientBooking?rgid=' + rgid + '&rid=' + rid + '&nobooking=' + isChecked; 22420 var resource = _getJsonObjResource(rgid, rid) 22421 22422 resource.no_client_booking_fl = isChecked; 22423 22424 if (isChecked) { 22425 resource.book_online_fl = 0; 22426 tr.find('td.resource-book-online input[type="checkbox"]').prop('checked', false); 22427 } 22428 22429 $.ajax({ type: "POST", url: uri, "cache": false }); 22430 //.success(function(data, textStatus, jqXHR) { }); 22431 } 22432 22433 function _getJsonObjResource(rgid, rid) { 22434 var rg = _getJsonObj(rgid); 22435 22436 for (var i=0; i < rg.resources.length; i++) { 22437 if (rid == rg.resources[i].resource_id) { 22438 return rg.resources[i]; 22439 } 22440 } 22441 22442 return null; 22443 } 22444 function _getJsonObj(rgid) { 22445 for (var i=0; i < _jsonResource.length; i++) { 22446 if (_jsonResource[i].resource_group_id == rgid) { 22447 return _jsonResource[i]; 22448 } 22449 } 22450 22451 return {}; 22452 } 22453 22454 function _populateResources(jcontainer, rg) { 22455 var tbl = jcontainer.find('#manage-resource-list').find('table > tbody').addClass('hide'); 22456 tbl.find('tr').remove(); 22457 22458 if (rg.resources.length > 0) { 22459 for (var r=0; r < rg.resources.length; r++) { 22460 var tr = _getResourceHtm(rg.resources[r], r + 1); 22461 tbl.append(tr); 22462 } 22463 22464 tbl.removeClass('hide'); 22465 } 22466 } 22467 22468 function _getResourceHtm(jsonResource, rowNumber) { 22469 var rid = jsonResource.resource_id; 22470 var name = jsonResource.resource_name_vc; 22471 var isRestrict = '', isBookOnlineChecked = ''; 22472 22473 if (UTIL.parseBool(jsonResource.no_client_booking_fl)) { isRestrict = ' checked="checked"'; } 22474 if (UTIL.parseBool(jsonResource.book_online_fl)) { isBookOnlineChecked = ' checked="checked"'; } 22475 22476 if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 10) == 20) { 22477 var tdStaffOnly = '', tdBookOnline = ''; 22478 } else { 22479 var chkidRestrict = 'resource-restrict-client' + rowNumber; 22480 var chkRestrict = '<input id="' + chkidRestrict + '" type="checkbox" onchange="GLO.Provider.Resource.saveResourceNoClientBooking(this)"' + isRestrict + '>'; 22481 var lblRestrict = '<label for="' + chkidRestrict + '">Staff Only</label>'; 22482 22483 var chkidOnline = 'resource-book-online' + rowNumber; 22484 var chkOnline = '<input id="' + chkidOnline + '" type="checkbox" onchange="GLO.Provider.Resource.saveResourceBookOnline(this)"' + isBookOnlineChecked + '>'; 22485 var lblOnline = '<label for="' + chkidOnline + '">Book Online</label>'; 22486 22487 var tdStaffOnly = '<td class="resource-restrict-client-booking">' + chkRestrict + lblRestrict + '</td>' 22488 var tdBookOnline = '<td class="resource-book-online">' + chkOnline + lblOnline + '</td>' 22489 } 22490 22491 var removeIcon = '<td class="remove-icon"> <span title="Remove this resource" onclick="GLO.Provider.Resource.removeResource(this)" class="ui-icon ui-icon-circle-close"></span> </td>'; 22492 var tr = '<tr resource_id="' + rid + '">' 22493 + removeIcon 22494 + '<td class="resource" onclick="GLO.Provider.Resource.openUpdateResource(this)">' + name + '</td>' 22495 + '<td class="resource-drag"><b class="drag-handle"></b></td>' 22496 + tdStaffOnly + tdBookOnline 22497 + '</tr>'; 22498 return tr; 22499 } 22500 22501 function _populateServices(jcontainer, rg) { 22502 var jSvcGroupDD = $($('#ServiceGroupOptionsClone').outerHTML()); 22503 var tbl = jcontainer.find('#manage-resource-type-service').find('table > tbody').addClass('hide'); 22504 var jall = $('#allServiceOptions'); 22505 22506 jSvcGroupDD.find('option[default_service_group_id="9"]').remove(); 22507 jSvcGroupDD.find('option[default_service_group_id="1009"]').remove(); 22508 tbl.find('tr').remove(); 22509 22510 if (rg.servicegroups.length > 0) { 22511 for (var sg=0; sg < rg.servicegroups.length; sg++) { 22512 var sgid = rg.servicegroups[sg].service_group_id; 22513 var sgname = rg.servicegroups[sg].service_group_name_vc; 22514 var sgcolor = UTIL.cleanString(rg.servicegroups[sg].css_color_vc); 22515 var srows = rg.servicegroups[sg].services; 22516 22517 var jdd = jall.find('select#crSvc' + sgid); 22518 22519 if (srows.length > 0) { 22520 for (var s=0; s < srows.length; s++) { 22521 var jsvc = jdd.find('option[value="' + srows[s].service_id + '"]'); 22522 var noStaffRequired = UTIL.parseBool(jsvc.attr('no_staff_fl')); 22523 var canBookResourceOnline = UTIL.parseBool(jsvc.attr('book_resource_online_fl')); 22524 22525 _addServiceRowToTable(tbl, sgid, sgname, sgcolor, srows[s].service_id, srows[s].service_name_vc, noStaffRequired, canBookResourceOnline); 22526 } 22527 } else { 22528 //service is required so no longer use -> _addServiceRowToTable(tbl, sgid, sgname, sgcolor, '', ''); 22529 } 22530 } 22531 22532 tbl.removeClass('hide'); 22533 //jSvcGroupDD.find('option[value="' + sgid + '"]').remove(); 22534 } 22535 22536 jcontainer.find('#Service_Group_id').html(jSvcGroupDD.html()); 22537 } 22538 22539 function _addServiceRowToTable(tbl, sgid, sgname, sgcolor, svcid, svcname, noStaffRequired, canBookResourceOnline) { 22540 var removeIcon = '<td class="remove-icon"> <span title="Remove this service" onclick="GLO.Provider.Resource.removeService(this)" class="ui-icon ui-icon-circle-close"></span> </td>'; 22541 var noStaffChecked = '', allowOnlineChecked = ''; 22542 var rowNumber = tbl.find('tr').length + 1; 22543 22544 if (noStaffRequired) { noStaffChecked = ' checked="checked"'; } 22545 if (canBookResourceOnline) { allowOnlineChecked = ' checked="checked"'; } 22546 22547 var idNoStaff = 'no_staff_fl' + rowNumber; 22548 var chkNoStaff = '<input type="checkbox" id="' + idNoStaff + '"' + noStaffChecked + ' onchange="GLO.Provider.Resource.changeNoStaff(this, event)"/>'; 22549 var lblNoStaff = '<label for="' + idNoStaff + '" title="This Service has no staff (only a resource)">' + chkNoStaff + 'No Staff</label>'; 22550 22551 var idBookOnline = 'book_resource_online_fl' + rowNumber; 22552 var chkBookOnline = '<input type="checkbox" id="' + idBookOnline + '"' + allowOnlineChecked + ' onchange="GLO.Provider.Resource.changeBookOnline(this, event)"/>'; 22553 var lblBookOnline = '<label for="' + idBookOnline + '" title="Allow Clients to pick which resource when booking online">' + chkBookOnline + 'Book Online</label>' 22554 22555 var tr = '<tr class="resource-service" service_group_id="' + sgid + '" service_id="' + svcid + '">' 22556 + removeIcon 22557 + '<td class="service-group" style="color: ' + sgcolor + ';">' + sgname + '</td>' 22558 + '<td class="service">' + svcname + '</td>' 22559 + '<td class="no_staff_fl">' + lblNoStaff + '</td>' 22560 + '<td class="book_resource_online_fl">' + lblBookOnline + '</td>' 22561 + '</tr>'; 22562 22563 tbl.append(tr); 22564 } 22565 22566 _conResourceAdmin.closeResourceGroup = function() { 22567 var j = $('#manage-resource-container').addClass('hide'); 22568 22569 $('#manage-resource-add-button').find('.btnAdd').hide().fadeIn(2400); 22570 $('#manage-resource-group-container2').removeClass('hide').find('.click-to-edit').removeClass('hide'); 22571 $('#resource-group-list').find('tr').removeClass('selected').removeClass('hide'); 22572 22573 _rgNameAutoSave.off(); 22574 $('#manage-resource-group-title').removeClass('display-back'); 22575 $('#manage-resource-group-container').removeClass('editing-specific-resource-group'); 22576 } 22577 22578 _conResourceAdmin.openAddResourceGroup = function() { 22579 var msg = $('<div id="pop-resource-group-add"> <h1 class="friendly-msg2">' + SA.Resource.AddResourceType + '</h1>' 22580 + '<div class="friendly-msg2"> <input type="text" id="Resource_Group_Name_vc" placeholder="' + SA.Resource.ResourceType + '"/> </div> </div>'); 22581
22582 _openSimplePopup(msg, GLO.Provider.Resource.addResourceGroup); 22583 } 22584 22585 function _updateServiceAttribute(sgid, svcid, attributeName, attributeValue) { 22586 var jsvc = $('#allServiceOptions').find('select#crSvc' + sgid).find('option[value="' + svcid + '"]'); 22587 jsvc.attr(attributeName, attributeValue); 22588 } 22589 22590 _conResourceAdmin.changeNoStaff = function(element, event) { 22591 var tr = $(element).closest('tr.resource-service'); 22592 var value = 0, sgid = tr.attr('service_group_id'), svcid = tr.attr('service_id'); 22593 22594 if (element.checked) { value = 1; } 22595 22596 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceService?sgid=' + sgid + '&svcid=' + svcid + '&nostaff=' + value; 22597 22598 $.ajax({ type: "POST", url: uri, "cache": false }) 22599 .success(function(data, textStatus, jqXHR) { 22600 _updateServiceAttribute(sgid, svcid, 'no_staff_fl', value); 22601 }); 22602 //.error(function(jqXHR, textStatus, errorThrown) { }); 22603 } 22604 _conResourceAdmin.changeBookOnline = function(element, event) { 22605 var tr = $(element).closest('tr.resource-service'); 22606 var value = 0, sgid = tr.attr('service_group_id'), svcid = tr.attr('service_id'); 22607 22608 if (element.checked) { value = 1; } 22609 22610 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceService?sgid=' + sgid + '&svcid=' + svcid + '&bookonline=' + value; 22611 22612 $.ajax({ type: "POST", url: uri, "cache": false }) 22613 .success(function(data, textStatus, jqXHR) { 22614 _updateServiceAttribute(sgid, svcid, 'book_resource_online_fl', value); 22615 }); 22616 //.error(function(jqXHR, textStatus, errorThrown) { }); 22617 } 22618 22619 _conResourceAdmin.addResourceGroup = function() { 22620 var jpop = $('#pop-resource-group-add').closest('.glopop'); 22621 var name = UTIL.coalesce(jpop.find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1)); 22622 22623 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddResourceGroup?name_vc=' + encodeURIComponent(name); 22624 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 22625 22626 $.ajax({ type: "POST", url: uri, "cache": false }) 22627 .success(function(data, textStatus, jqXHR) { 22628 GLO.Popup.close(jpop); 22629 var rgid = $(data).attr('resource_group_id'); 22630 22631 _jsonResource.push({ "resource_group_id": rgid, "resource_group_name_vc": name, "resources": [], "servicegroups": [] }); 22632 22633 var tr = '<tr resource_group_id="' + rgid + '" onclick="GLO.Provider.Resource.openResourceGroup(this)">' 22634 + '<td class="resource-group-drag-handle"> <b class="drag-handle"></b> </td>' 22635 + '<td class="resource-group-name">' + name + '</td>' 22636 + '<td class="service-list"></td>' 22637 + '</tr>'; 22638 22639 var j = $('#resource-group-list'); 22640 j.find('.no-result-row').remove(); 22641 var tbody = j.find('tbody').append(tr) 22642 22643 tbody.find('tr[resource_group_id="' + rgid + '"]').click(); 22644 }) 22645 .error(function(jqXHR, textStatus, errorThrown) { 22646 GLO.Popup.Error('Unable to add this resource type. Please try again.'); 22647 GLO.UI.Form.resetProcessing(); 22648 }); 22649 } 22650 22651 _conResourceAdmin.updateResourceGroup = function() { 22652 var name = UTIL.coalesce($('#manage-resource-container').find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1)); 22653 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22654 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroup?resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name); 22655 22656 $.ajax({ type: "POST", url: uri, "cache": false }) 22657 .success(function(data, textStatus, jqXHR) { 22658 _conResourceAdmin.updateResourceGroupComplete(); 22659 }) 22660 .error(function(jqXHR, textStatus, errorThrown) { 22661 GLO.Popup.Error('Unable to add this resource type. Please try again.'); 22662 GLO.UI.Form.resetProcessing(); 22663 }); 22664 } 22665 22666 _conResourceAdmin.updateResourceGroupComplete = function() { 22667 var tr = $('#resource-group-list').find('tr.selected'); 22668 var rgid = tr.attr('resource_group_id'); 22669 var name = UTIL.coalesce($('#manage-resource-container').find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1)); 22670 22671 tr.find('.resource-group-name').text(name); 22672 _getJsonObj(rgid).resource_group_name_vc = name; 22673 } 22674 22675 _conResourceAdmin.removeResourceGroup = function() { 22676 var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;'; 22677 new GLO.Popup.Confirm('<div style="' + css + '">Delete this Group of Resources?</div>', GLO.Provider.Resource.removeResourceGroupConfirmed); 22678 } 22679 22680 _conResourceAdmin.removeResourceGroupConfirmed = function() { 22681 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22682 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/DeleteResourceGroup?resource_group_id=' + rgid; 22683 22684 new GLO.Popup.Processing('Deleting Resource Type and associated Resources...'); 22685
22686 $.ajax({ type: "POST", url: uri, "cache": false }) 22687 .success(function(data, textStatus, jqXHR) { 22688 document.location = document.location.origin + document.location.pathname + document.location.search; 22689 }) 22690 .error(function(jqXHR, textStatus, errorThrown) { 22691 GLO.Popup.Error('Unable to delete this resource type. Please try again.'); 22692 GLO.UI.Form.resetProcessing(); 22693 }); 22694 } 22695 22696 _conResourceAdmin.openUpdateResource = function(td) { 22697 td = $(td); 22698 var rid = td.closest('tr').attr('resource_id'); 22699 var name = td.text(); 22700 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22701 22702 var msg = $('<div id="pop-resource-update" resource_group_id="' + rgid + '" resource_id="' + rid + '">' 22703 + '<h1 class="friendly-msg2">' + SA.Resource.UpdateResource + '</h1>' 22704 + '<div class="friendly-msg2"> <input type="text" id="Resource_Name_vc" value="' + name + '" placeholder="' + SA.Resource.UpdateResource + '"/> </div>' 22705 + '</div>'); 22706 22707 _openSimplePopup(msg, GLO.Provider.Resource.updateResource); 22708 } 22709 22710 function _openSimplePopup(msg, saveFn) { 22711 var oj = new GLO.Popup.Custom(msg, saveFn); 22712 22713 var jpop = oj.getPopup().addClass('no-persist'); 22714 var jbtn = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "letter-spacing": "1px" }); 22715 jbtn.find('.btnNo').removeClass('btnNo').addClass('btnCancel').find('a').text('Cancel'); 22716 jbtn.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('a').text('Save'); 22717 } 22718 22719 _conResourceAdmin.addResource = function(td) { 22720 var j = $('#manage-resource-list'); 22721 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22722 var name = j.find('#Resource_Name_vc').val(); 22723 22724 if (UTIL.isEmpty(name)) { 22725 new GLO.Popup.Warning('Please Enter Resource Name', function() { $('#manage-resource-list').find('#Resource_Name_vc').focus(); }); 22726 return; 22727 } 22728 22729 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddResource?resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name); 22730 GLO.UI.Form.beginProcessing( j.find('.btnAdd') ); 22731 22732 $.ajax({ type: "POST", url: uri, "cache": false }) 22733 .success(function(data, textStatus, jqXHR) { 22734 var tbody = $('#resource-list').find('tbody').removeClass('hide'); 22735 var trs = tbody.find('tr'); 22736 var trlast = trs.eq(trs.length - 1); 22737 22738 rid = parseInt($(data).attr('resource_id')); 22739 var isNoClientBook = trlast.find('.resource-restrict-client-booking input').prop('checked'); 22740 var isBookOnline = trlast.find('.resource-book-online input').prop('checked'); 22741 22742 var jsonResource = { "resource_id": rid, "resource_name_vc": name, "no_client_booking_fl": isNoClientBook, "book_online_fl": isBookOnline }; 22743 var rg = _getJsonObj(rgid); 22744 rg.resources.push(jsonResource); 22745 22746 var tr = _getResourceHtm(jsonResource, trs.length + 1); 22747 tbody.append(tr); 22748 22749 j.find('#Resource_Name_vc').val(''); 22750 GLO.UI.Form.resetProcessing(); 22751 }) 22752 .error(function(jqXHR, textStatus, errorThrown) { 22753 GLO.Popup.Error('Unable to add this resource type. Please try again.'); 22754 GLO.UI.Form.resetProcessing(); 22755 }); 22756 } 22757 22758 _conResourceAdmin.updateResource = function() { 22759 var jpop = $('#pop-resource-update').addClass('no-persist'); 22760 var rgid = jpop.attr('resource_group_id'); 22761 var rid = jpop.attr('resource_id'); 22762 var name = jpop.find('#Resource_Name_vc').val(); 22763 22764 if (UTIL.isEmpty(name)) { 22765 new GLO.Popup.Warning('Please Enter Resource Name', function() { $('#pop-resource-update').find('#Resource_Name_vc').focus(); }); 22766 return; 22767 } 22768 22769 jpop = jpop.closest('.glopop'); 22770 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResource?resource_id=' + rid + '&resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name); 22771 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 22772
22773 $.ajax({ type: "POST", url: uri, "cache": false }) 22774 .success(function(data, textStatus, jqXHR) { 22775 GLO.Popup.close(jpop); 22776 var rg = _getJsonObj(rgid); 22777 22778 for (var i=0; i < rg.resources.length; i++) { 22779 if (rid == rg.resources[i].resource_id) { 22780 rg.resources[i].resource_name_vc = name; 22781 } 22782 } 22783 22784 var tr = $('#resource-list').find('tr'); 22785 22786 for (var i=0; i < tr.length; i++) { 22787 if (rid == tr.eq(i).attr('resource_id')) { 22788 tr.eq(i).find('td.resource').text(name); 22789 } 22790 } 22791 }) 22792 .error(function(jqXHR, textStatus, errorThrown) { 22793 GLO.Popup.Error('Unable to add this resource type. Please try again.'); 22794 GLO.UI.Form.resetProcessing(); 22795 }); 22796 } 22797 22798 _conResourceAdmin.removeService = function(element) { 22799 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22800 var tr = $(element).closest('tr'); 22801 var sgid = tr.attr('service_group_id'); 22802 var svcid = tr.attr('service_id'); 22803 var name = tr.find('td.service').text(); 22804 22805 var fn = function() { 22806 GLO.Provider.Resource.removeServiceConfirmed(tr, rgid, sgid, svcid); 22807 }; 22808 22809 var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;'; 22810 new GLO.Popup.Confirm('<div style="' + css + '">Delete ' + name + '?</div>', fn); 22811 } 22812 22813 _conResourceAdmin.removeServiceConfirmed = function(tr, rgid, sgid, svcid) { 22814 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/RemoveService?resource_group_id=' + rgid + '&service_group_id=' + sgid + '&service_id=' + svcid; 22815 var oj = new GLO.Popup.Processing('<div style="letter-spacing: 1px; line-height: 200%; letter-spacing: 1px;">Deleting Service</div>'); 22816 var jservices = $('#manage-resource-type-service').find('tr.resource-service[service_group_id="' + sgid + '"]'); 22817 22818 $.ajax({ type: "POST", url: uri, "cache": false }) 22819 .success(function(data, textStatus, jqXHR) { 22820 oj.close(); 22821 var rg = _getJsonObj(rgid); 22822 22823 for (var sg=0; sg < rg.servicegroups.length; sg++) { 22824 if (rg.servicegroups[sg].service_group_id == sgid) { 22825 var svc = rg.servicegroups[sg].services; 22826 22827 for (var s=0; s < svc.length; s++) { 22828 if (svc[s].service_id == svcid) { 22829 svc.splice(s, 1); 22830 break; 22831 } 22832 } 22833 22834 break; 22835 } 22836 } 22837 22838 tr.remove(); 22839 22840 if (jservices.length === 1) { 22841 _conResourceAdmin.removeServiceGroupFromList(rgid, sgid); 22842 } 22843 }) 22844 .error(function(jqXHR, textStatus, errorThrown) { 22845 oj.close(); 22846 GLO.Popup.Error('Unable to delete this service. Please try again.'); 22847 GLO.UI.Form.resetProcessing(); 22848 }); 22849 } 22850 22851 _conResourceAdmin.removeServiceGroupFromList = function(rgid, sgid) { 22852 $('#resource-group-list').find('tr[resource_group_id="' + rgid + '"]').find('td.service-list').find('span[sgid="' + sgid + '"]').remove(); 22853 } 22854 _conResourceAdmin.addServiceGroupToList = function(rgid, sgid, sgname, sgcolor) { 22855 $('#resource-group-list').find('tr[resource_group_id="' + rgid + '"]').find('td.service-list').append(', <span sgid="' + sgid + '" style="color: ' + sgcolor + ';">' + sgname + '</span>'); 22856 } 22857 22858 _conResourceAdmin.addServiceGroup = function(dd) { 22859 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22860 var sgid = dd.value; 22861 var sgname = dd.options[dd.selectedIndex].text; 22862 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddServiceGroup?resource_group_id=' + rgid + '&service_group_id=' + sgid; 22863 22864 if (UTIL.coalesceInt(sgid, 0) === 0) { return; } 22865 22866 var htm = '<div style="letter-spacing: 2px; font-size: larger;">Adding Services to Resource...</div>'; 22867 var ojProcessing = new GLO.Popup.Processing(htm); 22868
22869 $.ajax({ type: "POST", url: uri, "cache": false }) 22870 .success(function(data, textStatus, jqXHR) { 22871 var options = $('#allServiceOptions #crSvc' + sgid).find('option'); 22872 var rg = _getJsonObj(rgid); 22873 var j = $('#manage-resource-type-service'); 22874 22875 var ddSG = j.find('#Service_Group_id'); 22876 ddSG.find('option[value="' + sgid + '"]').remove(); 22877 22878 var tbl = j.find('tbody').removeClass('hide'); 22879 var removeIcon = '<td class="remove-icon"> <span title="Remove service" onclick="GLO.Provider.Resource.removeService(this)" class="ui-icon ui-icon-circle-close"></span> </td>'; 22880 var arrSvc = [], servicesAdded = 0; 22881 22882 for (var i=0; i < options.length; i++) { 22883 if (UTIL.isEmpty(options.eq(i).attr('resource_group_id'))) { 22884 var svcid = options.eq(i).attr('value'); 22885 var svcname = options.eq(i).text(); 22886 var noStaffRequired = UTIL.parseBool(options.eq(i).attr('no_staff_fl')); 22887 var canBookResourceOnline = UTIL.parseBool(options.eq(i).attr('book_resource_online_fl')); 22888 var sgcolor = $(data).attr('rgb_color'); 22889 22890 arrSvc.push({ "service_id": svcid, "service_name_vc": svcname }); 22891 _addServiceRowToTable(tbl, sgid, sgname, sgcolor, svcid, svcname, noStaffRequired, canBookResourceOnline); 22892 ++servicesAdded; 22893 } 22894 } 22895 22896 if (servicesAdded > 0) { 22897 rg.servicegroups.push({ "service_group_id": sgid, "service_group_name_vc": sgname, "css_class_vc": "", "css_color_vc": "", "services": arrSvc }); 22898 _conResourceAdmin.addServiceGroupToList(rgid, sgid, sgname, sgcolor); 22899 } else { 22900 var msg1 = '<p>All ' + sgname + ' Services already attached to a Resource</p>'; 22901 var msg2 = '<p style="letter-spacing: 0; font-size: smaller;">To attach these services to a different resource first remove from current resource</p>'; 22902 var htm = '<div id="pop-warn-no-service">' + msg1 + msg2 + '</div>'; 22903 GLO.Popup.Warning.open(htm, 'Services Already Attached to Resource'); 22904 } 22905 22906 $('#manage-resource-container #Resource_Group_Name_vc').focus(); //= move focus away from SG drop down so don't accidentally select another service group. 22907 ojProcessing.close(); //GLO.UI.Form.resetProcessing(); 22908 }) 22909 .error(function(jqXHR, textStatus, errorThrown) { 22910 GLO.Popup.Error('Unable to add this resource type. Please try again.'); 22911 GLO.UI.Form.resetProcessing(); 22912 }); 22913 } 22914 22915 _conResourceAdmin.removeResource = function(td) { 22916 var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id'); 22917 var tr = $(td).closest('tr'); 22918 var rid = tr.attr('resource_id'); 22919 var name = tr.find('td.resource').text(); 22920 22921 var fn = function() { 22922 GLO.Provider.Resource.removeResourceConfirmed(rgid, rid); 22923 }; 22924 22925 var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;'; 22926 new GLO.Popup.Confirm('<div style="' + css + '">Delete ' + name + '?</div>', fn); 22927 } 22928 22929 _conResourceAdmin.removeResourceConfirmed = function(rgid, rid) { 22930 var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/DeleteResource?resource_group_id=' + rgid + '&resource_id=' + rid; 22931 22932 var oj = new GLO.Popup.Processing('<div style="letter-spacing: 1px; line-height: 200%; letter-spacing: 1px;">Deleting Resource</div>'); 22933 22934 $.ajax({ type: "POST", url: uri, "cache": false }) 22935 .success(function(data, textStatus, jqXHR) { 22936 oj.close(); 22937 var rg = _getJsonObj(rgid); 22938 22939 for (var r=0; r < rg.resources.length; r++) { 22940 if (rg.resources[r].resource_id == rid) { 22941 rg.resources.splice(r, 1); 22942 break; 22943 } 22944 } 22945 22946 $('#resource-list').find('tr[resource_id="' + rid + '"]').remove(); 22947 }) 22948 .error(function(jqXHR, textStatus, errorThrown) { 22949 oj.close(); 22950 GLO.Popup.Error('Unable to delete this resource. Please try again.'); 22951 GLO.UI.Form.resetProcessing(); 22952 }); 22953 } 22954 22955 return _conResourceAdmin; 22956})(); 22957 22958 22959GLO.Provider.Loyalty = (function() { 22960 function _cLoyalty() { } 22961 var _isEnabledOnLoad = false, _popOpenResetPoints = null; 22962 22963 _cLoyalty.init = function(start, earnCode, redeemCode) { 22964 var j = $('#manage-loyalty'); 22965 var jearn = j.find('#Loyalty_Earn_cd'), jredeem = j.find('#Loyalty_Redeem_cd'); 22966 var yearRange = GLO.UI.getYearRange(true); //'2012:' + (new Date().getFullYear() + 2); 22967 var isPerVisit = j.find('#Loyalty_Earn_By_Visit_fl').prop('checked'); 22968 22969 var jstart = j.find('#Loyalty_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, maxDate: 0 22970 , changeYear: true, yearRange: yearRange, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
22970atepicker }); 22971 22972 if (UTIL.isDate(start)) { 22973 jstart.val(start).attr('original_value', start); 22974 } 22975 22976 if (earnCode > 0 || isPerVisit) { 22977 j.find('#Loyalty_Enable_fl').prop('checked', true).change(); 22978 jearn.val(earnCode); 22979 22980 _isEnabledOnLoad = true; 22981 } 22982 22983 if (redeemCode > 0) { 22984 jredeem.val(redeemCode); 22985 } else { 22986 j.find('#Loyalty_Redeem_By_Dollar_fl').prop('checked', false).change(); 22987 } 22988 22989 jearn.removeClass('hide'); 22990 jredeem.removeClass('hide'); 22991 22992 j.find('#Loyalty_Earn_By_Dollar_fl').change(); 22993 j.find('#Loyalty_Earn_By_Visit_fl').change(); 22994 22995 GLO.Info.init(); 22996 var isInvalidPackage = ((GLO.Info.providerPackage == 4 && UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) || GLO.Info.providerPackage == 1); 22997 22998 if (GLO.Info.roleType < 220 || isInvalidPackage) { 22999 j.find('input,select').prop('disabled', true); 23000 j.find('.btnSave').remove(); 23001 23002 if (isInvalidPackage) { 23003 var msg = 'Gold package required to enable Loyalty'; 23004 } else { 23005 var msg = 'Manage or Admin required to setup Loyalty'; 23006 } 23007 23008 GLO.Popup.Info.open(msg, 'Loyalty Restriction'); 23009 } 23010 23011 j.find("#manage-loyalty-earn input:checkbox").change(UI.CrossOutCheckbox).change(); 23012 //_initAutoSave(j); 23013 _initDetectChange(j); 23014 _initLoyaltyUrl(); 23015 } 23016 function _initLoyaltyUrl() { 23017 var highlight = GLO.Uri.url('highlight'); 23018 23019 if (!UTIL.isEmpty(highlight)) { 23020 var jhigh = $('#manage-loyalty').find('#' + highlight + ', .' + highlight); 23021 UI.highlight(jhigh, 300, 6000, true); 23022 } 23023 } 23024 function _initDetectChange(jcontainer) { 23025 var jlist = jcontainer.find('#Loyalty_Enable_fl, #Loyalty_Earn_cd, #Loyalty_Redeem_cd, #Loyalty_Start_dt, #Loyalty_Earn_By_Dollar_fl, #Loyalty_Earn_By_Visit_fl, #Loyalty_Earn1_pct, #Loyalty_Earn2_pct, #Loyalty_Redeem1_pct, #Loyalty_Redeem2_pct, #Loyalty_Cash_Bonus_pct'); 23026 jlist.change(GLO.Provider.Loyalty.changeByUser); 23027 23028 jlist.keyup(function(event) { 23029 if (UI.keyPressIsNumber(event)) { 23030 GLO.Provider.Loyalty.changeByUser(this, event); 23031 } 23032 }); 23033 } 23034 function _initAutoSave(jcontainer) { 23035 var jfields = jcontainer.find('input,select'); 23036 var uriSave = GLO.Link.WebsiteDomain + 'loyalty/save'; 23037 new UI.AutoSave(jfields, uriSave, GLO.Provider.Loyalty.afterAutoSave, 2400); 23038 } 23039 23040 _cLoyalty.changePerCheckbox = function(checkbox) { 23041 var jparent = $(checkbox).closest('div'); 23042 var jfields = jparent.find('input[type="number"], select'); 23043 23044 if ($(checkbox).prop('checked')) { 23045 jfields.prop('disabled', false); 23046 jparent.css({ "text-decoration": "" }).removeClass('is-disabled').addClass('is-enabled'); 23047 } else { 23048 jfields.prop('disabled', true); 23049 jparent.css({ "text-decoration": "line-through" }).removeClass('is-enabled').addClass('is-disabled'); 23050 } 23051 } 23052 23053 _cLoyalty.afterAutoSave = function() { 23054 23055 } 23056 23057 _cLoyalty.changeEnable = function() { 23058 var j = $('#manage-loyalty'); 23059 23060 if (j.find('#Loyalty_Enable_fl').prop('checked')) { 23061 j.addClass('loyalty-enabled'); 23062 j.find('#Loyalty_Redeem_By_Dollar_fl').prop('checked', false).click(); 23063 } else { 23064 j.removeClass('loyalty-enabled'); 23065 } 23066 } 23067 23068 _cLoyalty.changeByUser = function(element, event) { 23069 var j = $('#manage-loyalty'); 23070 var jsave = j.find('.btnSave'); 23071 23072 if (!jsave.hasClass('btn-has-change')) { 23073 jsave.addClass('btn-has-change'); 23074 23075 window.onbeforeunload = function() { 23076 return 'Are you sure you want to leave without saving changes?'; 23077 }; 23078 } 23079 } 23080 _cLoyalty.changeDeleteBonus = function(element) { 23081 var jbonus = $('#pop-confirm-reset-loyalty-bonus-inner'); 23082 23083 if ($(element).prop('checked')) { 23084 jbonus.removeClass('hide'); 23085 } else { 23086 jbonus.addClass('hide'); 23087 } 23088 23089 _popOpenResetPoints.realign(); 23090 setTimeout(_popOpenResetPoints.realign, 80); 23091 }
23092 _cLoyalty.openResetPoints = function(btn) { 23093 var jmain = $('#manage-loyalty'); 23094 23095 if (jmain.find('.btnSave.btn-has-change').length) { 23096 GLO.Popup.Warning.open('Loyalty Program has unsaved changes<br/>Please save changes before deleting loyalting points', 'Un-Saved Changes'); 23097 return; 23098 } 23099 23100 var startDate = jmain.find('#Loyalty_Start_dt').val(); 23101 var msg = 'Delete Loyalty Points Earned by Clients'; 23102 23103 if (UTIL.isDate(startDate)) { 23104 msg += ' before ' + startDate; 23105 var origDate = jmain.find('#Loyalty_Start_dt').attr('original_value'); 23106 23107 if (new Date(startDate).toGloDate() != new Date(startDate).toGloDate()) { 23108 var warningMsg = '<p>Please save change to <b>Loyalty Program Start Date</b> before <b style="color: red;">Deleting Points</b></p>'; 23109 GLO.Popup.Warning.open(warningMsg, 'Un-Saved Changes'); 23110 return; 23111 } 23112 } 23113 23114 var checkboxBonus = '<div id="pop-confirm-reset-loyalty-bonus-checkbox">' 23115 + '<input type="checkbox" id="Loyalty_Delete_Bonus_fl" onchange="GLO.Provider.Loyalty.changeDeleteBonus(this)" style="height: 24px; width: 24px; margin-top: -4px;">' 23116 + '<label for="Loyalty_Delete_Bonus_fl" style="font-weight: bold; font-size: 120%;">Delete All Bonus Points</label>' 23117 + '</div>' 23118 23119 var passwordInput = '<div id="pop-confirm-reset-loyalty-password">' 23120 + '<label for="Delete_Loyalty_Password_vc">Enter Password to Confirm Delete</label>' 23121 + '<input type="password" id="Delete_Loyalty_Password_vc" maxlength="50" style="width: 150px;">' 23122 + '</div>' 23123 var msgIncludes = '<span class="narrow-text">(this includes any loyalty points uploaded from another scheduling system or loyalty program)</span>'; 23124 var msgBonus = '<p style="padding: 12px 0; line-height: 1.4;">Delete Bonus Loyalty Points given to Clients ' + msgIncludes + '</p>'; 23125 var msgWarning = '<p style="text-align: center; font-weight: bold; font-size: 120%; color: red;">Be careful, this cannot be undone!</p>'; 23126 var divBonusInner = '<div id="pop-confirm-reset-loyalty-bonus-inner" class="hide">' + msgBonus + msgWarning + passwordInput + '</div>'; 23127 var divBonus = '<div id="pop-confirm-reset-loyalty-bonus">' + checkboxBonus + divBonusInner + '</div>'; 23128 23129 var htmMsg = '<p style="text-align: center;"> <b class="checkmark-icon"></b> ' + msg + '</p>'; 23130 var htm = '<div id="pop-confirm-reset-loyalty">' + htmMsg + divBonus + '</div>'; 23131 _popOpenResetPoints = GLO.Popup.Custom.openSimple(htm, 'Delete Client Loyalty Points', GLO.Provider.Loyalty.saveResetPoints, null, true); 23132 23133 var jbtns = _popOpenResetPoints.getPopup().find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "500px", "font-size": "150%" }); 23134 jbtns.find('.btnSave').removeClass('btnSave').addClass('btnDelete').css({ "float": "right", "width": "180px", "margin": "0" }).find('>a').text('Delete Points'); 23135 } 23136 _cLoyalty.saveResetPoints = function() { 23137 var jpop = $('#pop-confirm-reset-loyalty').closest('.glopop'); 23138 var isDeleteBonus = jpop.find('#Loyalty_Delete_Bonus_fl').prop('checked'); 23139 var password = jpop.find('#Delete_Loyalty_Password_vc').val(); 23140 23141 var uri = GLO.Link.WebsiteDomain + 'loyalty/DeletePoints'; 23142 var jd = { "isRefreshPoints": 0, "isDeleteBonus": isDeleteBonus, "password": password }; 23143 23144 var jstart = $('#manage-loyalty #Loyalty_Start_dt'); 23145 var startDate = jstart.val(), startDateOriginal = jstart.attr('original_value'); 23146 23147 if (UTIL.isDate(startDate)) { // && new Date(startDate).toGloDate() != new Date(startDateOriginal).toGloDate() 23148 jd.isRefreshPoints = 1; 23149 } 23150 23151 var jbtn = jpop.find('.btnDelete'); 23152 GLO.UI.Form.beginProcessing(jbtn); 23153 23154 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 23155 .success(function(data, textStatus, jqXHR) { 23156 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23157 var jresponse = $(data); 23158 23159 if (!UTIL.isEmpty(jresponse.attr('error_cd')) || jresponse.hasClass('error')) { 23160 GLO.Popup.Error.open(data, 'Unable to Delete Loyalty Points'); 23161 } else if (!UTIL.isEmpty(jresponse.attr('warning_cd')) || jresponse.hasClass('warning')) { 23162 GLO.Popup.Error.open(data, 'Issue Deleting Loyalty Points'); 23163 } else { 23164 GLO.Popup.closeIfExist(jpop); 23165 GLO.Popup.Success.open('Loyalty Points Deleted', 'Delete Successful', 19000); 23166 _popOpenResetPoints = null; 23167 } 23168 }) 23169 .error(function(jqXHR, textStatus, errorThrown) { 23170 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23171 GLO.Popup.Error.open('Please try again later', 'Unable to Delete Loyalty Points'); 23172 }); 23173 } 23174 23175 function _saveIsValid(jcontainer) { 23176 var fnSave = function() { GLO.Provider.Loyalty.save(true); } 23177 23178 if (!_isEnabledOnLoad && !jcontainer.find('#Loyalty_Enable_fl').prop('checked')) { 23179 var fnAction = function() { 23180 GLO.Popup.close($('#pop-confirm-loyalty-enable').closest('.glopop')); 23181 $('#manage-loyalty').find('#Loyalty_Enable_fl').prop('checked', true).change(); 23182 GLO.Provider.Loyalty.save(); 23183 } 23184 23185 var htm = '<div id="pop-confirm-loyalty-enable" style="margin-top: 8px;">Do you want to Enable Loyalty?</div>'; 23186 GLO.Popup.Confirm.open(htm, 'Enable Loyalty?', fnAction, fnSave); 23187 return false; 23188 } 23189 23190 return true; 23191 } 23192 23193 _cLoyalty.save = function(isOverride) { 23194 var uri = GLO.Link.WebsiteDomain + 'loyalty/save'; 23195 var j = $('#manage-loyalty'); 23196 var jbtn = j.find('.btnSave'); 23197 23198 if (!isOverride) { 23199 if (!_saveIsValid(j)) { return; } 23200 } 23201 23202 GLO.UI.Form.beginProcessing(jbtn); 23203
23204 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: j.serialize() }) 23205 .success(function(data, textStatus, jqXHR) { 23206 window.onbeforeunload = null; 23207 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23208 jbtn.removeClass('btn-has-change'); 23209 23210 new GLO.Popup.Success(data, 19000); 23211 }) 23212 .error(function(jqXHR, textStatus, errorThrown) { 23213 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23214 //new GLO.Popup.Error('Unable to order the calendars staff'); 23215 }); 23216 } 23217 23218 return _cLoyalty; 23219})(); 23220 23221GLO.Provider.ShoppingCart = (function() { 23222 function _cShoppingCart() { } 23223 23224 _cShoppingCart.initConfig = function(cartConfig) { 23225 if (cartConfig !== null && cartConfig !== undefined) { 23226 var j = $('#manage-cart'); 23227 j.find('#Shipping_Policy_Note_vc').val(cartConfig.ShippingPolicyText); 23228 j.find('#Refund_Policy_Note_vc').val(cartConfig.RefundPolicyText); 23229 j.find('#store_popup_note_vc').val(cartConfig.PopupText); 23230 if (cartConfig.PopupImagePath !== '') { 23231 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + cartConfig.PopupImagePath; 23232 j.find('#store-popup-image-path').val(cartConfig.PopupImagePath); 23233 j.find('#store-popup-image-preview').attr("src",img_path); 23234 $('.store-popup-add-image').addClass('hide'); 23235 $('.store-popup-remove-image').removeClass('hide'); 23236 } 23237 j.find('input[name="Shopping_Cart_Enable_fl"]')[0].checked = cartConfig.CartEnabled; 23238 j.find('input[name="Sell_Memberships_fl"]')[0].checked = cartConfig.SellMemberships; 23239 j.find('input[name="Sell_Packages_fl"]')[0].checked = cartConfig.SellPackages; 23240 } else { 23241 GLO.UI.Form.resetProcessing(); 23242 new GLO.Popup.Error('Unable to retrieve Store settings. Please refresh page.'); 23243 } 23244 23245 GLO.Provider.ShoppingCart.changeEnable(); 23246 } 23247 23248 _cShoppingCart.validateEnable = function() { 23249 //check if on gold plan 23250 //check if products are setupo 23251 //check if merchant account is setup 23252 23253 initConfig 23254 } 23255 23256 _cShoppingCart.changeEnable = function() { 23257 var j = $('#manage-cart'); 23258 23259 if (j.find('#Shopping_Cart_Enable_fl').prop('checked')) { 23260 j.addClass('is-enabled'); 23261 } else { 23262 j.removeClass('is-enabled'); 23263 } 23264 } 23265 23266 _cShoppingCart.saveConfig = function() { 23267 var uri = GLO.Link.WebsiteDomain + 'provider/manage/cartconfig'; 23268 var j = $('#manage-cart'); 23269 var jbtn = j.find('.btnSave'); 23270 23271 var ShippingPolicyNote = j.find('#Shipping_Policy_Note_vc').val(); 23272 var RefundPolicyNote = j.find('#Refund_Policy_Note_vc').val(); 23273 var StorePopupNote = j.find('#store_popup_note_vc').val(); 23274 var PopupImagePath = j.find('#store-popup-image-path').val(); 23275 var EnableCart = j.find('input[name="Shopping_Cart_Enable_fl"]:checked').val(); 23276 var EnableMemberships = j.find('input[name="Sell_Memberships_fl"]:checked').val(); 23277 var EnablePackages = j.find('input[name="Sell_Packages_fl"]:checked').val(); 23278 var UpdatedByStaffId = GLO.Info.getStaffId(); 23279 23280 23281 GLO.UI.Form.beginProcessing(jbtn); 23282 23283 var viewModel = { 23284 "ProviderId":GLO.Data.provider.id, "ShippingPolicyText": ShippingPolicyNote, "RefundPolicyText": RefundPolicyNote, "CartEnabled": (EnableCart == 'on' ? 'true' : 'false') 23285 , "SellMemberships": (EnableMemberships == 'on' ? 'true' : 'false'), "SellPackages": (EnablePackages == 'on' ? 'true' : 'false'), "UpdatedByStaffId": UpdatedByStaffId, 23286 "PopupText":StorePopupNote,"PopupImagePath":PopupImagePath 23287 } 23288 23289 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: viewModel }) 23290 .success(function(data, textStatus, jqXHR) { 23291 window.onbeforeunload = null; 23292 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23293 jbtn.removeClass('btn-has-change'); 23294 23295 GLO.Popup.Success.open('Store settings updated', 'Store Config', 19000); 23296 }) 23297 .error(function(jqXHR, textStatus, errorThrown) { 23298 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23299 new GLO.Popup.Error('Unable to update Store settings'); 23300 }); 23301 } 23302 23303 _cShoppingCart.launchStorePopupImages= function(event) { 23304 23305 GLO.UI.loadBulkitCss(); 23306 23307 $('#store-popup-images-container').modal(); 23308 var jModal = $('#simplemodal-container #store-popup-images-container');
23309 var h = $(window).height() * 0.8; 23310 var w = $(window).width() * 0.8; 23311 23312 $.modal.update(h,w); 23313 $(window).resize(); 23314 $('.modalCloseImg').css("margin-top","20px"); 23315 $('.modalCloseImg').css("margin-right","20px"); 23316 $('.modalCloseImg').on("click",function() { GLO.Provider.ShoppingCart.closeStorePopupImages(); }); 23317 23318 if (GLO.Info.isMobile()) { 23319 $('#simplemodal-container').draggable({disable:true}); 23320 } 23321 $('#simplemodal-container').css("overflow-y","auto"); 23322 23323 // var frm = $('#inventory-item-form'); 23324 // var iid = frm.find('#Inventory_id').val(); 23325 23326 // GLO.Inventory.Item.getItemImages(iid); 23327 } 23328 23329 _cShoppingCart.closeStorePopupImages = function() { 23330 23331 $('.modalCloseImg').off("click"); 23332 GLO.UI.removeBulkitCss(); 23333 } 23334 23335 23336 _cShoppingCart.uploadImageAndResize = function () { 23337 //define the width to resize e.g 180px 23338 var resize_width = 500;//without px 23339 23340 //get the image selected 23341 var item = document.querySelector('#uploader').files[0]; 23342 23343 //create a FileReader 23344 var reader = new FileReader(); 23345 23346 //image turned to base64-encoded Data URI. 23347 reader.readAsDataURL(item); 23348 reader.name = item.name;//get the image's name 23349 reader.size = item.size; //get the image's size 23350 reader.onload = function(event) { 23351 var img = new Image();//create a image 23352 img.src = event.target.result;//result is base64-encoded Data URI 23353 img.name = event.target.name;//set name (optional) 23354 img.size = event.target.size;//set size (optional) 23355 img.onload = function(el) { 23356 var elem = document.createElement('canvas');//create a canvas 23357 23358 //scale the image to 600 (width) and keep aspect ratio 23359 var scaleFactor = resize_width / el.target.width; 23360 elem.width = resize_width; 23361 elem.height = el.target.height * scaleFactor; 23362 23363 //draw in canvas 23364 var ctx = elem.getContext('2d'); 23365 ctx.drawImage(el.target, 0, 0, elem.width, elem.height); 23366 23367 //get the base64-encoded Data URI from the resize image 23368 var srcEncoded = ctx.canvas.toDataURL('image/png', 1); 23369 23370 //assign it to thumb src 23371 document.querySelector('#store-popup-image').src = srcEncoded; 23372 23373 $('#btnSaveItemImage').removeClass('is-hidden'); 23374 $('#btnSaveItemImage').on("click",function() { GLO.Provider.ShoppingCart.saveStorePopupImage(srcEncoded,resize_width); }); 23375 } 23376 } 23377 } 23378 23379 _cShoppingCart.saveStorePopupImage = function(data,width) { 23380 23381 //remove the attached handler 23382 $('#btnSaveItemImage').off("click"); 23383 23384 var jcontainer = $('#uploader'); 23385 23386 //reset error 23387 $('#itemImageUploadErrorMessage').addClass('is-hidden'); 23388 23389 var fnCallback = function(jcontainer, fileName, imgId, imgSize) { 23390 if (fileName!=null && fileName.length > 0) { 23391 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName; 23392 // console.log(img_path); 23393 23394 //clear the image display 23395 document.querySelector('#store-popup-image').src =''; 23396 $('#btnSaveItemImage').addClass('is-hidden'); 23397 // $('#btnCloseModal').addClass('is-hidden'); 23398 23399 //set hidden field value 23400 $('#store-popup-image-path').val(fileName); 23401 23402 //assign it to preview src 23403 document.querySelector('#store-popup-image-preview').src = img_path; 23404 $('.store-popup-add-image').addClass('hide'); 23405 $('.store-popup-remove-image').removeClass('hide'); 23406 23407 //close the modal 23408 $('.simplemodal-close').click(); 23409 // closeItemOptionUploadColorSwatch 23410 23411 } 23412 else { 23413 //display error 23414 $('#itemImageUploadErrorMessage').removeClass('is-hidden'); 23415 } 23416 } 23417 23418 if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) { 23419 return true; 23420 } 23421 } 23422 23423 _cShoppingCart.removePopupImage = function(event) { 23424 $('#store-popup-image-path').val(''); 23425 23426 //assign it to preview src 23427 document.querySelector('#store-popup-image-preview').src = ''; 23428 $('.store-popup-add-image').removeClass('hide'); 23429 $('.store-popup-remove-image').addClass('hide'); 23430 } 23431 23432 23433 _cShoppingCart.openCreateShipping = function() { 23434 // var jhead = $('#gift-card-manage #report-header-help-gift'); 23435 // var customCards = UTIL.coalesceInt(jhead.attr('custom_gift_card_count_sr'), 0); 23436 23437 var small1 = '<small style="letter-spacing: 0;">(Birthday, Anniversary, Happy Graduation, etc)</small>'; 23438 var p1 = '<p>Setup how much you charge for shipping at checkout.</p>'; 23439 var p2 = '<p>Create custom flat-rate shipping options for customer to choose from.</p>';
23440 var msg = '<div id="pop-info-shipping-option">' + p1 + p2 + '</div>'; 23441 var gcLabel = 'Shipping Rate '; 23442 23443 if (innerWidth < 400) { gcLabel = ''; } 23444 23445 var lblName = '<label for="Shipping_Option_Name_vc">' + gcLabel + 'Name</label>'; 23446 var inputName = '<input id="Shipping_Option_Name_vc" type="text" placeholder="Shipping Rate Name" value="Flat-rate shipping"/>'; 23447 var htmName = '<div id="pop-create-shipping-option-name">' + lblName + inputName + '</div>'; 23448 23449 var lblAmount = '<label for="Shipping_Option_Price_mn">' + gcLabel + 'Amount</label>'; 23450 var inputAmount = '<input id="Shipping_Option_Price_mn" type="text" pattern="[0-9]*" onkeypress="UI.numberOnly(event, false, false, true)" placeholder="Shipping Rate" value="25"/>'; 23451 var htmAmount = '<div id="pop-create-shipping-option-price">' + lblAmount + '<b class="dollar-sign">$</b>' + inputAmount + '</div>'; 23452 23453 // if (false && customCards > 0) { 23454 // var lblDefault = '<label for="Default_Gift_Card_fl">Default Gift Card</label>'; 23455 // var inputDefault = '<input id="Default_Gift_Card_fl" type="checkbox"/>'; 23456 // var htmDefaultCard = '<div id="pop-create-gift-card-default">' + inputDefault + lblDefault + '</div>'; 23457 // } else { 23458 // var htmDefaultCard = ''; 23459 // } 23460 23461 // var htmVoucherInput = '<input id="Gift_Only_fl" type="checkbox"/>'; 23462 // var htmVoucherLabel = '<label for="Gift_Only_fl">
23462Is Gift Voucher</label>'; 23463 // var htmVoucherHelp = '<p>Gift Voucher cannot be used by client purchasing voucher, voucher must be used by different client</p>'; 23464 // var htmVoucher = '<div id="pop-create-gift-voucher">' + htmVoucherInput + htmVoucherLabel + htmVoucherHelp + '</div>'; 23465 23466 // var htmExpireInput = '<input id="Expire_Days_sr" type="text"/>'; 23467 // var htmExpireLabel1 = '<label for="Expire_Days_sr">Voucher Expires</label>'; 23468 // var htmExpireLabel2 = '<label for="Expire_Days_sr">Weeks After Purchase</label>'; 23469 // var htmExpire = '<div id="pop-create-gift-expire">' + htmExpireLabel1 + htmExpireInput + htmExpireLabel2 + '</div>'; 23470 var htmDefaultCard = ''; 23471 var htm = '<div id="pop-create-shipping-option"><p>' + msg + '</p> <form>' + htmName + htmAmount + htmDefaultCard + '</form></div>'; // + htmExpire + htmVoucher 23472 var jpop = GLO.Popup.Custom.openSimple(htm, 'Add New Shipping Rate', GLO.Provider.ShoppingCart.saveShipping); 23473 } 23474 23475 _cShoppingCart.saveShipping = function() { 23476 var jpop = $('#pop-create-shipping-option').closest('.glopop'); 23477 var amt = UTIL.displayMoney(jpop.find('#Shipping_Option_Price_mn').val(), true); 23478 var nm = $.trim(UTIL.htmlEncode4(jpop.find('#Shipping_Option_Name_vc').val())); 23479 var jd = { "name": nm, "amount": amt }; 23480 var url = GLO.Info.http + document.location.host + '/Inventory/AddShippingRate'; 23481 23482 GLO.UI.Form.beginProcessing( jpop.find('.btnSave') ); 23483 23484 $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 23485 .success(function(data, textStatus, jqXHR) { 23486 23487 if (data!==null && data.status =='success') { 23488 var msg1 = '<p>Shipping Rate Successfully Created</p>'; 23489 var htm = '<div id="pop-success-create-shipping-option">' + msg1 + '</div>'; 23490 23491 GLO.Popup.Success.open(htm, 'Shipping Rate Added', 3000); 23492 GLO.Popup.close(jpop); 23493 } 23494 else { 23495 GLO.Popup.Error('Unable to save shipping rate. Please try again'); 23496 // console.log(data.message); 23497 GLO.UI.Form.resetProcessing(); 23498 } 23499 23500 23501 }) 23502 .error(function(jqXHR, textStatus, errorThrown) { 23503 GLO.Popup.Error('Unable to save shipping rate. Please try again'); 23504 GLO.UI.Form.resetProcessing(); 23505 }); 23506 } 23507 23508 23509 _cShoppingCart.openHelp = function() { 23510 //TODO: DISPLAY SHOPPING CART SETUP HELP DOCS 23511 } 23512 return _cShoppingCart; 23513})(); 23514 23515GLO.Provider.ReputationManagement = (function() { 23516 function _reputation() { } 23517 23518 _reputation.init = function(providerReputationConfig) { 23519 var j = $('#manage-reputation'); 23520 var btnSave = j.find('.btnSave'); 23521 23522 if (providerReputationConfig.Enable_Appt_Survey == true) { 23523 j.addClass('reputation-enabled'); 23524 $('#appt_survey_message').prop('disabled',false); 23525 j.find('#Send_Appt_Survey_fl').prop('checked',true); 23526 $('#appt_survey_message').val(providerReputationConfig.Appt_Survey_Message); 23527 23528 } else { 23529 j.removeClass('reputation-enabled'); 23530 $('#appt_survey_message').prop('disabled',true); 23531 $('#appt_survey_message').val(''); 23532 j.find('#Send_Appt_Survey_fl').prop('checked',false); 23533 } 23534 23535 if (providerReputationConfig.Enable_Testimonials_Page == true) { 23536 j.find('#enable_testimonials_on_website_fl').prop('checked',true); 23537 } 23538 else { 23539 j.find('#enable_testimonials_on_website_fl').prop('checked',false); 23540 } 23541 23542 j.find('.review-link-input').on('keyup', GLO.Provider.ReputationManagement.keyupSocialMediaKey).keyup(); 23543 j.find('input, select').change(function() { UI.buttonDisplayChange(btnSave); }); 23544 j.find('input').keyup(function() { UI.buttonDisplayChange(btnSave); }); 23545 } 23546 23547 _reputation.keyupSocialMediaKey = function() { 23548 var jthis = $(this); 23549 var urlKey = jthis.val(); 23550 var jparent = jthis.closest('.manage-repuation-review-link'); 23551 var jlink = jparent.find('.social-media-link-column'); 23552 var url = ''; 23553 23554 if (!UTIL.isEmpty(urlKey)) { 23555 url = jparent.find('.review-domain').text() + urlKey; 23556 23557 if (innerWidth > 999) { 23558 var urlCSS = '', urlCaption = url; 23559 } else { 23560 var urlCaption = '➜'; //Heavy Round-Tipped Right Arrow 23561 var urlCSS = ' class="arrow-link"'; 23562 } 23563 23564 var link = '<a' + urlCSS + ' onclick="SA.App.openLinkInBrowser(\'https://' + url + '\', \'social-media-link\', true, null, true)">' + urlCaption + '</a>'; 23565 //var link = '<a' + urlCSS + ' onclick="GLO.Uri.gotoUri(\'' + url + '\', this, event, true)">' + url + '</a>'; 23566 } else { 23567 var link = ''; 23568 } 23569 23570 jlink.html(link); 23571 } 23572 23573 _reputation.highlightThumbsUpGoto = function() { 23574 var jgoto = $('#manage-reputation-great-goto'); 23575 UI.highlight(jgoto, 80, 4500, false); 23576 } 23577 _reputation.changeEnable = function() { 23578 var j = $('#manage-reputation'); 23579 23580 if (j.find('#Send_Appt_Survey_fl').prop('checked')) { 23581 j.addClass('reputation-enabled'); 23582 $('#appt_survey_message').prop('disabled',false); 23583 23584 } else { 23585 j.removeClass('reputation-enabled'); 23586 $('#appt_survey_message').prop('disabled',true); 23587 $('#appt_survey_message').val(''); 23588 } 23589 } 23590 23591 _reputation.openHelp = function(popId, h1) { 23592 var htm = $('#' + popId).outerHTML(); 23593 var ojpop = GLO.Popup.Info.open(htm, h1); 23594 23595 ojpop.addScrollBar(); 23596 ojpop.getPopup().addClass('pop-help-appt-survey'); 23597 } 23598 23599 _reputation.openHelpGoogleReview = function() { 23600 var htm = $('#pop-review-google-link').outerHTML(); 23601 GLO.Popup.Info.open(htm, 'Google Review Link').getPopup(); 23602 } 23603 _reputation.openHelpFacebookReview = function() { 23604 var htm = $('#pop-facebook-review-link-help').outerHTML(); 23605 var jpop = GLO.Popup.Info.open(htm, 'Facebook Review Link').getPopup().addClass('help-review-link'); 23606 } 23607 23608 _reputation.save = function(isOverride) { 23609 var uri = GLO.Link.WebsiteDomain + 'repman/save'; 23610 var j = $('#manage-reputation'); 23611 var jbtn = j.find('.btnSave'); 23612 23613 var SendApptSurvey = j.find('#Send_Appt_Survey_fl').prop('checked'); 23614 var EnableTestimonialsPage = j.find('#enable_testimonials_on_website_fl').prop('checked'); 23615 var ApptSurveyMessage = j.find('#appt_survey_message').val(); 23616 var greatGoTo = j.find('input[name="appt-survey-great-goto"]:checked').val(); 23617 23618 var googleReviewUrl = j.find('#Google_Review_Url').val(); 23619 var facebookReviewUrl = j.find('#Facebook_Review_Url').val(); 23620 23621 23622 GLO.UI.Form.beginProcessing(jbtn); 23623 23624 var viewModel = { 23625 "Enable_Appt_Survey": SendApptSurvey, "Appt_Survey_Message": ApptSurveyMessage, "GoToOnPositiveExperience": greatGoTo 23626 , "GoogleReviewUrl": googleReviewUrl, "FacebookReviewUrl": facebookReviewUrl, "YelpReviewUrl": "", "Enable_Testimonials_Page": EnableTestimonialsPage 23627 } 23628
23629 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: viewModel }) 23630 .success(function(data, textStatus, jqXHR) { 23631 window.onbeforeunload = null; 23632 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23633 jbtn.removeClass('btn-has-change'); 23634 23635 GLO.Popup.Success.open(data, 'Appointment Survey', 19000); 23636 }) 23637 .error(function(jqXHR, textStatus, errorThrown) { 23638 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 23639 //new GLO.Popup.Error('Unable to order the calendars staff'); 23640 }); 23641 } 23642 return _reputation; 23643})(); 23644 23645 23646GLO.Provider.MemberService = (function() { 23647 function _cMemberService() { } 23648 23649 _cMemberService.init = function(isRefresh) { 23650 _initReport('Member Service Report', isRefresh); 23651 } 23652 _cMemberService.initActivityReport = function(isRefresh) { 23653 var jhead = $('#report-main .report-search-header'); 23654 var htmSummary = $.trim($('#membership-report tfoot .member-column-duration').html()); 23655 23656 if (!UTIL.isEmpty(htmSummary) && (UTIL.isDate(jhead.find('#Member_Start_dt').val()) || UTIL.isDate(jhead.find('#Member_End_dt').val())) ) { 23657 htmSummary = '<div style="font-weight: bold;">During Searched Period</div>' + htmSummary; 23658 } 23659 23660 $('#membership-report-summary').html(htmSummary); 23661 23662 if (!isRefresh) { 23663 var yearRange = GLO.UI.getYearRange(true); 23664 23665 jhead.find('.is-date-picker').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 23666 , dateFormat: "M d, yy", numberOfMonths: 1, beforeShow: UI.loadDatepicker, changeYear: true, yearRange: yearRange }); 23667 } 23668 23669 _initReport('Member Activity Report', isRefresh); 23670 _initFromUrl(); 23671 } 23672 function _initFromUrl() { 23673 var highlight = GLO.Uri.url('highlight'); 23674 var open = GLO.Uri.url('open'); 23675 var step = GLO.Uri.url('step'); 23676 23677 if (open == 'membership-setup-how-to' || open == 'how-to-guide-membership') { 23678 GLO.Provider.Membership.Help.openHowToSetup(step); 23679 } 23680 23681 if (!UTIL.isEmpty(highlight)) { 23682 var jhigh = jm.find('#' + highlight); 23683 23684 if (jhigh.length) { 23685 UI.highlight(jhigh, 300, 8000, true); 23686 } else { 23687 setTimeout(function() { 23688 var jhigh = $('.glopop #' + highlight); 23689 UI.highlight(jhigh, 300, 9000, true); 23690 }, 800); 23691 } 23692 } 23693 } 23694 function _initReport(reportName, isRefresh) { 23695 var jrpt = $('#membership-report.tablesorter'); 23696 UI.initTableSorter(jrpt); 23697 23698 GLO.Report.enableFullPageCheck(); 23699 GLO.Report.CellSummary.initReport(jrpt, false, true); 23700 23701 if (!isRefresh) { 23702 GLO.Report.portalName = reportName; 23703 GLO.Report.setupFastClick(); 23704 GLO.Staff.Filter.isReportPortal = true; 23705 23706 var mid = UTIL.cleanString(GLO.Uri.query('membership')); 23707 var jhead = $('#report-main .report-search-header'); 23708 var dd = GLO.Provider.Membership.getMembershipDropDown(); 23709 23710 jhead.find('#Membership_id').replaceWith(dd); 23711 jhead.find('#Membership_id').val(mid).change(GLO.Provider.Membership.searchReport).find('option:first').text('(all memberships)'); 23712 23713 _initShortcut(); 23714 _initUri(); 23715 } 23716 } 23717 23718 function _initUri() { 23719 var cid = GLO.Uri.url('client'); 23720 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 23721 var start = GLO.Uri.url('start'); 23722 var end = GLO.Uri.url('end'); 23723 23724 if (UTIL.isNumber(cid)) { 23725 var tr = $('#membership-report').find('tr[client_id="' + cid + '"]'); 23726 23727 if (tr.length === 1 && !UTIL.isEmpty(open)) { 23728 if (open === 'profile' || open === 'client') { 23729 tr.find('.membership-column-client, .member-column-client').find('>a').click(); 23730 } else if (open === 'membership' || open === 'name') { 23731 tr.find('.membership-column-name, .member-column-membership').find('>a').click(); 23732 } else if (open === 'status' || open === 'pay-status') {
23733 tr.find('.membership-column-pay-status, .member-column-status').click(); 23734 } else { 23735 tr.find('.membership-column-' + open + '.member-column-' + open).click(); 23736 } 23737 } 23738 } 23739 23740 if (UTIL.isDate(start)) { 23741 $('#Member_Start_dt').val(new Date(start).toGloDate()); 23742 } 23743 23744 if (UTIL.isDate(end)) { 23745 $('#Member_End_dt').val(new Date(end).toGloDate()); 23746 } 23747 } 23748 function _initShortcut() { 23749 $(document).keydown(function(event) { 23750 if (event.altKey) { 23751 if (event.which === 82) { //R: refresh report 23752 GLO.Provider.Membership.searchReport(); //GLO.Provider.Membership.searchReport(); 23753 } 23754 } 23755 }); 23756 $(window).bind('keypress', function(e) { 23757 if (e.altKey) { 23758 if (e.which === 82) { //R: refresh report 23759 e.preventDefault(); 23760 } 23761 } 23762 }); 23763 } 23764 23765 _cMemberService.clearDates = function(icon) { 23766 var jhead = $(icon).closest('.report-search-header'); 23767 jhead.find('.is-date-picker').val('').change(); 23768 } 23769 23770 _cMemberService.searchReport = function() { 23771 var qs = '', jhead = $('#report-main .report-search-header'); 23772 var mid = jhead.find('#Membership_id').val(); 23773 23774 if (!UTIL.isEmpty(mid)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'membership=' + mid); } 23775 23776 var url = window.location.origin + window.location.pathname + qs; 23777 window.history.pushState('', '', url); 23778 23779 //if (title) { document.title = title; } 23780 23781 $('h2#membership-report-header .fa-refresh').click(); 23782 } 23783 _cMemberService.refreshReport = function(button) { 23784 var jd = {}; 23785 button = $(button); 23786 23787 if (button.hasClass('fa-spin')) { 23788 return; 23789 } else if (!GLO.Report.hasReportPassword(jd)) { 23790 return; 23791 } else if (button.hasClass('fa')) { 23792 button.addClass('fa-spin'); 23793 } else { 23794 GLO.UI.Form.beginProcessing(button.parent()); 23795 } 23796 23797 GLO.UI.Form.beginProcessing($('.report-search-header .btnSearch')); 23798 23799 var jrpt = $('.report-container'); 23800 var uri = GLO.Uri.addQueryKeyAndValue(location.href, 'ispartial=1'); 23801 23802 var jqxhr = $.ajax({ "type": "POST", "url": uri, "cache": false, "data": jd }) 23803 .success(function(data, textStatus, jqXHR) { 23804 button.removeClass('fa-spin'); 23805 GLO.UI.Form.resetProcessing(); 23806 23807 jrpt.html($(data).outerHTML()); 23808 23809 if ($('#member-activity-report.report-container').length) { 23810 _cMemberService.initActivityReport(true); 23811 } else { 23812 _cMemberService.init(true); 23813 } 23814 }) 23815 .error(function(jqXHR, textStatus, errorThrown) { 23816 button.removeClass('fa-spin'); 23817 GLO.UI.Form.resetProcessing(); 23818 23819 var htm = '<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>'; 23820 jrpt.html(htm); 23821 }); 23822 } 23823 23824 return _cMemberService; 23825})(); 23826 23827 23828GLO.Provider.Membership = (function() { 23829 function _cMembership() { } 23830 23831 var _popEditType, _popEditTypeService; 23832 23833 function _loadPopup(popid) { 23834 var jpop = $('#' + popid); 23835 var htm = jpop.outerHTML(); 23836 jpop.remove(); 23837 return htm; 23838 } 23839 23840 _cMembership.init = function() { 23841 GLO.Info.init(); 23842 23843 _popEditType = _loadPopup('pop-membership-edit'); 23844 _popEditTypeService = _loadPopup('pop-membership-service-edit'); 23845 23846 var j = $('#manage-membership'); 23847 var isInvalidPackage = ((GLO.Info.providerPackage == 4 && UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) || GLO.Info.providerPackage == 1); 23848 23849 if (isInvalidPackage) { 23850 j.find('input,select').prop('disabled', true); 23851 j.find('.btnSave, .btnAddMembership').remove(); 23852 23853 if (isInvalidPackage) { 23854 var msg = 'Gold package required to enable Membership'; 23855 } else { 23856 var msg = 'Manager or Admin required to setup Membership'; 23857 } 23858 23859 GLO.Popup.Info.open(msg, 'Membership Restriction'); 23860 return; 23861 } 23862 23863 var jtbl = j.find('table#membership-list'); 23864 var jtbody = jtbl.find('tbody'); 23865 23866 jtbody.on('click', '.column-member-name, .column-member-price, .column-member-period, .column-member-
23866auto-bill, .column-member-description', GLO.Provider.Membership.openEditType); 23867 jtbody.on('click', 'tr.membership-type-service', GLO.Provider.Membership.openEditService); 23868 23869 if (jtbody.find('tr').length > 0) { jtbl.removeClass('hide'); } 23870 _initTable(jtbody); 23871 _initUrlMembershipSetup(); 23872 } 23873 function _initUrlMembershipSetup() { 23874 var isCreateMembership = UTIL.cleanString(GLO.Uri.url('create')).toLowerCase() === 'membership'; 23875 var msvcid = GLO.Uri.url('mservice'); 23876 var mid = GLO.Uri.url('membership'); 23877 var jm = $('#manage-membership'); 23878 var highlight = GLO.Uri.url('highlight'); 23879 var open = GLO.Uri.url('open'); 23880 var step = GLO.Uri.url('step'); 23881 23882 if (isCreateMembership) { 23883 GLO.Provider.Membership.openEditType(); 23884 } else if (!UTIL.isEmpty(msvcid)) { 23885 if (msvcid > 1) { 23886 var jTypeService = jm.find('.membership-type-service[membership_service_id="' + msvcid + '"]'); 23887 } else { 23888 var jTypeService = jm.find('.membership-type-service:first'); 23889 } 23890 23891 jTypeService.click(); 23892 jm = $('#pop-membership-service-edit').glopop('.closest'); 23893 } else if (open == 'membership-setup-how-to' || open == 'how-to-guide-membership') { 23894 GLO.Provider.Membership.Help.openHowToSetup(step); 23895 } else if (open == 'edit-membership') { 23896 if (!UTIL.isEmpty(mid)) { 23897 var jmembership = $('#membership-list').find('tr.membership-type[membership_id="' + mid + '"]'); 23898 } else { 23899 var jmembership = $('#membership-list').find('tr.membership-type'); 23900 } 23901 23902 jmembership.find('td.column-member-name').click(); 23903 } 23904 23905 if (!UTIL.isEmpty(highlight)) { 23906 var jhigh = jm.find('#' + highlight); 23907 23908 if (jhigh.length) { 23909 UI.highlight(jhigh, 300, 8000, true); 23910 } else { 23911 setTimeout(function() { 23912 var jhigh = $('.glopop #' + highlight); 23913 UI.highlight(jhigh, 300, 9000, true); 23914 }, 800); 23915 } 23916 } 23917 } 23918 _cMembership.initReport = function(isReload) { 23919 GLO.Info.init(); 23920 GLO.Staff.Filter.isReportPortal = true; 23921 GLO.Report.Template.initStaffFilter(); 23922 23923 var jrpt = $('#membership-report.tablesorter'); 23924 UI.initTableSorter(jrpt); 23925 GLO.Report.enableFullPageCheck(); 23926 GLO.Report.CellSummary.initReport(jrpt, false, true); 23927 23928 if (innerWidth < 800 && $('body.report-full-page').length === 0) { 23929 $('#membership-report thead td.membership-column-period').attr('colspan', 3); 23930 } 23931 23932 if (!isReload) { 23933 GLO.Report.portalName = 'Membership Report'; 23934 GLO.Report.setupFastClick(); 23935 GLO.Staff.Filter.isReportPortal = true; 23936 23937 var mid = UTIL.cleanString(GLO.Uri.query('membership')), status = UTIL.cleanString(GLO.Uri.query('status')); 23938 var sfilter = GLO.Uri.url('sfilter'); 23939 23940 var jhead = $('#report-main .report-search-header'); 23941 var dd = _cMembership.getMembershipDropDown(); 23942 jhead.find('#Membership_id').replaceWith(dd); 23943 23944 jhead.find('#Membership_id').val(mid).change(GLO.Provider.Membership.searchReport).find('option:first').text('(all memberships)'); 23945 jhead.find('#Membership_Status_cd').val(status).change(GLO.Provider.Membership.searchReport); 23946 23947 if (GLO.Info.roleType > 209 && !UTIL.isEmpty(sfilter) && sfilter.toLowerCase() !== 'all') { 23948 GLO.Report.setStaffFilter(sfilter); //$('#staff-filter').val(sfilter).change(); 23949 } 23950 23951 _initShortcut(); 23952 _initUri(); 23953 23954 if (GLO.Info.isMobile()) { 23955 $('#staff-filter').prepend('<option value="">All</option>'); 23956 23957 if (UTIL.isEmpty(sfilter)) { 23958 $('#staff-filter').val(sfilter); 23959 } 23960 } 23961 23962 _setMembershipReportOverview(); 23963 _initNoMemberships(); 23964 _initUrlMembershipSetup(); 23965 } 23966 23967 jrpt.on('click.open-tag', '.client-tag', GLO.Report.openTag); 23968 } 23969 function _initNoMemberships() { 23970 if (GLO.Data.provider.MembershipList.length === 0) { 23971 var msg1 = '<p>No Memberships Setup</p>'; 23972 var msg2 = '<p>Go to <a onclick="GLO.Uri.gotoUriWithSpinner(\'membership\', this, event, true)">Membership Setup</a></p>'; 23973 23974 GLO.Popup.Info.open('<div id="pop-help-no-memberships">' + msg1 + msg2 + '</div>', 'No Memberships Setup'); 23975 } 23976 } 23977 function _initUri() { 23978 var cid = GLO.Uri.url('client'); 23979 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 23980 23981 if (!UTIL.isEmpty(cid)) { 23982 if (cid > 1) { 23983 var tr = $('#membership-report').find('tr[client_id="' + cid + '"]'); 23984 } else { 23985 var tr = $('#membership-report').find('tbody tr:first'); 23986 } 23987 23988 if (tr.length === 1 && !UTIL.isEmpty(open)) { 23989 if (open === 'profile' || open === 'client') { 23990 tr.find('.membership-column-client').find('>a').click(); 23991 } else if (open === 'membership' || open === 'name') { 23992 tr.find('.membership-column-name').find('>a').click(); 23993 } else if (open === 'status' || open === 'pay-status') {
23994 tr.find('.membership-column-pay-status').click(); 23995 } else { 23996 tr.find('.membership-column-' + open).click(); 23997 } 23998 23999 setTimeout(GLO.Provider.Membership.initUri2, 1500); 24000 } 24001 } 24002 } 24003 _cMembership.initUri2 = function() { 24004 var open2 = UTIL.cleanString(GLO.Uri.url('open2')).toLowerCase(); 24005 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 24006 var highlightClass = UTIL.cleanString(GLO.Uri.url('highlight-class')).toLowerCase(); 24007 var jpop = $('.glopop, #simplemodal-container'); 24008 24009 if (open2 == 'commission-price') { 24010 jpop.find('.adjust-total-service-price:first .help-icon4').click(); //GLO.Provider.Membership.openServicePriceHelp(this); //$('#pop-member-view').closest('.glopop') 24011 return; 24012 } else if (!UTIL.isEmpty(highlight)) { 24013 var jhigh = jpop.find('#' + highlight); 24014 } else if (!UTIL.isEmpty(highlightClass)) { 24015 var jhigh = jpop.find('.' + highlightClass); 24016 } 24017 24018 if (jhigh && jhigh.length) { 24019 UI.highlight(jhigh, 300, 6000, true); 24020 } 24021 } 24022 24023 function _initShortcut() { 24024 $(document).keydown(function(event) { 24025 if (event.altKey) { 24026 if (event.which === 82) { //R: refresh report 24027 GLO.Provider.Membership.searchReport(); 24028 } 24029 } 24030 }); 24031 $(window).bind('keypress', function(e) { 24032 if (e.altKey) { 24033 if (e.which === 82) { //R: refresh report 24034 e.preventDefault(); 24035 } 24036 } 24037 }); 24038 } 24039 24040 function _initTable(jtbody) { 24041 var rowCSS = null, trs = jtbody.find('> tr'); 24042 24043 for (var i=1; i < trs.length; i++) { 24044 var tr = trs.eq(i); 24045 24046 if (tr.hasClass('membership-type')) { 24047 if (!UTIL.isEmpty(rowCSS)) { 24048 rowCSS = null; 24049 } else { 24050 rowCSS = 'odd-row-membership'; 24051 } 24052 } 24053 24054 if (!UTIL.isEmpty(rowCSS)) { 24055 tr.addClass(rowCSS); 24056 } 24057 } 24058 24059 _updateMembershipCount(); 24060 } 24061 24062 function _updateMembershipCount() { 24063 var cnt = $('#membership-list').find('tr.membership-type').length; 24064 var msg = UTIL.pluralLabel(cnt, 'membership'); 24065 24066 $('#member-header-info #membership-count').text(msg); 24067 } 24068 24069 _cMembership.openSell = function(event) { 24070 var htm = '<div id="pop-sell-membership">'; 24071 var dd = '<div id="pop-sell-membership-select"> <label for="Membership_id">Select Membership</label>' + _cMembership.getMembershipDropDown() + '</div>'; 24072 24073 /* toDo: add start date 24074 var dtStart = new Date().toGloDate(); 24075 var htmStartInput = '<input type="text" id="Membership_Start_dt" pattern="[0-9]*" value="' + dtStart + '" onclick="GLO.UI.displayDatePicker(this)"/>'; 24076 var htmStart = '<div id="pop-sell-membership-start"> <label for="Membership_Start_dt">Start Date</label>' + htmStartInput + '</div>'; 24077 */ 24078 24079 htm += dd + '</div>'; 24080 var jpop = GLO.Popup.Custom.openSimple(htm, 'Select Membership'); 24081 jpop.find('#Membership_id').change(GLO.Provider.Membership.openSell2); 24082 GLO.Popup.Custom.singleButton(jpop, 'Close'); 24083 } 24084 24085 _cMembership.openSell2 = function() { 24086 var jpop = $('#pop-sell-membership-select').closest('.glopop'); 24087 var membershipId = jpop.find('#Membership_id').val(); 24088 var membership = GLO.ClientProfile.getMembership(membershipId); 24089 24090 GLO.Popup.close(jpop); 24091 24092 UserPortal.Price.quit(); 24093 UserPortal.Price.inventoryXml = '<li amount_nr="1" tax_rate_pct="0" cost_mn="0" vendor_id="" product_line_id="" vendor_merchant_id=""' 24094 + ' price_mn="' + membership.price + '" employee_price_mn="' + membership.price + '" membership_id="' + membershipId + '"' 24095 + ' inventory_id="' + membership.inventory_id + '" inventory_vc="' + UTIL.removeBadCharacters(UTIL.replaceQuotes(membership.name)) + '"/>'; 24096 24097 UserPortal.Price.open(null, true, null, false); 24098 var jPricePop = $('#appt-price-popup').closest('.glopop'); 24099 24100 if (UTIL.coalesceMoney(membership.price) === 0) { 24101 jPricePop.find('.booking-product-price').click(); 24102 } else { 24103 jPricePop.find('#purchaser-autocomplete-input').click(); 24104 } 24105 } 24106 24107 _cMembership.openPeriodSummary = function() {
24108 var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr'); 24109 var membershipId = tr.attr('membership_id'), iid = tr.attr('inventory_id'), cid = tr.attr('client_id'); 24110 var cname = tr.find('td.membership-column-client > a').text(); 24111 24112 _cMembership.openPeriodSummary2(membershipId, iid, cid, cname); 24113 } 24114 24115 function _getMember(tr) { //= gets price of next member payment (or balance due if current period) + other details for next member payment 24116 var membershipId = tr.attr('membership_id'), nextMembershipId = tr.attr('next_membership_id'); 24117 var balance = UTIL.coalesceMoney(tr.attr('balance_mn')), billPeriod = tr.attr('billing_period_cd'); 24118 24119 var membership = GLO.ClientProfile.getMembership(membershipId); 24120 var customPrice = tr.attr('custom_price_mn'); 24121 var price = UTIL.coalesceMoney(customPrice, membership.price); 24122 var hasCustomBillPeriod = (UTIL.coalesceInt(billPeriod, membership.period) != membership.period); 24123 24124 var dtNextBill = tr.attr('next_bill_dt'); 24125 var periodEnd = new Date(tr.attr('period_end_dt')), today = new Date(new Date().toGloDate()); 24126 var isNewMemberPeriod = (today >= periodEnd); 24127 24128 if (UTIL.isDate(dtNextBill)) { 24129 dtNextBill = new Date(dtNextBill); 24130 24131 if (hasCustomBillPeriod && periodEnd > dtNextBill) { 24132 isNewMemberPeriod = false; //= next billing period is not a new member period. 24133 } 24134 } else { 24135 dtNextBill = new Date(periodEnd).addDays(1); 24136 } 24137 24138 if (!UTIL.isEmpty(nextMembershipId) && isNewMemberPeriod) { 24139 var membership = GLO.ClientProfile.getMembership(nextMembershipId); 24140 price = membership.price; 24141 } else if (hasCustomBillPeriod) { 24142 var memberMonthCount = _cMembership.getPeriodMonthCount(membership.period); 24143 //var billMonthCount = _cMembership.getPeriodMonthCount(billPeriod); 24144 24145 /* just use listed price (much simplier) 24146 if (memberMonthCount > billMonthCount) { //= always use price (unless member period > billing period) 24147 price = UTIL.coalesceMoney(price * billMonthCount/memberMonthCount, true, false, true); 24148 } 24149 */ 24150 } 24151 24152 var due = _getDueAmount(price, balance, dtNextBill, isNewMemberPeriod); 24153 var member = { 24154 "price_mn": price, "due_mn": due, "balance_mn": balance, "is_new_member_period": isNewMemberPeriod, "is_custom_bill_period": hasCustomBillPeriod 24155 , "bill_dt": dtNextBill, "membership": membership 24156 }; 24157 24158 if (!UTIL.isEmpty(customPrice) && UTIL.isEmpty(nextMembershipId)) { member.custom_price_mn = customPrice; } 24159 24160 if (isNewMemberPeriod) { 24161 member.new_period_start_dt = new Date(periodEnd).addDays(1); 24162 member.new_period_end_dt = _cMembership.getPeriodEnd(membership.period, member.new_period_start_dt); 24163 24164 if (new Date() > member.new_period_end_dt) { 24165 member.new_period_start_dt = new Date(); 24166 member.new_period_end_dt = _cMembership.getPeriodEnd(membership.period, member.new_period_start_dt); 24167 } 24168 24169 /* if (UTIL.isEmpty(nextMembershipId) && hasCustomBillPeriod) { 24170 member.next_bill_dt = new Date(new Date(member.new_period_start_dt).setMonth(member.new_period_start_dt.getMonth() + billMonthCount)); 24171 } else { 24172 member.next_bill_dt = new Date(member.new_period_end_dt).addDays(1); 24173 } */ 24174 //} else if (hasCustomBillPeriod) { 24175 // member.next_bill_dt = new Date(new Date(dtNextBill).setMonth(dtNextBill.getMonth() + billMonthCount)); 24176 } 24177 24178 member.card_on_file_fl = UTIL.parseBool(tr.attr('card_on_file_fl')); 24179 member.auto_bill_fl = UTIL.parseBool(tr.find('.is-auto-bill').length); 24180 return member; 24181 } 24182 24183 function _getDueAmount(price, balance, dtNextBill, isNewMemberPeriod) { 24184 if (balance < 0 && !isNewMemberPeriod) { 24185 return UTIL.coalesceMoney(-balance); 24186 } else if (balance - price < 0) { 24187 if (balance < 0 && dtNextBill > new Date()) { 24188 return UTIL.coalesceMoney(-balance); 24189 } else { 24190 return UTIL.coalesceMoney(price - balance); 24191 } 24192 } else if (price > 0) { 24193 return 0; 24194 } 24195 } 24196 24197 _cMembership.changeWeb = function() { 24198 var jpop = $('#pop-membership-edit').closest('.glopop'); 24199 var webAccess = jpop.find('#Web_cd').val(); 24200 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 24201 24202 if (webAccess == 10) { 24203 if (mt > 24) { 24204 var htm = '<div id="pop-warn-merchant-required">Selling Memberships Online Requires Merchant Account</div>'; 24205 GLO.Popup.Warning.open(htm, 'Merchant Account Required'); 24206 jpop.find('#Web_cd').val(20); 24207 } 24208 } 24209 } 24210 24211 /* _cMembership.openPayMembershipFromCellSummary = function() {
24212 var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr'); 24213 } */ 24214 _cMembership.openPayMembershipFromPopup = function(membershipId, iid, cid, cname) { 24215 var tr = $('#membership-report').find('tr[client_id="' + cid + '"]'); 24216 var jpop = $('#pop-member-view').closest('.glopop'); 24217 var customPrice = null; 24218 24219 if (jpop.length) { 24220 jpop.find(':focus').blur(); 24221 24222 if (jpop.find('.btnSave > a.unsaved').length) { 24223 jpop.find('.btnSave > a').removeClass('unsaved'); 24224 24225 var fnYes = function() { jpop.find('.btnSave > a').click(); }; 24226 var fnNo = function() { jpop.find('#btnPayMembership > a').click(); }; 24227 24228 GLO.Popup.Confirm.open('Save Changes to Member Profile?', 'Un-Saved Changes', fnYes, fnNo); 24229 return; 24230 } else { 24231 var periodPrice = jpop.find('#Period_Price_mn').val(); 24232 var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val()); 24233 24234 if (UTIL.isNumber(periodPrice, true) && periodPrice != GLO.ClientProfile.getMembership(membershipId).price_mn) { 24235 customPrice = periodPrice; 24236 } 24237 24238 if (balance != 0) { 24239 var dtStart = jpop.find('#Period_Start_dt').val(); 24240 var dtEnd = jpop.find('#Period_End_dt').val(); 24241 24242 if (UTIL.isDate(dtStart) && UTIL.isDate(dtEnd) && new Date() < new Date(dtEnd)) { 24243 customPrice = -balance; 24244 } else { 24245 customPrice = customPrice - balance; 24246 } 24247 } 24248 } 24249 24250 GLO.Popup.close(jpop); 24251 GLO.Popup.Processing.open('<div id="pop-procesing-price-wait">Creating Membership Purchase Ticket...</div>', 'Creating Ticket'); 24252 } 24253 24254 setTimeout(function() { //= make async so UI closes popup (see above code) immediately 24255 if (tr.length === 1 && tr.attr('membership_id') == membershipId) { 24256 _cMembership.openPayMembership(tr); 24257 } else { 24258 _cMembership.openPayMembership2(membershipId, iid, cid, cname, customPrice); 24259 } 24260 }, 90); 24261 } 24262 _cMembership.openPayMembership = function(tr) { 24263 var membershipId = tr.attr('membership_id'), iid = tr.attr('inventory_id'), cid = tr.attr('client_id'); 24264 var cname = tr.find('td.membership-column-client > a').text(); 24265 var member = _getMember(tr); 24266 24267 if (member.due_mn > 0) { 24268 var customPrice = member.due_mn; 24269 } else { 24270 var customPrice = member.price_mn; 24271 } 24272 24273 _cMembership.openPayMembership2(membershipId, iid, cid, cname, customPrice); 24274 } 24275 _cMembership.openPayMembership2 = function(membershipId, iid, cid, cname, customPrice, startDate) { 24276 var membership = GLO.ClientProfile.getMembership(membershipId); 24277 var price = UTIL.coalesceMoney(customPrice, membership.price); 24278 var payInfo = $('<h2 client_id="' + cid + '" client_vc="' + cname + '"></h2>'); 24279 24280 if (UTIL.isEmpty(iid)) { 24281 iid = membership.inventory_id; 24282 } 24283 24284 GLO.Popup.close($('#pop-member-pay-summary').closest('.glopop')); 24285 GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop')); 24286 24287 UserPortal.Price.quit(); 24288 UserPortal.Price.inventoryXml = '<li amount_nr="1" tax_rate_pct="0" cost_mn="0" vendor_id="" product_line_id="" vendor_merchant_id=""' 24289 + ' price_mn="' + price + '" employee_price_mn="' + price + '" membership_id="' + membershipId + '" membership_start_dt="' + UTIL.cleanString(startDate) + '"' 24290 + ' inventory_id="' + membership.inventory_id + '" inventory_vc="' + UTIL.removeBadCharacters(UTIL.replaceQuotes(membership.name)) + '"/>'; 24291 24292 UserPortal.Price.open(null, true, payInfo, false); 24293 var jPricePop = $('#appt-price-popup').closest('.glopop'); 24294 24295 if (UTIL.coalesceMoney(membership.price) === 0) { 24296 jPricePop.find('.booking-product-price').focus(); 24297 } 24298 } 24299 24300 _cMembership.searchReport = function() { 24301 var qs = '', jhead = $('#report-main .report-search-header'); 24302 var mid = jhead.find('#Membership_id').val(); 24303 var status = jhead.find('#Membership_Status_cd').val(); 24304 var sfilter = GLO.Uri.url('sfilter'); //$('#staff-filter').val(); 24305 24306 var start = jhead.find('#Member_Start_dt').val(); 24307 var end = jhead.find('#Member_End_dt').val(); 24308 24309 if (!UTIL.isEmpty(mid)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'membership=' + mid); } 24310 if (!UTIL.isEmpty(status)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'status=' + status); } 24311 if (!UTIL.isEmpty(sfilter)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'sfilter=' + sfilter); } 24312 24313 if (!UTIL.isEmpty(start)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'start=' + start); } 24314 if (!UTIL.isEmpty(end)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'end=' + end); } 24315 24316 var url = window.location.origin + window.location.pathname + qs; 24317 window.history.pushState('', '', url); 24318 24319 //if (title) { document.title = title; } 24320 24321 $('h2#membership-report-header .fa-refresh').click(); 24322 } 24323 24324 _cMembership.refreshReportOnEdit = function(button) { 24325 $('#membership-report-header').find('.fa-refresh').click(); 24326 } 24327 24328 _cMembership.refreshReport = function(button) { 24329 var jd = {}; 24330 button = $(button); 24331 24332 if (button.hasClass('fa-spin')) { 24333 return; 24334 //} else if (!GLO.Report.hasReportPassword(jd)) { 24335 // return; 24336 } else if (button.hasClass('fa')) { 24337 button.addClass('fa-spin'); 24338 } else { 24339 GLO.UI.Form.beginProcessing(button.parent()); 24340 } 24341 24342 GLO.UI.Form.beginProcessing($('.report-search-header-button .btnSearch')); 24343 24344 var jrpt = $('.report-container'), jTagFilter = $('#tag-filter-container'); 24345 var uri = GLO.Uri.addQueryKeyAndValue(location.href, 'ispartial=1'); 24346 var qs = GLO.Message.Bulk.getTagQueryString(jTagFilter); 24347 24348 _setMembershipReportOverview(); 24349 24350 var jqxhr = $.ajax({ "type": "POST", "url": uri + qs, "cache": false, "data": jd }) 24351 .success(function(data, textStatus, jqXHR) { 24352 button.removeClass('fa-spin'); 24353 GLO.UI.Form.resetProcessing(); 24354 24355 jrpt.html($(data).outerHTML()); 24356 _cMembership.initReport(true); 24357 }) 24358 .error(function(jqXHR, textStatus, errorThrown) { 24359 button.removeClass('fa-spin'); 24360 GLO.UI.Form.resetProcessing(); 24361 24362 var htm = '<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>'; 24363 jrpt.html(htm); 24364 }); 24365 } 24366 24367 function _setMembershipReportOverview() { 24368 var jhead = $('#bd-page .report-search-header'); 24369 var mstatus = jhead.find('#Membership_Status_cd'); 24370 //var sfilter = $('#staffFilter .hello-bar-label'); //cannot use because not on mobile 24371 var sids = GLO.Uri.query('sfilter'); 24372 var htm = ''; 24373 24374 if (!UTIL.isEmpty(sids)) { 24375 var sfilter = GLO.Report.getStaffHelloLabel(sids); 24376 24377 if (!UTIL.isEmpty(sfilter)) { 24378 htm = '<p>Members with an appointment with one of these staff members: <small style="letter-spacing: 0;">' + sfilter + '</small></p>'; 24379 } 24380 } 24381 24382 if (!UTIL.isEmpty(mstatus.val())) { 24383 if (!UTIL.isEmpty(htm)) { 24384 htm += '<p style="padding-left: 8px; padding-bottom: 16px;">and have'; 24385 } else { 24386 htm = '<p>Members with'; 24387 } 24388 24389 htm += ' a membership status of ' + mstatus.find(':selected').text() + '</p>'; 24390 24391 //if (mstatus.val() == 0) { htm += '<div margin-top: "8px;">New membership status</div>'; } 24392 } 24393 24394 $('#membership-report-overview').html(htm); 24395 } 24396 24397 _cMembership.openEditType = function(event) { 24398 if (!GLO.Info.isGold()) { 24399 GLO.Popup.Warning.open('Managing memberships requires the Gold Package', 'Gold Package Only'); 24400 return; 24401 } 24402 24403 var tr = $(this).closest('tr'); 24404 24405 if (tr.hasClass('membership-type')) { 24406 var memberId = tr.attr('membership_id'); 24407 var strFnRemove = 'GLO.Provider.Membership.remove()'; 24408 var h1 = 'Edit Membership'; 24409 } else { 24410 var tr = null, memberId = null, strFnRemove = null, h1 = 'Create Membership'; 24411 } 24412 24413 var jpop = _openPopup(_popEditType, h1, GLO.Provider.Membership.save, strFnRemove); 24414 24415 if (tr) { 24416 var jdesc = tr.find('.column-member-description'); 24417 var hasEmailReminderDay = false, emailReminderDay = tr.attr('email_reminder_day_sr'), webAccess = tr.attr('web_cd'); 24418 24419 if (UTIL.coalesceInt(emailReminderDay, 0) > 0) { hasEmailReminderDay = true; } 24420 24421 jpop.attr('membership_id', tr.attr('membership_id')); 24422 jpop.find('#Membership_Name_vc').val(tr.find('.column-member-name').text());
24423 jpop.find('#Membership_Price_mn').val(UTIL.replaceAll(tr.find('.column-member-price').text(), '$', '')); 24424 jpop.find('#Membership_Period_cd').val(tr.attr('membership_period_cd')); 24425 jpop.find('#Billing_Period_cd').val(tr.attr('billing_period_cd')); 24426 24427 jpop.find('#Auto_Billing_fl').prop('checked', tr.find('.column-member-auto-bill .is-auto-bill').length); 24428 jpop.find('#Email_Reminder_fl').prop('checked', hasEmailReminderDay); 24429 jpop.find('#Email_Reminder_Day_sr').val(emailReminderDay); 24430 jpop.find('#Membership_Description_vc').val(UTIL.coalesce(jdesc.attr('title'), jdesc.text())); 24431 24432 if (webAccess) { 24433 jpop.find('#Web_cd').val(webAccess); 24434 } 24435 } else { 24436 jpop.find('#Auto_Billing_fl').prop('checked', true); 24437 } 24438 } 24439 24440 _cMembership.openEditService = function(event, membershipId) { 24441 var tr = $(this); 24442 24443 if (tr.hasClass('membership-type-service')) { 24444 membershipId = tr.attr('membership_id'); 24445 } else { 24446 tr = null; 24447 } 24448 24449 if (tr) { 24450 var membershipServiceId = tr.attr('membership_service_id'); 24451 var limit = tr.attr('limit_nr'); 24452 var rolloverUnused = tr.attr('rollover_unused_pct'); 24453 24454 var discountMoney = tr.attr('discount_mn'), discountPercent = tr.attr('discount_pct'); 24455 var svcFilter = tr.attr('service_id'); 24456 24457 if (UTIL.isEmpty(svcFilter)) { svcFilter = 'sg' + tr.attr('service_group_id'); } 24458 24459 var isRequireMembership = UTIL.parseBool(tr.attr('require_membership_fl')); 24460 var commissionPrice = tr.attr('price_mn'); 24461 } else { 24462 var membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent; 24463 var isRequireMembership = false, commissionPrice = null; 24464 } 24465 24466 var jpop = _cMembership.openEditService2(null, membershipId, membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent, commissionPrice); 24467 jpop.find('#Require_Membership_fl').prop('checked', isRequireMembership); 24468 } 24469 _cMembership.openAddCustomService = function(clientId, membershipId) { 24470 if (!UTIL.isEmpty(_popEditTypeService)) { 24471 _cMembership.openAddCustomService2(clientId, membershipId); 24472 } else { 24473 _cMembership.retrieveAddCustomServiceHtm(clientId, membershipId); 24474 } 24475 } 24476 _cMembership.retrieveAddCustomServiceHtm = function(clientId, membershipId) { 24477 var ojprocessing = GLO.Popup.Processing.open('Opening Add Custom Service Popup....', 'Custom Member Service'); 24478
24479 var uri = GLO.Link.WebsiteDomain + 'membership/AddMembershipServicePopup'; 24480 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 24481 .success(function(data, textStatus, jqXHR) { 24482 ojprocessing.close(); 24483 24484 if ($(data).attr('id') == 'pop-membership-service-edit') { 24485 _popEditTypeService = data; 24486 } else if ($(data).find('#pop-membership-service-edit').length) { 24487 _popEditTypeService = $(data).find('#pop-membership-service-edit').outerHTML(); 24488 } else { 24489 GLO.Popup.Warning.open('Unable to Add Custom Service to this Member\'s Profile', 'Member Custom Service'); 24490 return; 24491 } 24492 24493 _cMembership.openAddCustomService2(clientId, membershipId); 24494 }) 24495 .error(function(jqXHR, textStatus, errorThrown) { }); 24496 } 24497 _cMembership.openAddCustomService2 = function(clientId, membershipId) { 24498 var jpopAddCustomSvc = _cMembership.openEditService2(clientId, membershipId).attr('client_id', clientId); 24499 var jpopMember = $('#pop-member-view').closest('.glopop'); 24500 24501 var clientName = jpopMember.find('.client-name-link').text(); 24502 var spanStart = '<span style="display: inline-block; white-space: nowrap; margin-right: 12px; color: white;">'; 24503 24504 if (!UTIL.isEmpty(clientName)) { 24505 jpopAddCustomSvc.find('h1').html(spanStart + 'Add Custom Service</span>' + spanStart + clientName + ' Membership</span>'); 24506 jpopAddCustomSvc.find('#pop-mse-require').remove(); //removes row for 'Require_Membership_fl' 24507 } 24508 } 24509 _cMembership.openEditService2 = function(clientId, membershipId, membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent, commissionPrice) { 24510 if (!UTIL.isEmpty(clientId)) { 24511 var strFnRemove = null, h1 = 'Add Custom Service'; 24512 } else if (!UTIL.isEmpty(membershipServiceId)) { 24513 var strFnRemove = 'GLO.Provider.Membership.removeService()'; 24514 var h1 = 'Edit Membership Service'; 24515 } else { 24516 var strFnRemove = null, h1 = 'Add Membership Service'; 24517 } 24518 24519 var jpop = _openPopup(_popEditTypeService, h1, GLO.Provider.Membership.saveService, strFnRemove).attr('membership_id', membershipId); 24520 24521 jpop.attr('membership_service_id', membershipServiceId); 24522 jpop.find('.Service_Filter').val(svcFilter); 24523 jpop.find('#Limit_nr').val(limit); 24524 jpop.find('#Rollover_Unused_pct').val(rolloverUnused); 24525 jpop.find('#Service_Commission_Price_mn').val(UTIL.displayMoney(commissionPrice, true, false, true)); 24526 24527 if (!UTIL.isEmpty(discountMoney)) { 24528 jpop.find('#Discount_Money_fl').prop('checked', true); 24529 jpop.find('#Discount_mn').val(discountMoney); 24530 } else if (!UTIL.isEmpty(discountPercent)) { 24531 jpop.find('#Discount_Percent_fl').prop('checked', true); 24532 jpop.find('#Discount_pct').val(discountPercent); 24533 } else { 24534 jpop.find('#Free_fl').prop('checked', true); 24535 } 24536 24537 jpop.find('#Discount_Money_fl').click(function() { UI.changeFocus(this, 'Discount_mn'); }); 24538 jpop.find('#Discount_Percent_fl').click(function() { UI.changeFocus(this, 'Discount_pct'); }); 24539 24540 jpop.find('#Discount_mn').change(function() { UI.markCheckbox(this, 'Discount_Money_fl'); }).change(); 24541 jpop.find('#Discount_pct').change(function() { UI.markCheckbox(this, 'Discount_Percent_fl'); }).change(); 24542 return jpop; 24543 } 24544 function _openPopup(htm, h1, fnSave, strFnDelete) { 24545 var ojpop = GLO.Popup.Custom.openSimple(htm, h1, fnSave, null, true); 24546 var jpop = ojpop.getPopup(); 24547 var btnSave = jpop.find('.btnSave'); 24548 24549 jpop.find(':text, select').change(function() { UI.buttonDisplayChange(btnSave); }); 24550 jpop.find(':text').keyup(function() { UI.buttonDisplayChange(btnSave); }); 24551 24552 jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "letter-spacing": "1px", "font-size": "larger" }).find('>a').text('Close'); 24553 24554 if (!UTIL.isEmpty(strFnDelete)) { 24555 var btnDelete = '<span class="btnDelete" style="position: absolute; left: 8px; margin: 0;">
24555<a onclick="' + strFnDelete + '">Delete</a></span>'; 24556 jpop.find('.pop-buttons').prepend(btnDelete); 24557 } 24558 24559 if (innerWidth < 640) { 24560 jpop.css({ "width": "98%" }); 24561 } else { 24562 jpop.css({ "width": "600px" }); 24563 } 24564 24565 ojpop.realign(); 24566 return jpop; 24567 } 24568 24569 _cMembership.getIcon = function(membershipId, cid, cname) { 24570 var arr = GLO.Data.provider.MembershipList; 24571 24572 for (var i=0; i < arr.length; i++) { 24573 if (arr[i].id == membershipId) { 24574 var css = '', nm = arr[i].name + ' (' + _cMembership.getPeriodName(arr[i].period) + ')'; 24575 24576 if (!UTIL.isEmpty(arr[i].color)) { 24577 css = 'color: ' + arr[i].color + ';'; 24578 } 24579 24580 var fn = 'GLO.Provider.Membership.Client.openViewMemberFromTicket(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)'; 24581 var icon = '<span onclick="' + fn + '" style="' + css + '">' + UTIL.coalesce(arr[i].letter, 'M') + '</span>'; 24582 var cssClass = 'client-membership-icon' + UserPortal.Price.Discount.getMembershipIconClass(cid); 24583 24584 return '<span class="' + cssClass + '" membership_id="' + membershipId + '" title="' + nm + '">' + icon + '</span>'; 24585 } 24586 } 24587 24588 return {}; 24589 } 24590 _cMembership.getName = function(membershipId, includePeriod) { 24591 var arr = GLO.Data.provider.MembershipList; 24592 24593 for (var i=0; i < arr.length; i++) { 24594 if (arr[i].id == membershipId) { 24595 var name = arr[i].name; 24596 24597 if (includePeriod) { 24598 name += ' <small style="letter-spacing: 0; font-weight: normal;">(' + _cMembership.getPeriodName(arr[i].period) + ')</small>'; 24599 } 24600 24601 return name 24602 } 24603 } 24604 24605 return ''; 24606 } 24607 _cMembership.getPeriodNameCount = function(period, count) { 24608 var nm; 24609 24610 if (period == 10) { 24611 nm = 'day'; 24612 } else if (period == 20) { 24613 nm = 'week'; 24614 } else if (period == 30 || period == 40 || period == 50 || period == 60) { 24615 nm = 'month'; 24616 24617 if (period == 40) { 24618 count = count * 2; 24619 } else if (period == 50) { 24620 count = count * 3; 24621 } else if (period == 60) { 24622 count = count * 6; 24623 } 24624 } else if (period == 70) { 24625 nm = 'year'; 24626 } else if (period == 100) { 24627 nm = 'lifetime'; 24628 } 24629 24630 return UTIL.pluralLabel(count, nm); 24631 } 24632 _cMembership.getPeriodName = function(period) { 24633 if (period == 10) { return 'Daily'; } 24634 if (period == 20) { return 'Weekly'; } 24635 if (period == 30) { return 'Monthly'; } 24636 if (period == 40) { return 'Bi-Monthly'; } 24637 if (period == 50) { return 'Quarterly'; } 24638 if (period == 60) { return 'Semi-Annual'; } 24639 if (period == 70) { return 'Annual'; } 24640 if (period == 100) { return 'Lifetime'; } 24641 return ''; 24642 } 24643 _cMembership.getPeriodMonthCount = function(period) { 24644 if (period == 30) { return 1; } 24645 if (period == 40) { return 2; } 24646 if (period == 50) { return 3; } 24647 if (period == 60) { return 6; } 24648 if (period == 70) { return 12; } 24649 24650 return 0; 24651 } 24652 _cMembership.getPeriodEnd = function(period, dtStart) { 24653 if (period == 10) { 24654 return new Date(dtStart).addDays(1); 24655 } else if (period == 20) { 24656 return new Date(dtStart).addDays(7); 24657 } 24658 24659 var months = _cMembership.getPeriodMonthCount(period); 24660 return new Date(new Date(dtStart).setMonth(dtStart.getMonth() + months)); 24661 } 24662 24663 _cMembership.switchToChangeStatus = function(element, event) { 24664 var dd = '<select id="Member_Status_cd">' 24665 + '<option value="0">New</option>' 24666 + '<option value="50">Active</option>' 24667 + '<option value="30">Unpaid</option>' 24668 + '<option value="40">Partial Payment</option>' 24669 + '<option value="500">Payment Issue</option>' 24670 + '<option value="900">Inactive</option>' 24671 + '</select>'; 24672 24673 var jelement = $(element); 24674 var mstatus = jelement.attr('member_status_cd'); 24675 var jparent = jelement.parent(); 24676 24677 jelement.replaceWith(dd); 24678 jparent.find('#Member_Status_cd').val(mstatus); 24679 } 24680 24681 _cMembership.getMembershipDropDown = function() { 24682 var dd = '<select id="Membership_id"> <option value=""></option>'; 24683 var arr = GLO.Data.provider.MembershipList; 24684 24685 for (var i=0; i < arr.length; i++) { 24686 dd += '<option value="' + arr[i].id + '" period_cd="' + arr[i].period + '" title="' + arr[i].description + '">' + arr[i].name + '</option>'; 24687 } 24688 24689 return dd + '</select>'; 24690 } 24691 24692 function _saveIsValid(jcontainer) { 24693 var fnSave = function() { GLO.Provider.Membership.save(true); } 24694 24695 if (false) { 24696 var fnAction = function() { 24697 GLO.Popup.close($('#pop-confirm-membership-save').closest('.glopop')); 24698 GLO.Provider.Membership.save(); 24699 } 24700 24701 var htm = '<div id="pop-confirm-membership-save" style="margin-top: 8px;">Do you want to Save Membership Changes?</div>'; 24702 GLO.Popup.Confirm.open(htm, 'Save Membership?', fnAction, fnSave); 24703 return false; 24704 } 24705 24706 return true; 24707 } 24708 24709 _cMembership.remove = function() { 24710 var jpop = $('#pop-membership-edit').closest('.glopop'); 24711 var msg = '<p style="color: rgb(240,0,0);">Are you sure you want to delete the membership</p>'; 24712 var membershipName = '<p style="text-align: center; font-size: larger;">' + jpop.find('#Membership_Name_vc').val() + '</p>'; 24713 var htm = '<div id="pop-confirm-member-service-remove" style="margin-top: 8px; font-weight: bold;">' + msg + membershipName + '</div>'; 24714 24715 GLO.Popup.Confirm.open(htm, 'Confirm Delete Membership', GLO.Provider.Membership.removeConfirmed); 24716 } 24717 24718 _cMembership.removeConfirmed = function() { 24719 var jpop = $('#pop-membership-edit').closest('.glopop'); 24720 var membershipId = UTIL.cleanString(jpop.attr('membership_id')); 24721 var jbtn = jpop.find('.btnDelete'); 24722 var uri = GLO.Link.WebsiteDomain + 'membership/delete?membership=' + membershipId; 24723 24724 GLO.UI.Form.beginProcessing(jbtn); 24725
24726 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 24727 .success(function(data, textStatus, jqXHR) { 24728 GLO.Popup.close(jpop); //GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 24729 var tr = $('#membership-list tr[membership_id="' + membershipId + '"]'); 24730 var trAddSvcBtn = tr.next(); 24731 24732 tr.remove(); 24733 24734 if (trAddSvcBtn.hasClass('membership-type-service-add')) { 24735 trAddSvcBtn.remove(); 24736 } 24737 24738 var jtbody = $('table#membership-list').find('tbody'); 24739 jtbody.find('tr.odd-row-membership').removeClass('odd-row-membership'); 24740 _initTable(jtbody); 24741 }) 24742 .error(function(jqXHR, textStatus, errorThrown) { 24743 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 24744 }); 24745 } 24746 24747 _cMembership.removeService = function() { 24748 var jpop = $('#pop-membership-service-edit').closest('.glopop'); 24749 var membershipId = jpop.attr('membership_id'); 24750 var membershipName = GLO.ClientProfile.getMembership(membershipId).name; 24751 var htm = '<div id="pop-confirm-member-service-remove">' + 'Are you sure you want to remove this service from the membership ' + membershipName + '?</div>'; 24752 24753 GLO.Popup.Confirm.open(htm, 'Confirm Remove Membership Service', GLO.Provider.Membership.removeServiceConfirmed); 24754 } 24755 24756 _cMembership.removeServiceConfirmed = function() { 24757 var jpop = $('#pop-membership-service-edit').closest('.glopop'); 24758 var membershipId = UTIL.cleanString(jpop.attr('membership_id')), membershipServiceId = UTIL.cleanString(jpop.attr('membership_service_id')); 24759 var jbtn = jpop.find('.btnDelete'); 24760 var uri = GLO.Link.WebsiteDomain + 'membership/deleteService?membership=' + membershipId + '&msid=' + membershipServiceId; 24761 24762 GLO.UI.Form.beginProcessing(jbtn); 24763 24764 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 24765 .success(function(data, textStatus, jqXHR) { 24766 GLO.Popup.close(jpop); 24767 $('#membership-list tr.membership-type-service[membership_service_id="' + membershipServiceId + '"]').remove(); 24768 }) 24769 .error(function(jqXHR, textStatus, errorThrown) { 24770 GLO.UI.Form.resetProcessing(); 24771 }); 24772 } 24773 24774 _cMembership.changeEmailRemindDays = function() { 24775 var j = $('#pop-membership-edit-reminder'); 24776 var jhas = j.find('#Email_Reminder_fl');
24777 var days = UTIL.coalesceInt(j.find('#Email_Reminder_Day_sr').val(), 0); 24778 24779 if (days > 0) { 24780 jhas.prop('checked', true); 24781 } else { 24782 jhas.prop('checked', false); 24783 } 24784 } 24785 _cMembership.save = function() { 24786 var jpop = $('#pop-membership-edit').closest('.glopop'); 24787 var membershipId = UTIL.cleanString(jpop.attr('membership_id')); 24788 var period = jpop.find('#Membership_Period_cd').val(), billPeriod = jpop.find('#Billing_Period_cd').val(); 24789 var price = UTIL.coalesceMoney(jpop.find('#Membership_Price_mn').val()); 24790 var name = UTIL.htmlEncode(jpop.find('#Membership_Name_vc').val()), description = UTIL.htmlEncode(jpop.find('#Membership_Description_vc').val()); 24791 var webAccess = jpop.find('#Web_cd').val(); 24792 24793 var uri = GLO.Link.WebsiteDomain + 'membership/save?membership=' + membershipId + '&period=' + period + '&price=' + price; 24794 var jbtn = jpop.find('.btnSave'); 24795 var jd = { "name": name, "description": description, "web": webAccess }; 24796 24797 if (UTIL.isEmpty(period)) { 24798 GLO.Popup.Warning.open('Please Enter a Membership Period', 'Membership Period Required', function() { jpop.find('#Membership_Period_cd').focus(); }); 24799 return; 24800 } 24801 24802 if (UTIL.parseBool(jpop.find('#Auto_Billing_fl').prop('checked'))) { uri += '&autobill=1'; } 24803 if (!UTIL.isEmpty(billPeriod)) { uri += '&billperiod=' + billPeriod; } 24804 24805 if (jpop.find('#Email_Reminder_fl').prop('checked')) { 24806 jd.emailremind = jpop.find('#Email_Reminder_Day_sr').val(); 24807 } 24808 24809 GLO.UI.Form.beginProcessing(jbtn); 24810 24811 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 24812 .success(function(data, textStatus, jqXHR) { 24813 GLO.Popup.close(jpop); //GLO.UI.Form.resetProcessing(); 24814 var jtbody = $('#membership-list').removeClass('hide').find('tbody'); 24815 24816 if (!UTIL.isEmpty(membershipId)) { 24817 jtbody.find('tr.membership-type-service[membership_id="' + membershipId + '"]').remove(); 24818 jtbody.find('tr.membership-type[membership_id="' + membershipId + '"]').replaceWith(data); 24819 } else { 24820 jtbody.append(data); 24821 } 24822 24823 _initTable(jtbody); 24824 }) 24825 .error(function(jqXHR, textStatus, errorThrown) { 24826 GLO.UI.Form.resetProcessing(); 24827 }); 24828 } 24829 24830 _cMembership.saveService = function() { 24831 var jpop = $('#pop-membership-service-edit').closest('.glopop'); 24832 var membershipId = UTIL.cleanString(jpop.attr('membership_id')), msid = UTIL.cleanString(jpop.attr('membership_service_id')), clientId = UTIL.cleanString(jpop.attr('client_id')); 24833 var limit = jpop.find('#Limit_nr').val(); 24834 var rolloverUnused = UTIL.cleanString(jpop.find('#Rollover_Unused_pct').val()); 24835 var jbtn = jpop.find('.btnSave'); 24836 24837 var discountMoney = '', discountPercent = '', sgid = '', svcid = '', isRequireMembership = 0; 24838 var svc = jpop.find('.Service_Filter').val(); 24839 var price = UTIL.coalesceMoney(jpop.find('#Service_Commission_Price_mn').val()); 24840 24841 if (!UTIL.isEmpty(svc)) { 24842 isRequireMembership = jpop.find('#Require_Membership_fl').prop('checked'); 24843 24844 if (svc.substring(0,2) === 'sg') { 24845 sgid = svc.substring(2); 24846 24847 if (false && isRequireMembership) { 24848 var htm = '<div style="text-align: center;">To require membership please select a service <span style="display: block; white-space: nowrap;">(not a group of services)</span></div>'; 24849 GLO.Popup.Warning.open(htm, 'Service Not Selected'); 24850 return; //isRequireMembership = 0; 24851 } 24852 } else { 24853 svcid = svc; 24854 sgid = UserPortal.getServiceGroupId(svcid); 24855 } 24856 } 24857 24858 if (jpop.find('#Discount_Money_fl').prop('checked')) { 24859 discountMoney = jpop.find('#Discount_mn').val(); 24860 } else if (jpop.find('#Discount_Percent_fl').prop('checked')) { 24861 discountPercent = jpop.find('#Discount_pct').val(); 24862 } else if (jpop.find('#Free_fl').prop('checked')) { 24863 discountPercent = 100; 24864 } 24865 24866 var uri = GLO.Link.WebsiteDomain + 'membership/SaveService?membership=' + membershipId + '&msid=' + msid + '&client=' + clientId 24867 + '&limit=' + limit + '&sgid=' + sgid + '&svcid=' + svcid + '&isrequire=' + isRequireMembership 24868 + '&money=' + discountMoney + '&percent=' + discountPercent + '&price=' + price + '&rolloverUnused=' + rolloverUnused; 24869 24870 GLO.UI.Form.beginProcessing(jbtn); 24871
24872 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} }) 24873 .success(function(data, textStatus, jqXHR) { 24874 GLO.Popup.close(jpop); 24875 24876 if (_reloadMemberProfile(clientId, 'with new custom member service')) { 24877 return; 24878 } 24879 24880 var tbody = $('#membership-list').find('tbody'); 24881 var isOddRow = tbody.find('tr.membership-type[membership_id="' + membershipId + '"]').hasClass('odd-row-membership'); 24882 24883 if (isOddRow) { data = $(data).addClass('odd-row-membership'); } 24884 24885 if (!UTIL.isEmpty(msid)) { 24886 tbody.find('tr[membership_service_id="' + msid + '"]').replaceWith(data); 24887 } else { 24888 var tr = tbody.find('tr.membership-type-service[membership_id="' + membershipId + '"]:last'); 24889 24890 if (tr.length === 0) { 24891 tr = tbody.find('tr.membership-type[membership_id="' + membershipId + '"]'); 24892 } 24893 24894 tr.after(data); 24895 } 24896 }) 24897 .error(function(jqXHR, textStatus, errorThrown) { 24898 GLO.UI.Form.resetProcessing(); 24899 }); 24900 } 24901 function _reloadMemberProfile(clientId, msgCustom) { 24902 if (!UTIL.isEmpty(clientId)) { 24903 var jpopMember = $('#pop-member-view').closest('.glopop'); 24904 var clientName = jpopMember.find('.client-name-link').text(); 24905 24906 if (jpopMember.length) { 24907 var htm = '<div id="pop-loading-view-member">Updating ' + clientName + ' member profile ' + msgCustom + '...</div>'; 24908 24909 GLO.Popup.close(jpopMember); 24910 GLO.Popup.Processing.open(htm, 'Updating Member Profile'); 24911 GLO.Provider.Membership.Client.openViewMember(clientId, clientName); 24912 24913 return true; 24914 } 24915 } 24916 24917 return false; 24918 } 24919 _cMembership.validateMembershipPurchase = function(jPricePop) { 24920 if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) { return true; } 24921 24922 var jproduct = jPricePop.find('tr.appt-product-row .booking-product'); 24923 24924 if (jproduct.length === 0) { return true; } 24925 24926 var currentMembershipId = UserPortal.Price.Discount.getMembershipId(jPricePop); 24927 var newMembershipId = null; 24928 24929 for (var i=0; i < jproduct.length; i++) { 24930 var rowMembershipId = jproduct.eq(i).attr('membership_id'); 24931 24932 if (!UTIL.isEmpty(newMembershipId) && !UTIL.isEmpty(rowMembershipId) && newMembershipId != rowMembershipId) { 24933 var htm = '<div id="pop-membership-purchase-warning"><p>Cannot purchase more than one type of membership</p><p>A client can only have one membership at a time</p></div>'; 24934 GLO.Popup.Warning.open(htm, 'Multiple Memberships'); 24935 return false; 24936 } else { 24937 newMembershipId = rowMembershipId; 24938 } 24939 } 24940 24941 if (!UTIL.isEmpty(newMembershipId)) { 24942 var h2 = jPricePop.find('h2'); 24943 var userId = UTIL.coalesce(h2.attr('user_id'), h2.attr('client_id'), h2.find('.client-name-header-link').attr('cid')); 24944 24945 if (UTIL.isEmpty(userId) || String(userId).substring(0,1) === 'S') { 24946 var htm = '<div id="pop-membership-purchase-warning"><p>Client required on ticket to purchase membership</p></div>'; 24947 GLO.Popup.Warning.open(htm, 'Client Required'); 24948 return false; 24949 } 24950 } 24951 24952 //changing membership: if (UTIL.coalesce(newMembershipId, currentMembershipId, 0
24952) != UTIL.coalesce(currentMembershipId, newMembershipId, 0)) { } 24953 24954 return true; 24955 } 24956 24957 function _getPeriodDropDown(id) { 24958 var id = UTIL.coalesceString(id, 'Membership_Period_cd'); 24959 24960 return '<select id="' + id + '" name="' + id + '">' 24961 + '<option value="">(same as Membership period)</option>' 24962 + '<!-- <option value="20">Weekly</option> -->' 24963 + '<option value="30">Monthly</option>' 24964 + '<!-- <option value="40" title="Every Other Month">Bi-Monthly</option> -->' 24965 + '<option value="50" title="Every 3 Months">Quarterly</option>' 24966 + '<option value="60" title="Every 6 Months">Semi-Annual</option>' 24967 + '<option value="70">Yearly</option>' 24968 + '</select>'; 24969 } 24970 24971 _cMembership.openMemberOnlyServiceHelp = function(icon) { 24972 var msgMore = '<i class="narrow-text">(clients with this membership or another membership you setup that also includes this service)</i>'; 24973 var msg = '<p>When you check the box <b style="color: purple;">This Service Requires Membership</b> then this service can only be booked by clients who have a membership</p>' + msgMore + '</p>'; 24974 var htm = '<div id="pop-help-membership-service-rollover" style="margin-bottom: 8px;"><div>' + msg + '</div></div>'; 24975 var h1 = 'Member Only Services'; 24976 GLO.Popup.Info.open(htm, h1); 24977 } 24978 _cMembership.openServiceRolloverHelp = function(icon) { 24979 var msg1 = 'Rollover 0% to 100% of un-used services to the next membership period'; 24980 var htm = '<div id="pop-help-membership-service-rollover" style="margin-bottom: 8px;"><div>' + msg1 + '</div></div>'; 24981 var h1 = 'Rollover Un-Used Services'; 24982 GLO.Popup.Info.open(htm, h1); 24983 } 24984 _cMembership.openServicePriceHelp = function(icon) { 24985 var msg1 = 'Membership Service Commission Price'; 24986 var li1 = '<li>used when calculating staff commission</li>'; 24987 var li2 = '<li>the membership price does not have to equal the <span style="font-size: 100%; color: purple;">commission price</span></li>'; 24988 //var li3 = '<li>the <span style="font-size: 100%; color: purple;">membership service commission price</span> helps you account for costs</li>'; 24989 //var li4 = '<li>the membership price is what the client pays</li>'; 24990 //var li5 = '<li>helpful when breaking down how the membership should be priced</li>'; 24991 24992 var setupScreen = '<a style="letter-spacing: 0; font-size: 90%;" onclick=\'GLO.Report.Template2.goToReport("Membership Setup", "membership", event)\'>Membership Setup Screen</a>'; 24993 var rpt = '<a style="letter-spacing: 0; font-size: 90%;" onclick=\'GLO.Report.Template2.goToReport("Membership Report", "membership/report", event)\'>Membership Report</a>'; 24994 var msg3 = 'Set the default membership service commission price on the ' + setupScreen + ' and set for specific clients on the ' + rpt; 24995 var h1 = 'Membership Service Commission Price'; 24996 24997 var jPopMemberProfile = $('#pop-member-view').closest('.glopop'); 24998 24999 if (icon && jPopMemberProfile.length) { 25000 var jsvc = $(icon).closest('li.membership-service-row'); 25001 var svcName = jsvc.find('.membership-service-label').text(); 25002 var memberProfileServiceList = _openServicePriceHelp_MemberProfile(jsvc); 25003 25004 if (!UTIL.isEmpty(svcName)) { 25005 h1 = UTIL.cleanString(jPopMemberProfile.find('h1 .client-name-link').text() + ' ') + svcName + ' Commission Price'; 25006 } 25007 } else { 25008 var memberProfileServiceList = _openServicePriceHelp_MembershipSetup(); 25009 var svcName = $('#pop-membership-service-edit').closest('.glopop').find('.Service_Filter option:selected').text(); 25010 25011 if (!UTIL.isEmpty(svcName)) { 25012 h1 = svcName + ' Membership Commission Price'; 25013 } 25014 } 25015 25016 msg1 = '<div>' + msg1 + '<ul style="padding-left: 12px;">' + li1 + li2 + '</ul></div>'; // + li3 + li4 + li5 25017 var htm = '<div id="pop-help-membership-service-price">' + msg1 + '<div style="padding-bottom: 12px;">' + msg3 + '</div>' + memberProfileServiceList + '</div>'; 25018 25019 GLO.Popup.Info.open(htm, h1).getPopup().css({ "background-color": "white" }); 25020 } 25021
25022 _cMembership.changeCostPerService = function(btn) { 25023 var jparent = $(btn).closest('#pop-preview-cost-per-service'); 25024 var cost = UTIL.coalesceMoney(jparent.find('#Cost_Per_Service_mn').val()); 25025 var limit = UTIL.coalesceInt(jparent.attr('limit_sr')); 25026 var msid = jparent.attr('membership_service_id'); 25027 var totalCost = UTIL.displayMoney(cost * limit, true, false, true); 25028 var jPopMemberProfile = $('#pop-member-view').closest('.glopop'); 25029 25030 if (jPopMemberProfile.length) { 25031 jPopMemberProfile.find('#membership-service-list li[membership_service_id="' + msid + '"]').find('input.cost').val(totalCost); 25032 } else { 25033 var jPopMembershipService = $('#pop-membership-service-edit').closest('.glopop'); 25034 jPopMembershipService.find('#Service_Commission_Price_mn').val(totalCost); 25035 } 25036 25037 GLO.Popup.close($('#pop-help-membership-service-price').closest('.glopop')); 25038 } 25039 25040 function _getCostPerServiceHtm(cost, limit, msid) { 25041 if (limit > 0) { 25042 var label = '<label for="Cost_Per_Service_mn">Commission Price per Service</label> <span class="dollar-sign">$</span>'; 25043 var htmInput = '<input id="Cost_Per_Service_mn" type="text" value="' + UTIL.displayMoney(cost/limit, true) + '"/>'; 25044 var btnSave = '<span class="btnAdd"><a onclick="GLO.Provider.Membership.changeCostPerService(this)">Change</a></span>'; 25045 25046 return '<div id="pop-preview-cost-per-service" limit_sr="' + limit + '" membership_service_id="' + UTIL.cleanString(msid) + '">' + label + htmInput + btnSave + '</div>'; 25047 } else { 25048 return ''; 25049 } 25050 } 25051 25052 function _openServicePriceHelp_MembershipSetup() { 25053 var jpop = $('#pop-membership-service-edit').closest('.glopop'); 25054 var cost = UTIL.coalesceMoney(jpop.find('#Service_Commission_Price_mn').val()); 25055 var limit = UTIL.coalesceInt(jpop.find('#Limit_nr').val(), 0); 25056 25057 return _getCostPerServiceHtm(cost, limit); 25058 } 25059 25060 function _openServicePriceHelp_MemberProfile(jsvc) { 25061 var totalPrice = UTIL.coalesceMoney(jsvc.find('.adjust-total-service-price .cost').val()); 25062 var msid = jsvc.attr('membership_service_id'); 25063 var htm = '', cnt = 0, remaining = UTIL.coalesceInt(jsvc.find('.remaining').val(), 0); 25064 25065 while (jsvc.next().hasClass('membership-appt-row')) { 25066 jsvc = jsvc.next(); 25067 ++cnt; 25068 } 25069 25070 if (cnt > 0 || remaining > 0) { 25071 htm += '<div style="margin-top: 6px; font-size: 16px; font-weight: bold;"><label>Scheduled Appointments <small>(this period)</small></label> = <span>' + cnt + '</span></div>'; 25072 htm += '<div style="margin-top: 12px; font-size: 16px; font-weight: bold;"><label>Remaining Appointments <small>(this period)</small></label> = <span>' + remaining + '</span></div>'; 25073 htm += '<div style="margin-top: 6px; font-size: 16px; font-weight: bold;"><label>Total Appointments <small>(this period)</small></label> = <span>' + (remaining + cnt) + '</span></div>'; 25074 htm += _getCostPerServiceHtm(totalPrice, remaining + cnt, msid); 25075 } 25076 25077 var htmDefaultCost = '', ms = GLO.ClientProfile.getMembershipService(msid); 25078 25079 if (ms.limit_nr < 900) { 25080 if (ms.limit_nr > 0 && (totalPrice > 0 || UTIL.coalesceMoney(ms.price_mn) > 0)) { 25081 htmDefaultCost = '<span id="membership-service-default-cost"> (commission price of ' + UTIL.displayMoney(UTIL.coalesceMoney(ms.price_mn)/ms.limit_nr) + ' per service) </span>'; 25082 } 25083 25084 htm += '<div id="pop-help-membership-service-default"><span id="membership-service-default-label">Normal Membership Service Setup: </span>'; 25085 htm += '<span id="membership-service-default-limit">' + UTIL.pluralLabel(ms.limit_nr, 'service') + '</span>' + htmDefaultCost; 25086 htm += '<span id="membership-service-default-rollover"> rollover ' + UTIL.coalesceInt(ms.rollover_unused_pct) + '% of un-used services</span> </div>'; 25087 } 25088 25089 return htm; 25090 } 25091 25092 _cMembership.Client = (function() { 25093 function _cMemberClient() {} 25094 25095 _cMemberClient.open = function(btn) { 25096 var jclient = $('form#client-form'); 25097 var membershipId = jclient.find('#Membership_id').val(); 25098 var cid = jclient.find('#Client_id').val(); 25099 var cname = UTIL.coalesce(jclient.find('#Full_Name_vc').val(), jclient.find('#First_Name_vc').val() + ' ' + jclient.find('#Last_Name_vc').val()); 25100 var linkedProviderId = $('#clientProfile-buttons #clientProfile-import').attr('link_provider_id'); 25101 25102 if (!UTIL.isEmpty(membershipId)) { 25103 GLO.UI.Form.beginProcessing(btn); 25104 _cMemberClient.openViewMember(cid, cname, null, null, linkedProviderId); 25105 } else { 25106 _openAddMember(jclient, cid, cname); 25107 } 25108 } 25109 25110 function _getViewMemberProfileLink(cid, cname) { 25111 var clientName = UTIL.replaceQuotesTitle(cname); 25112 var btnViewMember = '<a onclick="GLO.Provider.Membership.Client.openViewMember(' + cid + ', \'' + clientName + '\', this)">View Member Profile</a>'; 25113 var htmViewMember = '<div id="pop-member-view-profile" style="margin-top: 12px;"><span id="btnViewMember" class="btnAdd">' + btnViewMember + '</span></div>'; 25114 return htmViewMember; 25115 } 25116 25117 _cMemberClient.openPaySummaryByClientId = function(cid) { 25118 GLO.Popup.close($('#pop-member-profile')); 25119 25120 var td = $('#membership-report').find('tr[client_id=' + cid + ']').find('.membership-column-next-bill-date'); 25121 25122 _cMemberClient.openPaySummary(td); 25123 } 25124
25125 _cMemberClient.openPaySummary = function(btn) { 25126 //GLO.Popup.Processing.open(msg, h1); 25127 var tr = $(btn).closest('tr'); 25128 var cid = tr.attr('client_id'), iid = tr.attr('inventory_id'), mcid = tr.attr('membership_client_id'), status = tr.attr('member_status_cd'); 25129 var membershipId = tr.attr('membership_id'), nextMembershipId = tr.attr('next_membership_id'); 25130 var nextBillDate = tr.attr('next_bill_dt'), periodEndDate = tr.attr('period_end_dt') 25131 var payCount = UTIL.coalesceInt(tr.attr('payment_count_sr')), lastPurchaseDate = tr.attr('last_purchase_dt'); 25132 var balance = tr.attr('balance_mn'), payFail = tr.attr('payment_fail_vc'), hasCardOnFile = tr.attr('card_on_file_fl'); 25133 var autoBill = tr.find('.membership-column-auto-bill .is-auto-bill').length, cname = tr.find('.membership-column-client > a').text(); 25134 25135 if (UTIL.isDate(nextBillDate)) { 25136 periodEndDate = new Date(nextBillDate); 25137 } else { 25138 periodEndDate = new Date(periodEndDate).addDays(1); 25139 } 25140 25141 var htmNextPeriod = _getNextPeriodHtm(balance, autoBill, nextMembershipId, true); 25142 var htmCardOnFile = _getCardOnFileButton(hasCardOnFile, cid); 25143 var htmViewMember = _getViewMemberProfileLink(cid, cname); 25144 25145 var btnPreviewNextPeriod = '<a onclick="GLO.Provider.Membership.Client.openPreviewNextPeriod(' + cid + ', this)">
25145Preview Next Period</a>'; 25146 var htmPreviewNextPeriod = '<div id="pop-member-preview-next-period" style="margin-top: 12px;"><span id="btnPreviewNextPeriod" class="btnAdd">' + btnPreviewNextPeriod + '</span></div>'; 25147 25148 var htmData = '<input type="hidden" id="Membership_Client_id" value="' + mcid + '"/>'; 25149 var h3 = '<h3 style="padding: 2px 16px 1px; font-size: 20px; color: white; background-color: #003366;">Membership Payments</h3>'; 25150 var htmNextPayment = _getNextPayHtm(tr, membershipId, nextMembershipId, cid, cname, payFail, balance, nextBillDate, periodEndDate, status); 25151 var htmLastPayment = _getLastPayHtm(cid, cname, iid, payCount, lastPurchaseDate); 25152 25153 var htm = '<div id="pop-member-pay-summary" client_id="' + cid + '">' + htmNextPeriod + htmCardOnFile + htmViewMember + htmPreviewNextPeriod + htmData + h3 + htmNextPayment + htmLastPayment + '</div>'; 25154 var h1 = '<a class="client-name-link" onclick="GLO.Provider.Membership.Client.openClientProfile(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\')">' + UTIL.coalesce(cname, 'View Member') + '</a>'; 25155 25156 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 25157 jpop.find('h1').css({ "margin-bottom": "0" }).find('a').css({ "border-bottom": "none", "text-decoration": "underline", "color": "white" }); 25158 jpop.find('#Auto_Billing_fl').change(GLO.Provider.Membership.Client.saveAutoBill); 25159 jpop.find('.btnSave').remove(); 25160 jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none" }).find('>a').text('Close').focus(); 25161 } 25162 25163 _cMemberClient.openApptHistoryByDate = function(element, cid, start, end) { 25164 GLO.UI.Form.beginProcessing($(element)); 25165 GLO.ClientHistory.open(cid, true, null, start, end); 25166 } 25167 _cMemberClient.openApptHistory = function(btn) { 25168 var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr'); 25169 var cid = tr.attr('client_id'); 25170 var start = tr.attr('period_start_dt'); 25171 var end = tr.attr('period_end_dt'); 25172 25173 GLO.UI.Form.beginProcessing($(btn)); 25174 GLO.ClientHistory.open(cid, true, null, start, end); 25175 } 25176 25177 _cMemberClient.openViewMemberFromTicket = function(cid, cname, btn) { 25178 GLO.Popup.closeIfExist($('#pop-warn-member-status').closest('.glopop')); 25179 25180 _cMemberClient.openViewMember(cid, cname, btn); 25181 } 25182 25183 _cMemberClient.openViewMember = function(cid, cname, btn, clickOn, linkedProviderId) { 25184 var uri = GLO.Link.WebsiteDomain + 'membership/GetClient?cid=' + cid; 25185 var jPopPreview = $('#pop-preview-next-period').closest('.glopop'); 25186 25187 if (!UTIL.isEmpty(linkedProviderId)) { 25188 uri += '&linkedprovider=' + linkedProviderId; 25189 } 25190 25191 GLO.Popup.closeIfExist(jPopPreview); 25192 25193 if (btn) { 25194 if ($(btn).hasClass('btnProcessing4')) { 25195 return; 25196 } 25197 25198 GLO.UI.Form.beginProcessing($(btn)); 25199 } 25200 25201 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 25202 .success(function(data, textStatus, jqXHR) { 25203 GLO.UI.Form.resetProcessing(); 25204 GLO.Popup.closeIfExist($('#pop-loading-view-member').closest('.glopop')); 25205 25206 var isLinkedProviderMembership = false; 25207 var jsonContainer = JSON.parse(data); 25208 var json = jsonContainer.member; 25209 var membership = GLO.ClientProfile.getMembership(json.membership_id); 25210 25211 if (UTIL.isEmpty(membership.id) && !UTIL.isEmpty(linkedProviderId)) { 25212 var membership = jsonContainer.membership[0]; 25213 isLinkedProviderMembership = true; 25214 } 25215 25216 var membershipName = membership.name; // GLO.Provider.Membership.getName(json.membership_id, !GLO.Info.isMobile()); 25217 25218 if (UTIL.isEmpty(membershipName)) { 25219 GLO.Popup.Warning.open('<div id="pop-warn-member-not-found">Unable to find membership</div>', 'Membership Not Found'); 25220 return; 25221 } else if ($('#pop-member-view').closest('.glopop').length) { 25222 return; //=member profile already open. 25223 } 25224 25225 var jhelp = $('#pop-help-cell-summary').closest('.glopop'), jClosePo
25225p = $('#pop-member-pay-summary').closest('.glopop'); 25226 if (jhelp.length) { GLO.Popup.close(jhelp); } //= if open from sales detail report cell summary automatically opened. 25227 if (jClosePop.length) { GLO.Popup.close(jClosePop); } 25228 25229 var statusName = GLO.ClientProfile.getStatusName(json.member_status_cd); 25230 var statusCSS = GLO.ClientProfile.getStatusCSS(json.member_status_cd); 25231 25232 var priceTitle = 'default price = ' + UTIL.displayMoney(membership.price, false, false, true); 25233 var htmName = '<div id="pop-member-view-name"><b onclick="GLO.Provider.Membership.Client.displayChangeMembership(this)" title="' + priceTitle + '">' + membershipName + '</b></div>'; 25234 var htmStatus = '<span id="pop-member-view-status"><label>Status</label><b>' + statusName + '</b></span>'; 25235 var htmStart = '<span id="pop-member-view-start" start_dt="' + json.start_dt + '"><label>Start Date: </label><b>' + new Date(json.start_dt).toSADate(true) + '</b></span>'; 25236 var htmStartAndStatus = '<div id="pop-member-view-ss">' + htmStart + htmStatus + '</div>'; 25237 var htmCurrentPeriod = _getCurrentPeriodHtm(json.end_dt, json.period_start_dt, json.period_end_dt, cid, cname); 25238 var htmPrice = _getPriceAndNextHtm(json.price_mn, json.custom_price_mn, json.billing_period_cd, json.next_bill_dt, json.period_end_dt, json.member_status_cd, membership); 25239 25240 var btnPayNow = _getPayNowButton(membership.id, json.next_membership_id, json.next_bill_dt, json.period_end_dt, cid, cname); 25241 var htmNextPeriod = _getNextPeriodHtm(json.balance_mn, json.auto_billing_fl, json.next_membership_id, false, btnPayNow); 25242 25243 var htmServiceList = _getServiceListHtm(json.services, cid, cname); 25244 var htmHidden = _getHiddenHtm(json.membership_id, cid); 25245 var htm = '<div id="pop-member-view">' + htmHidden + htmStartAndStatus + htmCurrentPeriod + htmPrice + htmNextPeriod + htmName + htmServiceList + '</div>'; 25246 25247 var h1 = '<a class="client-name-link" onclick="GLO.Provider.Membership.Client.openClientProfile(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\')">' + UTIL.coalesce(cname, 'View Member') + '</a>'; 25248 var h1QuietStart = '<a class="quietest-left quietest no-animate" style="margin-top: 0;" '; 25249 25250 if ($('#membership-report').length > 0) { 25251 h1 = h1QuietStart + 'onclick="GLO.Provider.Membership.Client.openPaySummaryByClientId(' + cid + ')">pay summary</a>' + h1; 25252 } else if (GLO.Info.roleType >= 170) { 25253 h1 = h1QuietStart + 'onclick="GLO.Provider.Membership.Client.openMemberPayHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)">payments</a>' + h1; 25254 } 25255 25256 var ojpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.Membership.Client.save, null, true); 25257 var jpop = ojpop.getPopup().attr('id', 'pop-member-profile'); 25258 jpop.find('h1').addClass(statusCSS).css({ "margin-bottom": "0" }).find('a').css({ "border-bottom": "none", "text-decoration": "underline", "color": "white" }); 25259 25260 var cssCancel = { "position": "relative;", "left": "inherit", "float": "none", "padding": 0, "margin-left": "-4px", "letter-spacing": "1px", "font-weight": "bold", "font-size": "large" }; 25261 var btnCancel = jpop.find('.btnCancel').css(cssCancel); 25262 25263 if (GLO.Info.roleType > 199) { 25264 var btnDelete = '<span class="btnDelete" style="position: absolute; left: 10px; margin: 0;"><a onclick="GLO.Provider.Membership.Client.remove()">Delete</a></span>'; 25265 btnCancel.before(btnDelete); 25266 25267 jpop.find('#Period_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 25268 jpop.find('#Period_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 25269 } else { 25270 jpop.find('.btnSave').remove(); 25271 jpop.find('input,select').prop('disabled', true); 25272 } 25273 25274 _openViewMember2(jpop, json.next_bill_dt, json.billing_period_cd); 25275 _addMemberProfileHelloBar(jpop); 25276 25277 ojpop.realign(); 25278 btnCancel.find('>a').text('Close'); 25279 jpop.find(':focus').blur(); 25280 25281 if (isLinkedProviderMembership) { 25282 _setPopupToReadOnly(jpop, true); 25283 25284 var css = 'margin-top: 16px; padding: 8px; letter-spacing: 1px; text-align: center; font-weight: bold; background-color: ' + jsonContainer.provider.bgcolor + '; color: white;'; 25285 var htm = '<p style="' + css + '">this membership is at ' + jsonContainer.provider.name + '</p>'; 25286 jpop.find('.pop-buttons-parent').before(htm); 25287 } else if (clickOn) { 25288 jpop.find(clickOn).click(); 25289 } else { 25290 setTimeout(function() { jpop.find(':focus').blur(); }, 100); 25291 } 25292 }) 25293 .error(function(jqXHR, textStatus, errorThrown) { 25294 GLO.UI.Form.resetProcessing(); 25295 }); 25296 } 25297 25298 function _addMemberProfileHelloBar(jpop) { 25299 jpop.find('#hello-bar-change-next-bill').remove(); 25300 25301 var dtStart = jpop.find('#Period_Start_dt').val(); 25302 var dtEnd = jpop.find('#Period_End_dt').val(); 25303 var dtNextBill = jpop.find('#Next_Bill_dt').val(); 25304
25305 var billPeriod = jpop.find('#Billing_Period_cd option:selected').attr('value'); 25306 var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val()); 25307 25308 if (GLO.Info.roleType > 209 && UTIL.isEmpty(billPeriod) && balance === 0 && UTIL.isDate(dtStart) && UTIL.isDate(dtEnd) && UTIL.isDate(dtNextBill)) { 25309 if (new Date(dtNextBill).toGloDate() != new Date(dtEnd).addDays(1).toGloDate()) { 25310 var cssClass = '', label = '<label></label>', id = 'hello-bar-change-next-bill'; 25311 var aChange = '<a onclick="GLO.Provider.Membership.Client.changeBillDateToDefault()">Change Next Bill Date to Start of Next Period</a>'; 25312 var btnChange = '<span class="btnAdd">' + aChange + '</span>'; 25313 var htmHello = '<div>' + label + btnChange + '</div>'; 25314 25315 GLO.Popup.addHelloBar(jpop, htmHello, id, cssClass); 25316 } 25317 } 25318 } 25319 25320 function _setPopupToReadOnly(jpop, isRemoveButtons) { 25321 jpop.find('input,select,textarea').prop('disabled', true); 25322 25323 if (isRemoveButtons) { 25324 jpop.find('.btnAdd, .btnSave, .btnDelete').remove(); 25325 GLO.Popup.Custom.singleButton(jpop, 'Close'); 25326 } 25327 } 25328 25329 function _openViewMember2(jpop, next_bill_dt, billing_period_cd) { 25330 if (!UTIL.isEmpty(next_bill_dt) || !UTIL.isEmpty(billing_period_cd)) { 25331 GLO.Provider.Membership.Client.changeBillDate(); 25332
25333 if (billing_period_cd) { jpop.find('#Billing_Period_cd').val(billing_period_cd); } 25334 if (UTIL.isDate(next_bill_dt)) { jpop.find('#Next_Bill_dt').val(next_bill_dt); } 25335 25336 _cMemberClient.setPricePerPeriod(); 25337 } 25338 25339 if (GLO.Info.roleType < 170) { 25340 jpop.find('input,select').prop('disabled', true); 25341 } else { 25342 jpop.find('input,select').change(function() { 25343 $('#pop-member-view').closest('.glopop').find('.btnSave > a').addClass('unsaved'); 25344 }); 25345 } 25346 } 25347 25348 function _getAutoBillStatusHtm(member) { 25349 if (!member.card_on_file_fl) { 25350 var status = 'No Card on File'; 25351 var style = 'background-color: rgba(255,0,0,.6);'; 25352 } else if (member.auto_bill_fl) { 25353 var status = 'Enabled'; 25354 var style = 'background-color: rgba(0,255,0,.8);'; 25355 } else { 25356 var status = 'Disabled'; 25357 var style = 'background-color: orange;'; 25358 } 25359 25360 return '<div id="pop-preview-bill-status" style="' + style + '"> <label>Auto Billing Status</label> <b style="color: white;">' + status + '</b> </div>' 25361 } 25362 25363 _cMemberClient.openPreviewNextPeriod = function(cid, btn) { 25364 var tr = $('#membership-report').find('tr[client_id="' + cid + '"]'); 25365 var cname = tr.find('td.membership-column-client > a').text(); 25366 var member = _getMember(tr); 25367 25368 if (UTIL.isEmpty(member.membership.name)) { 25369 GLO.Popup.Warning.open('Membership Not Found', 'Membership Deleted?'); 25370 return; 25371 } 25372 25373 var htmAutoBillStatus = _getAutoBillStatusHtm(member); 25374 var htmNewPeriod = '', dueLabel = '', price = '', due = UTIL.displayMoney(member.due_mn, false, false, true); 25375 25376 if (new Date() > member.bill_dt) { 25377 var dt = 'now'; 25378 } else { 25379 var dt = member.bill_dt.toSADate(true); 25380 } 25381 25382 if (member.new_period_end_dt >= member.bill_dt || new Date() > member.bill_dt) { 25383 price = UTIL.displayMoney(UTIL.coalesceMoney(member.custom_price_mn, member.membership.price, false, false, true)); 25384 25385 if (price > 0) { 25386 if (UTIL.isEmpty(due)) { 25387 dueLabel = 'pre-paid'; 25388 } else { 25389 dueLabel = 'Due'; 25390 } 25391 } 25392 } 25393 25394 var htmPayDate = '<span style="float: left;"><label>Next Payment</label> <b>' + dt + '</b></span>'; 25395 var htmPayDue = '<span style="float: right;"><label>' + dueLabel + '</label> <b>' + due + '</b></span>'; 25396 var htmPay = '<div id="pop-preview-pay-date">' + htmPayDate + htmPayDue + '</div>'; 25397 var htmMembership = '<div id="pop-preview-membership" style="clear: both;"> <b>' + member.membership.name + ' <i>' + price + '</i> </div>'; 25398 25399 if (member.is_new_member_period) { 25400 var dateRange = member.new_period_start_dt.toSADate(true) + ' - ' + member.new_period_end_dt.toSADate(true); 25401 htmNewPeriod = '<div id="pop-preview-new-period"> <label>New Member Period</label> <b>' + dateRange + '</b> </div>'; 25402 //htmNewPeriod += '<div id="pop-preview-new-period"> <label>Next Billing Date</label> <b>' + member.next_bill_dt.toSADate(true) + '</b> </div>'; 25403 //} else if (member.is_custom_bill_period) { 25404 // htmNewPeriod = '<div id="pop-preview-new-period"> <label>Next Billing Date</label> <b>' + member.next_bill_dt.toSADate(true) + '</b> </div>'; 25405 } 25406 25407 var htmViewMember = _getViewMemberProfileLink(cid, cname); 25408 var htmThrobber = '<div id="pop-preview-throbber" style="margin-top: 16px;">' + GLO.Report.Template2.getBlueThrobber() + '</div>'; 25409 var htmServices = '<div id="pop-preview-services">' + '<h4 style="margin-top: 16px;">Member Services</h4>' + htmThrobber + '</div>'; 25410 var htm = '<div id="pop-preview-next-period">' + htmAutoBillStatus + htmPay + htmMembership + htmNewPeriod + htmViewMember + htmServices + '</div>'; 25411 25412 if (btn) { 25413 GLO.UI.Form.beginProcessing($(btn)); 25414 var jPopPaySummary = $('#pop-member-pay-summary').closest('.glopop'); 25415 if (jPopPaySummary.length) { GLO.Popup.close(jPopPaySummary); } 25416 } 25417 25418 var ojpop = GLO.Popup.Custom.openSimple(htm, cname + ': Preview Next Perio
25418d', null, null, true); 25419 var jpop = ojpop.getPopup(); 25420 GLO.Popup.Custom.singleButton(jpop, 'Close'); 25421 25422 jpop.find('h1').css({ "margin-bottom": 0 }); 25423 GLO.UI.Form.resetProcessing(); 25424 25425 if (member.is_new_member_period || member.balance_mn >= 0) { 25426 _getNextPeriodServices(cid, jpop, ojpop); 25427 } else { 25428 var htm = '<div id="pop-preview-pay-balance"><p>Same Membership Period</p><p>Next Payment is for Balance Due</p></div>'; 25429 jpop.find('#pop-preview-services #pop-preview-throbber').replaceWith(htm); 25430 } 25431 } 25432 function _getNextPeriodServices(cid, jpop, ojpop) { 25433 var uri = GLO.Link.WebsiteDomain + 'membership/PreviewNextPeriod?client=' + cid; 25434 25435 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false, "dataType": "json" }) 25436 .complete(function(data, textStatus, jqXHR) { 25437 var warning = null, arr = data.responseJSON; 25438 25439 if (arr && arr.length > 0) { 25440 warning = arr[0].warning_vc 25441 } 25442 25443 if (!UTIL.isEmpty(warning)) { 25444 var htm = '<div>' + warning + '</div>'; 25445 } else { 25446 var htm = _getNextPeriodServices2(arr); 25447 } 25448 25449 jpop.find('#pop-preview-services #pop-preview-throbber').replaceWith(htm); 25450 ojpop.realign(); ojpop.realign(); ojpop.realign(); 25451 }); 25452 //.error(function(jqXHR, textStatus, errorThrown) { }); 25453 } 25454 function _getNextPeriodServices2(arr) { 25455 var htm = ''; 25456 25457 for (var i=0; i < arr.length; i++) { 25458 var nm = UTIL.coalesceString(arr[i].service_vc, 'any service'); 25459 var cost = arr[i].price_mn, costPerService = arr[i].price_per_service_mn; 25460 25461 if (innerWidth < 640) { nm = UTIL.maxString(nm, 20); } 25462 25463 if (UTIL.isEmpty(arr[i].limit_sr)) { 25464 var rollover = 0, limit = '<span style="letter-spacing: 0; font-weight: normal; font-size: 11px;">unlimited</span>'; 25465 } else { 25466 var limit = UTIL.coalesceInt(arr[i].limit_sr), rollover = UTIL.coalesceInt(arr[i].rollover_sr); 25467 } 25468 25469 if (arr[i].discount_pct > 0) { 25470 var discount = parseInt(arr[i].discount_pct) + '%'; 25471 } else { 25472 var discount = UTIL.displayMoney(arr[i].discount_mn); 25473 } 25474 25475 var li = '<li><b class="preview-service-limit">' + limit; 25476 25477 if (rollover > 0) { 25478 li += '<small class="preview-service-rollover" style="margin-left: 2px;">(' + rollover + ' <span style="font-size: 11px;">rollover</span>)</small>'; 25479 } 25480 25481 li += '</b>' + '<b class="preview-service-name">' + nm + '</b><b class="preview-service-discount">' + discount + '</b>'; 25482 25483 if (cost > 0 && limit > 0) { 25484 li += '<span class="preview-service-cost">Commission: ' + UTIL.displayMoney(cost, false, false, true); 25485 25486 if (limit > 1) { 25487 li += '<small style="margin-left: 4px;">(' + UTIL.displayMoney(costPerService) + ' per service)</small>'; 25488 } 25489 25490 li += '</span>'; 25491 } 25492 25493 htm += li + '</li>'; 25494 } 25495 25496 return '<ul id="preview-service-list">' + htm + '</ul>'; 25497 } 25498 25499 _cMemberClient.openClientProfile = function(cid, cname) { 25500 var jpop = $('#pop-member-view, #pop-member-pay-summary').closest('.glopop'); 25501 GLO.Popup.close(jpop); 25502 ClientProfile.goto(cid, true, cname); 25503 } 25504 25505 _cMemberClient.openMemberPayHistory = function(cid, cname, btn) { 25506 var uri = GLO.Link.WebsiteDomain + 'membership/PaymentHistory?client=' + cid; 25507 25508 if (btn) { 25509 GLO.UI.Form.beginProcessing($(btn)); 25510 } 25511 25512 var jpop = GLO.Popup.getTopCustomPopup(); 25513 if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); } 25514 25515 $.modal.close(); 25516 var ojpop = GLO.Popup.Processing.open(SA.Resource.LookingUp + ' ' + SA.Resource.PaymentHistory + ' for ' + cname + '...', SA.Resource.LookingUp + ' ' + SA.Resource.PaymentHistory); 25517 25518 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 25519 .success(function(data, textStatus, jqXHR) { 25520 GLO.UI.Form.resetProcessing(); 25521 ojpop.close(); 25522 25523 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 25524 GLO.Popup.Warning.open(data, SA.Resource.PaymentHistory + ' ' + SA.Resource.NotFound); 25525 return; 25526 } 25527 25528 var h1 = '<span style="padding-right: 4px; white-space: nowrap; color: white;">' + cname + '</span> <span style="white-space: nowrap; color: white;">Membership ' + SA.Resource.PaymentHistory + '</span>'; 25529 var jpop = GLO.Popup.Custom.openSimple(data, h1); 25530 GLO.Popup.Custom.singleButton(jpop); 25531 var jtbl = jpop.find('#membership-payment-report'); 25532 25533 UI.initTableSorter(jtbl); 25534 25535 jpop.find('h1').css({ "margin-bottom": "0" }); 25536 }) 25537 .error(function(jqXHR, textStatus, errorThrown) { 25538 GLO.UI.Form.resetProcessing(); 25539 ojpop.close(); 25540 }); 25541 } 25542 25543 _cMemberClient.openMemberPeriodHistory = function(cid, cname, btn) { 25544 var uri = GLO.Link.WebsiteDomain + 'membership/PeriodHistory?client=' + cid; 25545 25546 if (btn) { 25547 GLO.UI.Form.beginProcessing($(btn)); 25548 } 25549 25550 var jpop = GLO.Popup.getTopCustomPopup(); 25551 if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); } 25552 25553 $.modal.close(); 25554 var ojpop = GLO.Popup.Processing.open('Looking up Period History for ' + cname + '...', 'Member Period History'); 25555 25556 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 25557 .success(function(data, textStatus, jqXHR) { 25558 GLO.UI.Form.resetProcessing(); 25559 ojpop.close(); 25560 25561 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 25562 GLO.Popup.Warning.open(data, 'Period History Not Found'); 25563 return; 25564 } 25565 25566 var h1 = '<span style="padding-right: 4px; white-space: nowrap; color: white;">' + cname + '</span> <span style="white-space: nowrap; color: white;">Member Period History</span>'; 25567 var jpop = GLO.Popup.Custom.openSimple(data, h1).css({ "max-width": "1100px" }); 25568 GLO.Popup.Custom.singleButton(jpop); 25569 var jtbl = jpop.find('#member-period-report'); 25570 25571 UI.initTableSorter(jtbl); 25572 GLO.Report.CellSummary.initReport(jtbl, false, true); 25573 25574 jpop.find('h1').css({ "margin-bottom": "0" }); 25575 }) 25576 .error(function(jqXHR, textStatus, errorThrown) { 25577 GLO.UI.Form.resetProcessing(); 25578 ojpop.close(); 25579 }); 25580 } 25581 25582 _cMemberClient.openAddCustomService = function(cid, cname, btn) { 25583 var jpopMember = $('#pop-member-view').closest('.glopop'); 25584 var membershipId = jpopMember.find('#Membership_id').val(); 25585 GLO.Provider.Membership.openAddCustomService(cid, membershipId); 25586 } 25587 25588 _cMemberClient.addCardOnFile = function(btn, cid) { 25589 var jpop = $('#pop-member-pay-summary'); 25590 var cid = jpop.attr('client_id'); 25591 25592 jpop = jpop.closest('.glopop'); 25593 var cname = UTIL.directTagOnly(jpop.find('.pop-header h1')); 25594 25595 ClientProfile.goto(cid, true, cname, ClientProfile.openAddCard); 25596 25597 GLO.UI.Form.beginProcessing($(btn)); 25598 } 25599 25600 _cMemberClient.openMemberPayment = function(cid, iid, dt, btn) { 25601 var uri = GLO.Link.Object.Provider.Ajax + 'LookupTicketByProductDate?client=' + cid + '&inventory=' + iid + '&date=' + dt; 25602 25603 if (btn) { 25604 GLO.UI.Form.beginProcessing($(btn)); 25605 } 25606 25607 var jpop = GLO.Popup.getTopCustomPopup(); 25608 if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); } 25609 25610 $.modal.close(); 25611 var ojpop = GLO.Popup.Processing.open('Looking up Payment on ' + new Date(dt).toSADate(true) + '...', 'Looking up Payment'); 25612 25613 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 25614 .success(function(data, textStatus, jqXHR) { 25615 GLO.UI.Form.resetProcessing(); 25616 ojpop.close(); 25617 25618 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 25619 GLO.Popup.Warning.open(data, 'Payment Not Found'); 25620 return; 25621 } 25622 25623 if (!UTIL.isEmpty($(data).attr('schedule_id'))) { 25624 UserPortal.Edit.getOpen(data, jqXHR, UserPortal.Edit.isCalendar, true); 25625 } else { 25626 UserPortal.Price.getOpen(data, jqXHR); 25627 } 25628 }) 25629 .error(function(jqXHR, textStatus, errorThrown) { 25630 GLO.UI.Form.resetProcessing(); 25631 ojpop.close(); 25632 }); 25633 } 25634
25635 _cMemberClient.openMergeMembership = function(btn) { 25636 var jpopMember = $('#pop-member-view').closest('.glopop'); 25637 var clientName = jpopMember.find('.client-name-link').text(); 25638 var clientId = jpopMember.find('#Client_id').val(); 25639 25640 var currentMembershipName = UTIL.directTagOnly(jpopMember.find('#pop-member-view-name > b')); 25641 var currentMembershipId = jpopMember.find('#Membership_id').val(); 25642 25643 var jNextMembership = jpopMember.find('.next-membership-name'); 25644 var nextMembershipName = jNextMembership.text(); 25645 var nextMembershipId = jNextMembership.attr('next_membership_id'); 25646 25647 var msg = '<p style="font-weight: bold;">Merging the current membership (' + currentMembershipName + ') and the next membership (' + nextMembershipName + ') on ' 25648 + clientName + ' member profile will then include the services for both memberships in the current member profile</p>'; 25649 25650 var msgNote = '<p style="margin: 24px; margin-right: 0; font-style: italic; font-size: smaller;">This will <b>NOT</b> affect the membership profile for any other client'; 25651 25652 var divStart = '<div id="pop-confirm-merge-membership" membership_id="' + currentMembershipId + '" next_membership_id="' + nextMembershipId + '" client_id="'+ clientId + '">'; 25653 var htm = divStart + msg + msgNote + '</div>'; 25654 25655 var h1 ='Merge the current and next membership for ' + clientName + '?'; 25656 var jpop = GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Membership.Client.saveMergeMembership); 25657 } 25658 _cMemberClient.saveMergeMembership = function(btn) { 25659 var jpopMerge = $('#pop-confirm-merge-membership'); //.closest('.glopop'); 25660 var currentMembershipId = jpopMerge.attr('membership_id'), nextMembershipId = jpopMerge.attr('next_membership_id'), clientId = jpopMerge.attr('client_id'); 25661 25662 var uri = GLO.Link.WebsiteDomain + 'membership/MergeMembership?membershipCurrent=' + currentMembershipId + '&membershipNext=' + nextMembershipId + '&client=' + clientId; 25663 25664 var htm = '<div id="pop-merging-membership">Merging Memberships...</div>'; 25665 var ojprocessing = GLO.Popup.Processing.open(htm, 'Updating Member Profile'); 25666 25667 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} }) 25668 .success(function(data, textStatus, jqXHR) { 25669 ojprocessing.close(); 25670 GLO.Popup.closeIfExist(jpopMerge); 25671 25672 _reloadMemberProfile(clientId, 'with merged memberships'); 25673 }) 25674 .error(function(jqXHR, textStatus, errorThrown) { }); 25675 } 25676 25677 function _getCardOnFileButton(hasCardOnFile, cid) { 25678 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 60) { 25679 return ''; 25680 } else if (UTIL.parseBool(hasCardOnFile)) { 25681 var btn = '<span id="btnViewCardOnFile" class="btnAdd"><a onclick="GLO.ClientProfile.viewCardOnFile(this)">View Card On File</a></span>'; 25682 } else { 25683 var btn = '<span id="btnAddCardOnFile" class="btnAdd"><a onclick="GLO.Provider.Membership.Client.addCardOnFile(this, ' + cid + ')">Add Card On File</a></span>'; 25684 } 25685 25686 return '<div id="pop-member-card-file">' + btn + '</div>'; 25687 } 25688 function _getLastPayHtm(cid, cname, iid, payCount, lastPurchaseDate) { 25689 var htm = ''; 25690 25691 if (UTIL.isDate(lastPurchaseDate)) { 25692 var dt = new Date(lastPurchaseDate); 25693 var fn = 'GLO.Provider.Membership.Client.openMemberPayment(' + cid + ', ' + iid + ', \'' + dt.toGloDate() + ' ' + dt.toGloTime() + '\')'; 25694 var lbl = '<label>last payment</label>'; 25695 var link = '<a onclick="' + fn + '" id="last-membership-pay-date">' + dt.toPrettyDate() + '</a>'; 25696 htm += '<span id="pop-member-summary-pay-last">' + lbl + link + '</span>'; 25697 } 25698 25699 if (payCount > 0) { 25700 if (GLO.Info.roleType > 209) { 25701 var fn = 'GLO.Provider.Membership.Client.openMemberPayHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)'; 25702 htm += '<a onclick="' + fn + '" id="membership-payment-history">' + UTIL.pluralLabel(payCount, 'membership payment') + '</a>'; 25703 } else { 25704 htm += '<span id="membership-payment-history">' + UTIL.pluralLabel(payCount, 'membership payment') + '</span>'; 25705 } 25706 } 25707 25708 if (!UTIL.isEmpty(htm)) { 25709 return '<div id="pop-member-last-pay">' + htm + '</div>'; 25710 } else { 25711 return ''; 25712 } 25713 } 25714 function _getNextPayHtm(tr, membershipId, nextMembershipId, cid, cname, payFail, balance, nextBillDate, periodEndDate, status) { 25715 var msgCSS = '', msg = ''; 25716 var btnPayNow = _getPayNowButton(membershipId, nextMembershipId, nextBillDate, periodEndDate, cid, cname); 25717 25718 if (balance < 0 && !UTIL.isEmpty(payFail)) { 25719 msgCSS = 'font-weight: bold; color: rgb(255,0,0);'; 25720 msg = '<i>Payment Failed</i>'; 25721 25722 if (payFail != 'Other Error') { msg += '<small style="letter-spacing: 0; margin-left: 8px;">' + payFail + '</small>'; } 25723 } else { 25724 //var membership = GLO.ClientProfile.getMembership(membershipId); 25725 var member = _getMember(tr); 25726 25727 if (member.due_mn > 0) { 25728 var due = UTIL.displayMoney(member.due_mn, false, false, true); 25729
25730 if (balance < 0 && !member.is_new_member_period) { 25731 msg = UTIL.displayMoney(-balance, false, false, true) + ' due'; 25732 } else if (status != 50) { 25733 msg = due + ' due'; 25734 } else if (member.bill_dt > new Date()) { 25735 msg = due + ' due ' + member.bill_dt.toSADate(true); 25736 } else { 25737 msg = due + ' due'; 25738 } 25739 } else if (member.price_mn > 0) { 25740 msgCSS = 'color: rgb(20,200,40);'; 25741 25742 if (!UTIL.isEmpty(tr.attr('next_membership_id'))) { 25743 msg = 'next charge of ' + UTIL.displayMoney(member.price_mn, false, false, true) + ' on ' + member.bill_dt.toSADate(true) + ' is paid'; 25744 } else { 25745 var period = UTIL.coalesceInt(tr.attr('billing_period_cd'), member.membership.period); 25746 msg = 'next ' + _cMembership.getPeriodNameCount(period, parseInt(balance/member.price_mn)) + ' paid'; 25747 } 25748 } 25749 } 25750 25751 return '<div id="pop-member-next-pay"> <span id="next-membership-payment" style="' + msgCSS + '">' + msg + '</span>' + btnPayNow + '</div>'; 25752 } 25753 function _getPriceAndNextHtm(price_mn, custom_price_mn, billing_period_cd, next_bill_dt, period_end_dt, status, membership) { 25754 var htmDefaultPrice = '', htm = '<div id="pop-member-price-row" billing_period_cd="' + UTIL.cleanString(billing_period_cd) + '">'; 25755 25756 if (UTIL.coalesce(custom_price_mn, price_mn) == 0) { 25757 var price = 0; 25758 } else { 25759 var price = UTIL.displayMoney(UTIL.coalesceMoney(custom_price_mn, price_mn), true, false, true); 25760 } 25761 25762 if (UTIL.coalesceMoney(custom_price_mn, price_mn) != membership.price) { 25763 htmDefaultPrice = '<small id="membership-default-price">(normal price: ' + UTIL.displayMoney(membership.price, false, false, true) + ')</small>'; 25764 } 25765 25766 if (UTIL.coalesceInt(status, 30) === 50) { 25767 var dt0 = UTIL.coalesceDate(next_bill_dt, new Date(period_end_dt).addDays(1)); 25768 var dt = dt0.toGloDate(), dtString = dt0.toSADate(true); 25769 } else { 25770 var dt = new Date().toGloDate(), dtString = 'now'; 25771 } 25772 25773 if (GLO.Info.roleType > 209) { 25774 var htmBillDate = '<a next_bill_dt="' + dt + '" onclick="GLO.Provider.Membership.Client.changeBillDate()">' + dtString + '</a>'; 25775 } else { 25776 var htmBillDate = '<b>' + dtString + '</b>'; 25777 } 25778 25779 var htmBillPrice = '<input id="Period_Price_mn" type="text" value="' + price + '" onchange="GLO.Provider.Membership.Client.changeBillPrice()" onkeyup="GLO.Provider.Membership.Client.changeBillPrice()"/>'; 25780 htm += '<span id="pop-member-price"><label for="Period_Price_mn">Price</label><b class="dollar-sign">$</b>' + htmBillPrice + htmDefaultPrice + '</span>'; 25781 htm += '<span id="pop-member-next-bill-date"><label for="Next_Bill_dt">Next Bill <i style="">Date</i></label>' + htmBillDate + '</span>'; 25782 25783 return htm + '</div>'; 25784 } 25785 function _getPayNowButton(membershipId, nextMembershipId, dtNextBill, dtPeriodEnd, cid, cname) { 25786 if (!GLO.Data.Staff.canSellProducts) { 25787 return ''; 25788 } 25789 25790 var membership = GLO.ClientProfile.getMembership(membershipId); 25791 25792 if (!UTIL.isEmpty(nextMembershipId)) { 25793 if (!UTIL.isDate(dtNextBill) || new Date(dtPeriodEnd) > new Date(dtNextBill)) { 25794 membership = GLO.ClientProfile.getMembership(nextMembershipId); 25795 } 25796 } 25797 25798 var cname = UTIL.removeQuotes(cname); 25799 var onclickPayNow = 'GLO.Provider.Membership.openPayMembershipFromPopup(' + membership.id + ', ' + membership.inventory_id + ', ' + cid + ', \"' + cname + '\")'; 25800 25801 return '<span id="btnPayMembership" class="btnAdd"><a onclick=\'' + onclickPayNow + '\'>Pay Now</a></span>'; 25802 } 25803 function _getNextPeriodHtm(balance_mn, auto_billing_fl, next_membership_id, isViewOnly, btnPayNow) { 25804 var htmChecked = '', cssBalance = ''; 25805 var htm = '<div id="pop-member-view-next">'; 25806 25807 if (true || balance_mn != 0) { 25808 var disabledAttribute = '', balance = UTIL.displayMoney(balance_mn, true, false, true); 25809 25810 if (UTIL.coalesceMoney(balance_mn) < 0) { 25811 cssBalance = 'has-negative-balance'; 25812 } else if (UTIL.coalesceMoney(balance_mn) > 0) { 25813 cssBalance = 'has-positive-balance'; 25814 } 25815 25816 //if (GLO.Info.roleType < 220) { disabledAttribute = ' disabled="disabled"'; } 25817
25818 if (isViewOnly) { 25819 var balanceInput = '<b class="dollar-sign">$</b> <span class="view-balance-amount">' + UTIL.coalesceString(balance, '0') + '</span>'; 25820 } else { 25821 var balanceInput = '<b class="dollar-sign">$</b><input id="Balance_mn" type="text" value="' + balance + '"/>'; 25822 } 25823 25824 htm += '<span id="pop-member-view-balance" class="' + cssBalance + '"> <label for="Balance_mn">Balance</label>' + balanceInput + '</span>'; 25825 } 25826 25827 if (UTIL.parseBool(auto_billing_fl)) { htmChecked = ' checked="checked"'; } 25828 25829 var htmAutoBill = '<input type="checkbox" id="Auto_Billing_fl"' + htmChecked + '>' + '<label for="Auto_Billing_fl">Auto Billing</label>'; 25830 25831 htm += '<span id="pop-member-auto-bill">' + htmAutoBill + UTIL.cleanString(btnPayNow) + '</span>'; 25832 htm += '</div>'; 25833 25834 if (!UTIL.isEmpty(next_membership_id)) { 25835 var nextMembershipName = UTIL.coalesceString(GLO.ClientProfile.getMembership(next_membership_id).name, 'different type of memberhip'); 25836 var nextHtm = '<b class="next-membership-name" next_membership_id="' + next_membership_id + '">' + nextMembershipName + '</b>'; 25837 var msg = '<span style="display: inline-block; padding-right:12px;">Next period the membership will change to ' + nextHtm + '</span>'; 25838 var btnMerge = '<span id="btnMergeMembership" class="btnAdd"><a onclick="GLO.Provider.Membership.Client.openMergeMembership(this)" style="background: black;">Merge</a></span>'; 25839 htm += '<div id="next-membership-bar" next_membership_id="' + next_membership_id + '">' + msg + btnMerge + '</div>'; 25840 } 25841 25842 return htm; 25843 } 25844 function _getCurrentPeriodHtm(end_dt, period_start_dt, period_end_dt, cid, cname) { 25845 var fnPeriodHistory = 'GLO.Provider.Membership.Client.openMemberPeriodHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)'; 25846 var btnPeriodHistory = '<span id="btnPeriodHistory" class="btnAdd"><a onclick="' + fnPeriodHistory + '"><i>Period</i> History</a></span>'; 25847 25848 if (GLO.Info.roleType < 170) { btnPeriodHistory = ''; } 25849 25850 if (UTIL.isDate(end_dt) && new Date() > new Date(end_dt)) { 25851 var htmCurrentPeriod = '<div id="pop-member-view-end"><label>Membership Ended</label><b>' + end_dt + '</b>' + btnPeriodHistory + '</div>'; 25852 } else { 25853 var htmCurrentPeriod = '<div id="pop-member-view-current"><label>Current <i>Membership</i> Period</label>'; 25854 var pstart = UTIL.cleanString(period_start_dt); 25855 25856 if (GLO.Info.roleType > 199) { 25857 htmCurrentPeriod += '<input type="text" id="Period_Start_dt" pattern="[0-9]*" value="' + pstart + '" onclick="GLO.UI.displayDatePicker(this)" original_dt="' + pstart + '"/>'; 25858 htmCurrentPeriod += '<b style="font-size: 20px;"> - </b> <input type="text" id="Period_End_dt" pattern="[0-9]*" value="' + UTIL.cleanString(period_end_dt) + '"/>'; 25859 htmCurrentPeriod += '<style> .ui-datepicker { z-index: 9999 !important; } </style>'; 25860 } else { 25861 htmCurrentPeriod += '<b>' + period_start_dt + ' - ' + period_end_dt + '</b>'; 25862 } 25863 25864 htmCurrentPeriod += btnPeriodHistory + '</div>'; 25865 } 25866 25867 return htmCurrentPeriod; 25868 } 25869 25870 function _getServiceListHtm(arrService, cid, cname) { 25871 var maxlen = 30, htm = '<ul id="membership-service-list">', rowCss = 'odd-row'; 25872 if (innerWidth < 800) { maxlen = 20; } 25873 25874 for (var i=0; i < arrService.length; i++) { 25875 var sgid = UTIL.cleanString(arrService[i].service_group_id), svcid = UTIL.cleanString(arrService[i].service_id); 25876 var msid = arrService[i].membership_service_id; 25877 var svcName = UTIL.maxString(UTIL.coalesce(arrService[i].service_vc, arrService[i].service_group_vc, 'any service'), maxlen); 25878 var svcLabelCount = '', svcLabel = '<span class="membership-service-label" title="' + svcName + '">' + svcName + '</span>'; 25879 var discountLabel = _getDiscountLabel(arrService[i].discount_mn, arrService[i].discount_pct, true); 25880 var limit = arrService[i].limit_nr, limitAdjust = arrService[i].limit_adjust_nr; 25881 var limitPeriod = UTIL.coalesceInt(limitAdjust, limit); 25882 var removeCustomSvc = '', isCustomService = UTIL.parseBool(arrService[i].custom_service_fl); 25883 25884 var apptLabel = _getLimitLabel(i + 1, arrService[i].remaining_nr, limit, limitAdjust, arrService[i].appointments.length, arrService[i].price_mn); 25885 25886 if (isCustomService) { 25887 var icon = '<span class="ui-icon ui-icon-circle-close"></span>'; 25888 removeCustomSvc = '<span class="membership-service-custom-remove" onclick="GLO.Provider.Membership.Client.removeCustomService(this)">' + icon + '</span>'; 25889 rowCss += ' is-custom-service'; 25890 } 25891 25892 if (limit < 900) { 25893 svcLabelCount = '<span class="membership-service-label-count">' + limitPeriod + '</span>'; 25894 } 25895 25896 if (UTIL.isNumber(limitPeriod)) { 25897 limitPeriod -= arrService[i].appointments.length; 25898 } else { 25899 limitPeriod = ''; 25900 } 25901 25902 htm += '<li class="membership-service-row ' + rowCss + '" service_group_id="' + sgid + '" service_id="' + svcid + '" original_limit_nr="' + limitPeriod 25903 + '" membership_service_id="' + msid + '">' + removeCustomSvc + svcLabelCount + svcLabel + discountLabel + apptLabel + '</li>'; 25904 25905 htm += _getApptListHtm(arrService[i].appointments, cid, rowCss); 25906 25907 if (rowCss === 'odd-row') { rowCss ='even-row'; } else { rowCss ='odd-row'; } 25908 } 25909 25910 htm += '</ul>'; 25911 25912 if (GLO.Info.roleType > 219) {
25913 var fnOpenAddCustomService = 'GLO.Provider.Membership.Client.openAddCustomService(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)'; 25914 htm += '<div id="member-service-add-custom"> <span id="btnAddCustomService" class="btnAdd btnAction2"><a onclick="' + fnOpenAddCustomService + '">Add Custom Service</a></span> </div>'; 25915 } 25916 25917 return '<div id="">' + htm + '</div>'; 25918 } 25919 25920 function _getApptListHtm(arrAppt, cid, rowCss) { 25921 var htm = ''; 25922 25923 for (var a=0; a < arrAppt.length; a++) { 25924 var scheduleId = arrAppt[a].schedule_id, smid = arrAppt[a].schedule_multi_id, svcid = arrAppt[a].service_id, sid = arrAppt[a].staff_id, apptStatus = arrAppt[a].appt_status_cd; 25925 var onclick = 'GLO.Provider.Membership.Client.openAppt(' + smid + ')'; 25926 var dtAppt = new Date(arrAppt[a].start_dt); 25927 25928 if (GLO.Info.isFirefox) { 25929 dtAppt = new Date(arrAppt[a].start_dt.replace(' am', ':00').replace(' pm', ':00')); 25930 25931 if (arrAppt[a].start_dt.indexOf('pm') !== -1) { 25932 dtAppt = new Date(dtAppt.setHours(dtAppt.getHours() + 12)); 25933 } 25934 } 25935 25936 var lbl = '<a onclick="' + onclick + '">' + dtAppt.toPrettyDate() + '</a>'; 25937 htm += '<li class="membership-appt-row ' + rowCss + '" schedule_id="' + scheduleId + '" schedule_multi_id="' + smid + '" service_id="' + svcid + '" staff_id="' + sid + '">' + lbl + '</li>'; 25938 } 25939 25940 return htm; 25941 } 25942 25943 function _getServiceTotalPrice(rowNumber, price) { 25944 var htm = '<span class="adjust-total-service-price">' 25945 + '<label for="Service_Commission_Price_mn' + rowNumber + '">Comm. Price</label>' 25946 + '<b class="dollar-sign">$</b>' 25947 + '<input type="text" id="Service_Commission_Price_mn' + rowNumber + '" class="cost" value="' + UTIL.displayMoney(price, true, false, true) + '"/>' 25948 + '<b class="help-icon4" onclick="GLO.Provider.Membership.openServicePriceHelp(this)">?</b>' 25949 + '</span>'; 25950 return htm; 25951 } 25952 function _getLimitLabel(rowNumber, remaining, limit, limitAdjust, apptCount, price) { 25953 var htm = '<span class="membership-remaining-label">'; 25954 25955 if (limit < 500) { 25956 var fns = ' onchange="GLO.Provider.Membership.Client.adjustChange(this, event)" onkeyup="UI.verifyNumberInput(this, true)"'; 25957 htm += '<input type="number" id="Remaining_nr' + rowNumber + '" class="remaining" value="' + remaining + '" min="-500" max="500"' + fns + '/>'; 25958 htm += '<label for="Remaining_nr' + rowNumber + '" class="remaining-label">' + UTIL.makePlural('service', remaining) + ' remaining</label>'; 25959 25960 htm += _getServiceTotalPrice(rowNumber, price); 25961 25962 htm += '<span class="each-period">' 25963 + '<label for="Limit_nr' + rowNumber + '">Each Period</label>' 25964 + '<input type="number" id="Limit_nr' + rowNumber + '" class="limit" value="' + limit + '" min="-500" max="500" onkeyup="UI.verifyNumberInput(this, true)"/>' 25965 + '</span>'; 25966 } else { 25967 htm += '<small>Unlimited</small>'; 25968 } 25969 25970 return htm + '</span>'; 25971 } 25972 25973 function _getDiscountLabel(discountMoney, discountPercent, isHtm) { 25974 if (discountMoney > 0) { 25975 var lbl = UTIL.displayMoney(discountMoney) + ' off'; 25976 } else if (discountPercent) { 25977 var lbl = discountPercent + '% off'; 25978 } else { 25979 var lbl = 'Free'; 25980 } 25981 25982 return '<i class="membership-discount-label">' + lbl + '</i>'; 25983 } 25984 25985 function _getHiddenHtm(membership_id, cid) { 25986 var htm = '<input type="hidden" id="Membership_id" value="' + membership_id + '"/>'; 25987 htm += '<input type="hidden" id="Client_id" value="' + cid + '"/>'; 25988 return htm; 25989 } 25990 25991 function _openAddMember(jclient, cid, cname) { 25992 var btnCardOnFile = UTIL.cleanString(jclient.find('#client-card-on-file').find('#btnViewCardOnFile, #btnAddCardOnFile').outerHTML()); 25993 25994 if (!UTIL.isEmpty(btnCardOnFile)) { btnCardOnFile = '<div id="pop-member-card-btn" style="padding-bottom: 16px;">' + btnCardOnFile + '</div>'; } 25995 25996 var dd = _cMembership.getMembershipDropDown();
25997 var htm = '<div id="pop-member-add">' + btnCardOnFile 25998 + '<div id="pop-member-add-name">' 25999 + '<input type="hidden" id="Client_id" value="' + cid + '"/>' 26000 + '<input type="hidden" id="Client_Name_vc" value="' + cname + '"/>' 26001 + '<label for="Membership_id">Membership</label>' + dd 26002 + '</div>' 26003 + '<div id="pop-member-add-start">' 26004 + '<label for="Member_Start_dt">Start Date</label>' 26005 + '<input type="text" id="Member_Start_dt" pattern="[0-9]*"/> <style> .ui-datepicker { z-index: 9999 !important; } </style>' 26006 + '</div>' 26007 + '</div>'; 26008 var h1 = 'Add Member'; 26009 26010 if (!UTIL.isEmpty(cname)) { h1 += ': ' + cname; } 26011 26012 var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.Membership.Client.saveCreateMember); 26013 var jbtns = jpop.find('.pop-buttons'); 26014 jbtns.append('<span class="btnAdd"><a onclick="GLO.Provider.Membership.Client.openBuyMembership()">Pay Now</a></span>'); 26015 26016 jpop.find('#Member_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, minDate: "-9M", maxDate: "+6M" }); 26017 } 26018 _cMemberClient.openBuyMembership = function() { 26019 var jpop = $('#pop-member-add').closest('.glopop'); 26020 var mid = jpop.find('#Membership_id').val(), start = jpop.find('#Member_Start_dt').val(); 26021 var cid = jpop.find('#Client_id').val(), cname = jpop.find('#Client_Name_vc').val(); 26022 26023 if (UTIL.isEmpty(mid)) { 26024 GLO.Popup.Warning.open('Please Select Membership', 'Membership Required'); 26025 return; 26026 } 26027 26028 GLO.Popup.close(jpop); 26029 GLO.Popup.Processing.open('<div id="pop-procesing-price-wait">Creating Membership Purchase Ticket...</div>', 'Creating Ticket'); 26030 26031 setTimeout(function() { //= make async so UI closes popup (see above code) immediately 26032 GLO.Provider.Membership.openPayMembership2(mid, null, cid, cname, null, start); 26033 }, 90); 26034 } 26035 26036 function _getMonthByPeriod(periodCode) { 26037 if (periodCode == 30) { 26038 return 1; 26039 } else if (periodCode == 40) { 26040 return 2; 26041 } else if (periodCode == 50) { 26042 return 3; 26043 } else if (periodCode == 60) { 26044 return 6; 26045 } else if (periodCode == 70) { 26046 return 12; 26047 } 26048 } 26049 26050 function _allowChangeMemberBillingPeriod(memberPeriod, billPeriod) { 26051 if (memberPeriod == 20 && $('#pop-warn-weekly-membership-period').closest('.glopop').length === 0) { 26052 if (!UTIL.isEmpty(billPeriod)) { 26053 var msg1 = 'Cannot change billing period on weekly membership'; 26054 var msg2 = 'When membership period is weekly, then billing period is always weekly'; 26055 var htm = '<div id="pop-warn-weekly-membership-period"><div>' + msg1 + '</div><div style="letter-spacing: 0; font-size: smaller;">' + msg2 + '</div></div>'; 26056 26057 GLO.Popup.Warning.open(htm, 'Weekly Membership'); 26058 return false; 26059 } else { 26060 $('#pop-member-change-bill-period').addClass('hide'); 26061 } 26062 } 26063 26064 return true; 26065 } 26066 26067 _cMemberClient.setPricePerPeriod = function() { 26068 var jpop = $('#pop-member-view').closest('.glopop'); 26069 var periodPrice = _cMemberClient.getPricePerPeriod(jpop); 26070 26071 var membershipId = jpop.find('#Membership_id').val(); 26072 var membership = GLO.ClientProfile.getMembership(membershipId); 26073 var memberMonthCount = _cMembership.getPeriodMonthCount(membership.period); 26074
26075 var billPeriod = jpop.find('#Billing_Period_cd').find('option:selected').attr('value'); //jpop.find('#Billing_Period_cd').val(); 26076 var billMonthCount = _cMembership.getPeriodMonthCount(billPeriod); 26077 26078 var memberPrice = UTIL.coalesceMoney(jpop.find('#Period_Price_mn').val(), membership.price); 26079 26080 if (!_allowChangeMemberBillingPeriod(membership.period, billPeriod)) { return; } 26081 26082 if (memberMonthCount == 0 || billMonthCount == 0 || memberPrice == 0 || billMonthCount >= memberMonthCount) { 26083 jpop.find('#pop-member-billing-period-price').addClass('hide').find('#Bill_Period_mn').text(''); 26084 } else { 26085 var billPrice = UTIL.displayMoney(memberPrice * billMonthCount/memberMonthCount, true, false, true); 26086 jpop.find('#pop-member-billing-period-price').removeClass('hide').find('#Bill_Period_mn').text(billPrice); 26087 } 26088 } 26089 26090 _cMemberClient.getPricePerPeriod = function(jpop) { 26091 var membershipPrice = UTIL.coalesceMoney(jpop.find('#pop-member-price').find('input').val());
26092 var billPeriod = jpop.find('#Billing_Period_cd').val(); 26093 var dtNext = jpop.find('#Next_Bill_dt').val(), dtEnd = jpop.find('#Period_End_dt').val(); 26094 var mid = jpop.find('#Membership_id').val(); 26095 26096 return _cMemberClient.getPricePerPeriod2(mid, membershipPrice, billPeriod, dtNext, dtEnd); 26097 } 26098 26099 _cMemberClient.getPricePerPeriod2 = function(mid, membershipPrice, billPeriod, dtNext, dtEnd) { 26100 if (UTIL.isEmpty(mid) || UTIL.isEmpty(billPeriod) || !UTIL.isDate(dtNext) || !UTIL.isDate(dtEnd)) { 26101 var periodPrice = membershipPrice; 26102 } else { 26103 //var membershipPeriod = GLO.ClientProfile.getMembership(mid).period; 26104 //var membershipMonths = _getMonthByPeriod(membershipPeriod), billMonths = _getMonthByPeriod(billPeriod); 26105 var payPeriods = _getPayPeriods(billPeriod, dtNext, dtEnd); 26106 26107 if (payPeriods > 0) { 26108 var periodPrice = membershipPrice / payPeriods; 26109 } else { 26110 var periodPrice = 0; 26111 } 26112 } 26113 26114 return UTIL.displayMoney(periodPrice, false, false, true); 26115 } 26116 26117 function _getPayPeriods(billPeriod, dtNext, dtEnd) { 26118 dtNext = new Date(dtNext); 26119 dtEnd = new Date(dtEnd); 26120 26121 var monthsInPeriod = _getMonthByPeriod(billPeriod); 26122 var monthDiff = dtNext.getMonthDiff(dtEnd); 26123 26124 return Math.round(monthDiff/monthsInPeriod); 26125 } 26126 26127 _cMemberClient.changeBillDateToDefault = function() { 26128 var jpop = $('#pop-member-view').closest('.glopop'); 26129 var dt = new Date(jpop.find('#Period_End_dt').val()).addDays(1).toGloDate(); 26130 26131 var jnext = jpop.find('#Next_Bill_dt'); 26132 UI.highlight(jnext, 100, 6400, true); 26133 26134 setTimeout(function() { 26135 jnext.val(dt).change(); 26136 jpop.find('#hello-bar-change-next-bill').remove(); 26137 }, 2400); 26138 } 26139 _cMemberClient.changeBillDate = function() { 26140 var jpop = $('#pop-member-view').closest('.glopop'); 26141 var jdt = jpop.find('#pop-member-next-bill-date').find('a'); 26142 var htmDateInput = '<input id="Next_Bill_dt" type="text" pattern="[0-9]*" value="' + jdt.attr('next_bill_dt') + '"/>'; 26143 26144 //var htmDate = '<span id="pop-member-next-bill-date"> <label for="Next_Bill_dt">Next Bill Date</label>' + htmDateInput + '</span>'; 26145 var htmDollarSign = '<b class="dollar-sign">$</b>'; 26146 var htmPeriodPrice = '<span id="pop-member-billing-period-price" title="Billing Period Price"> <label for="Bill_Period_mn">Bill Period</label> ' + htmDollarSign + '<b id="Bill_Period_mn"></b> </span>'; 26147 var htmPeriodLength = '<span id="pop-member-period-length">
26147 <label for="Billing_Period_cd">Billing Period</label>' + _getPeriodDropDown('Billing_Period_cd') + '</span>'; 26148 var htm = '<div id="pop-member-change-bill-period">' + htmPeriodPrice + htmPeriodLength + '</div>'; 26149 26150 jpop.find('#pop-member-change-bill-period').remove(); 26151 jpop.find('#pop-member-price-row').before(htm); 26152 jpop.find('#Billing_Period_cd').change(GLO.Provider.Membership.Client.changeBillingPeriod); 26153 26154 jdt.replaceWith(htmDateInput); 26155 jpop.find('#Next_Bill_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 26156 jpop.find('#Next_Bill_dt').change(GLO.Provider.Membership.Client.changeNextBillDate); 26157 _cMemberClient.setPricePerPeriod(); 26158 } 26159 26160 _cMemberClient.changeMembership = function() { 26161 _cMemberClient.setPricePerPeriod(); 26162 } 26163 _cMemberClient.changeNextBillDate = function() { 26164 //var jpop = $('#pop-member-view').closest('.glopop'); 26165 _cMemberClient.setPricePerPeriod(); 26166 } 26167 _cMemberClient.changeBillPrice = function() { 26168 _cMemberClient.setPricePerPeriod(); 26169 } 26170 _cMemberClient.changeBillingPeriod = function() { 26171 _cMemberClient.setPricePerPeriod(); 26172 return; 26173 /* 26174 var jpop = $('#pop-member-view').closest('.glopop');
26175 var bp = jpop.find('#Billing_Period_cd').val(); 26176 var dt = jpop.find('#Period_Start_dt').val(); 26177 var dt2 = new Date(jpop.find('#Period_End_dt').val()); 26178 26179 if (!UTIL.isDate(dt)) { return ''; } 26180 26181 dt = new Date(dt); 26182 var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds 26183 26184 if (UTIL.isEmpty(bp)) { 26185 var dtNext = dt2; 26186 } else if (bp == 20) { //weekly 26187 var dtTemp = new Date(dt.setMonth(dt.getMonth()+1)); 26188 var halfAMonth = Math.round((dtTemp.getTime() - dt.getTime())/oneDay/2); 26189 var dtNext = new Date(dt.addDays(halfAMonth)); 26190 } else if (bp == 30) { //monthly 26191 var dtNext = new Date(dt.setMonth(dt.getMonth() + 1)); 26192 } else if (bp == 40) { //bi-monthly 26193 var dtNext = new Date(dt.setMonth(dt.getMonth() + 2)); 26194 } else if (bp == 50) { //quarterly 26195 var dtNext = new Date(dt.setMonth(dt.getMonth() + 3)); 26196 } else if (bp == 60) { //semi-annual 26197 var dtNext = new Date(dt.setMonth(dt.getMonth() + 6)); 26198 } else if (bp == 70) { //annual 26199 var dtNext = new Date(dt.setFullYear(dt.getFullYear() + 1)); 26200 } 26201 26202 if (dt2 > new Date() && dtNext > new Date()) { 26203 jpop.find('#Next_Bill_dt').val(dtNext.toGloDate()); 26204 } else { 26205 jpop.find('#Next_Bill_dt').focus(); 26206 } 26207 26208 _cMemberClient.setPricePerPeriod(); 26209 */ 26210 } 26211 26212 _cMemberClient.displayChangeMembership = function() { 26213 var jpop = $('#pop-member-view').closest('.glopop'); 26214 var membershipId = jpop.find('#Membership_id').attr('id', 'Orig_Membership_id').val(); 26215 26216 var jname = jpop.find('#pop-member-view-name'); 26217 var dd = _cMembership.getMembershipDropDown(); 26218 jname.html(dd); 26219 jpop.find('#Membership_id').val(membershipId).change(GLO.Provider.Membership.Client.setPricePerPeriod).find('option[value=""]').remove(); 26220 } 26221 26222 _cMemberClient.removeCustomService = function(icon) { 26223 var jpop = $('#pop-member-view').closest('.glopop'); 26224 var membershipName = UTIL.coalesceString(jpop.find('#pop-member-view-name > b').text(), jpop.find('#pop-member-view-name #Membership_id option:selected').text()); 26225 var clientName = jpop.find('.client-name-link').text(); 26226 26227 var msg1 = '<p>This service is not normally on this ' + membershipName + ' memberships</p>'; 26228 var msg2 = '<p>Would you like to remove this service from ' + clientName + ' membership?</p>'; 26229 var msg3 = '<p> </p>'; 26230 var htm = '<div id="pop-confirm-member-service-remove">' + msg1 + msg2 + msg3 + '</div>'; 26231 26232 var msid = $(icon).closest('li').attr('membership_service_id'); 26233 26234 var fn = function() { 26235 GLO.Provider.Membership.Client.removeCustomServiceConfirmed(msid); 26236 } 26237 26238 GLO.Popup.Confirm.open(htm, 'Remove Custom Member Service?', fn); 26239 26240 } 26241 _cMemberClient.removeCustomServiceConfirmed = function(msid) { 26242 var jpop = $('#pop-member-view'); 26243 var cid = jpop.find('#Client_id').val(); 26244 var uri = GLO.Link.WebsiteDomain + 'membership/RemoveCustomService?cid=' + cid + '&msid=' + msid; 26245 26246 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 26247 .success(function(data, textStatus, jqXHR) { 26248 var jd = $(data); 26249 26250 if (jd.hasClass('warning')) { 26251 GLO.Popup.Warning.open(data, 'Problem Remove Service'); 26252 } else { 26253 jpop.find('li.membership-service-row.is-custom-service[membership_service_id="' + msid + '"]').remove(); 26254 GLO.Popup.Success.open('Custom Service Removed', 'Change Successful'); 26255 } 26256 }) 26257 .error(function(jqXHR, textStatus, errorThrown) { }); 26258 } 26259 26260 _cMemberClient.adjustChange = function(input, event) { 26261 var li = $(input).closest('li.membership-service-row'); 26262 var jtotal = li.find('.membership-service-label-count'); 26263 var remaining = UTIL.coalesceInt(input.value, 0); //var limit = UTIL.coalesceInt(li.attr('original_limit_nr'));
26264 var apptCount = _getMemberServiceApptCount(li); 26265 26266 jtotal.text(remaining + apptCount); 26267 } 26268 26269 function _getMemberServiceApptCount(li) { 26270 var apptCount = 0; 26271 26272 while (li.next().hasClass('membership-appt-row')) { 26273 li = li.next(); 26274 ++apptCount; 26275 } 26276 26277 return apptCount; 26278 } 26279 26280 _cMemberClient.openAppt = function(smid) { 26281 GLO.Popup.close(); 26282 UserPortal.Edit.get(null, smid, true, UserPortal.Edit.isCalendar, false); 26283 } 26284 26285 function _getUpdateMember(jpop, isVerify, isNextPeriod) { 26286 var jPeriodStart = jpop.find('#Period_Start_dt'); 26287 var periodStart = UTIL.cleanString(jPeriodStart.val()); 26288 var periodEnd = UTIL.cleanString(jpop.find('#Period_End_dt').val()); 26289 26290 if (UTIL.isDate(periodEnd)) { periodEnd = new Date(periodEnd).addDays(1).toGloDate(); } 26291 26292 var start = new Date(jpop.find('#pop-member-view-start').attr('start_dt')).toGloDate(); 26293 26294 if (new Date(jPeriodStart.attr('original_dt')).toGloDate() == start) { //= if start is same as current-period-start, changing period start also changes start date 26295 start = periodStart; 26296 } 26297 26298 var membershipId = jpop.find('#Membership_id').val(); 26299 var autoBill = jpop.find('#Auto_Billing_fl').prop('checked'); 26300 var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val()); 26301 var jsonPost = { "membership": membershipId, "autobill": autoBill, "start": start, "periodstart": periodStart, "periodend": periodEnd, "balance": balance }; 26302 var origMembershipId = jpop.find('#Orig_Membership_id').val();
26303 var jBillPeriod = jpop.find('#Billing_Period_cd'); 26304 26305 if (jBillPeriod.length > 0) { 26306 var billPeriod = jBillPeriod.val(); 26307 } else { 26308 var billPeriod = jpop.find('#pop-member-price-row').attr('billing_period_cd'); 26309 } 26310 26311 var priceCustom = jpop.find('#pop-member-price').find('input').val(); 26312 var priceDefault = UTIL.coalesceMoney(GLO.ClientProfile.getMembership(membershipId).price); 26313 var dtNextBill = jpop.find('#Next_Bill_dt').val(); 26314 var mstatus = jpop.find('#Member_Status_cd').val(); 26315 26316 if (UTIL.isDate(dtNextBill) && dtNextBill != periodEnd) { jsonPost.billdate = dtNextBill; } 26317 if (!UTIL.isEmpty(priceCustom) && UTIL.coalesceMoney(priceCustom) != priceDefault) { jsonPost.price = UTIL.coalesceMoney(priceCustom); } 26318 if (!UTIL.isEmpty(billPeriod)) { jsonPost.billperiod = billPeriod; } 26319 if (!UTIL.isEmpty(mstatus)) { jsonPost.status = mstatus; } 26320 26321 if (!UTIL.isEmpty(origMembershipId) && membershipId != origMembershipId) { 26322 if (!isVerify || isNextPeriod) { 26323 jsonPost.nextmembership = membershipId; 26324 jsonPost.membership = origMembershipId; 26325 } 26326 } else if (jpop.find('select#Membership_id').length === 0) { //= not changing membership so keep next-membership (if exists) 26327 var nextMembershipId = jpop.find('#next-membership-bar').attr('next_membership_id'); 26328 26329 if (!UTIL.isEmpty(nextMembershipId)) { 26330 jsonPost.nextmembership = nextMembershipId; 26331 } 26332 } 26333 26334 return jsonPost; 26335 } 26336 26337 function _askInactiveOnMembershipChange(jpop, jsonPost) { 26338 if (jpop.find('.member-status-bubble').attr('member_status_cd') != 900) { return; } 26339 26340 var msg1 = '<p>This member is In-Active</p>'; 26341 var msg2 = '<p>Do you want to Activate this membership?</p>'; 26342 var htm = '<div id="pop-confirm-keep-inactive">' + msg1 + msg2 + '</div>'; 26343 26344 var fnSave = function() { GLO.Provider.Membership.Client.save(true); } 26345 var fnActivate = function() { 26346 var jpop = $('#pop-member-view'); 26347 jpop.find('.member-status-bubble').click(); 26348 jpop.find('#Member_Status_cd').val(50); 26349 GLO.Provider.Membership.Client.save(true); 26350 } 26351 26352 var jpop = GLO.Popup.Confirm.open(htm, 'Member Currently In-Active', fnActivate, fnSave).getPopup(); 26353 var btnCancel = '<span class="btnCancel" onclick="GLO.Popup.close()" style="float: none; margin: 0; margin-left: -40px; padding: 0 12px;"><a>Close</a></span>'; 26354 jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" }); 26355 26356 jpop.find('.btnNo').removeClass('btnNo').addClass('btnSave').find('>a').text('Keep In-Active').css({ "position": "absolute", "left": "8px" }); 26357 jpop.find('.btnYes').before(btnCancel); 26358 jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('>a').text('Make Active').css({ "position": "absolute", "right": "8px" }); 26359 26360 return true; 26361 } 26362 function _requireVerifyMembershipChange(jpop, jsonPost) { 26363 if (UTIL.isEmpty(jsonPost.nextmembership)) { return false; } 26364 26365 var nm = jpop.find('#Membership_id').find('option[value="' + jsonPost.nextmembership + '"]').text(); 26366 var msg = 'When do you want to change the membership to: ' + nm + '?'; 26367 var lblChange = 'Change '; 26368 26369 if (innerWidth < 400) { lblChange = ''; } 26370 26371 var fnNow = function() { GLO.Provider.Membership.Client.save(true); } 26372 var fnNext = function() { GLO.Provider.Membership.Client.save(true, true); } 26373 26374 var jpop = GLO.Popup.Confirm.open(msg, 'Confirm Membership Change', fnNext, fnNow).getPopup(); 26375 var btnCancel = '<span class="btnCancel" onclick="GLO.Popup.close()" style="float: none; margin: 0; margin-left: -40px; padding: 0 12px;"><a>Cancel</a></span>'; 26376 jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" }); 26377 26378 jpop.find('.btnNo').removeClass('btnNo').addClass('btnSave').find('>a').text(lblChange + 'Now').css({ "position": "absolute", "left"
26378: "8px" }); 26379 jpop.find('.btnYes').before(btnCancel); 26380 jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('>a').text(lblChange + 'Next Period').css({ "position": "absolute", "right": "8px" }); 26381 26382 return true; 26383 } 26384 26385 _cMemberClient.saveAutoBill = function() { 26386 var jpop = $('#pop-member-pay-summary').closest('.glopop'); 26387 var mcid = jpop.find('#Membership_Client_id').val(); 26388 var autoBill = jpop.find('#Auto_Billing_fl').prop('checked'); 26389 26390 var tr = $('#membership-report').find('tr[membership_client_id="' + mcid + '"]'); 26391 var hasCardOnFile = tr.attr('card_on_file_fl'); 26392 var tdAutoBill = tr.find('.membership-column-auto-bill'); 26393 26394 var uri = GLO.Link.WebsiteDomain + 'membership/AutoBilling?mcid=' + mcid + '&autobill=' + autoBill; 26395 26396 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 26397 .success(function(data, textStatus, jqXHR) { 26398 if (autoBill) { 26399 tdAutoBill.html('<i class="is-auto-bill" title="Auto-Billing enabled">✔</i>'); 26400 } else if (hasCardOnFile || UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 59) { 26401 tdAutoBill.html('<b>+</b>'); 26402 } else { 26403 tdAutoBill.html('<b>-</b>'); 26404 } 26405 }) 26406 .error(function(jqXHR, textStatus, errorThrown) { }); 26407 } 26408 _cMemberClient.saveCreateMember = function() { 26409 var jpop = $('#pop-member-add').closest('.glopop'); 26410 var cid = jpop.find('#Client_id').val(), mid = jpop.find('#Membership_id').val(), start = jpop.find('#Member_Start_dt').val(); 26411 var uri = GLO.Link.WebsiteDomain + 'membership/CreateMember?client=' + cid + '&membership=' + mid + '&start=' + start; 26412 var jbtn = jpop.find('.btnSave'); 26413 26414 GLO.UI.Form.beginProcessing(jbtn); 26415 26416 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 26417 .success(function(data, textStatus, jqXHR) { 26418 GLO.Popup.close(jpop); 26419 var jclient = $('form#client-form'); 26420 26421 if (jclient.find('#Client_id').val() === cid) { 26422 jclient.find('#Membership_id').val(mid); 26423 26424 GLO.ClientProfile.initMembershipButton(jclient, mid); 26425 GLO.Provider.Membership.refreshReportOnEdit(); 26426 } 26427 }) 26428 .error(function(jqXHR, textStatus, errorThrown) { 26429 GLO.UI.Form.resetProcessing(); 26430 }); 26431 } 26432 _cMemberClient.save = function(isVerify, isNextPeriod) { 26433 var jpop = $('#pop-member-add').closest('.glopop'); 26434 26435 if (jpop.length === 0) { 26436 jpop = $('#pop-member-view').closest('.glopop'); 26437 26438 var jsonPost = _getUpdateMember(jpop, isVerify, isNextPeriod); 26439 var membershipId = jsonPost.membership; 26440 26441 if (!isVerify) { 26442 if (_requireVerifyMembershipChange(jpop, jsonPost)) { return; } 26443 if (_askInactiveOnMembershipChange(jpop, jsonPost)) { return; } 26444 } 26445 } else { 26446 var membershipId = jpop.find('#Membership_id').val(); 26447 var start = UTIL.cleanString(jpop.find('#Member_Start_dt').val()); 26448 var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val()); 26449 var jsonPost = { "membership": membershipId, "periodstart": start, "balance": balance }; 26450 } 26451 26452 var svcXml = '', jsvc = $('#membership-service-list').find('li.membership-service-row'); 26453 26454 for (var i=0; i < jsvc.length; i++) { 26455 var li = jsvc.eq(i); 26456 var msid = UTIL.cleanString(li.attr('membership_service_id')); 26457 26458 if (li.find('.remaining').length) { //= NOT unlimited 26459 var cost = li.find('.adjust-total-service-price .cost').val(); 26460 var more = '', remaining = li.find('.remaining').val(); 26461 var limitThisPeriod = UTIL.coalesceInt(li.find('.membership-service-label-count').text()); 26462 var limitEachPeriod = li.find('.limit').val(); 26463 26464 var apptCount = _getMemberServiceApptCount(li); 26465 var defaultLimit = GLO.ClientProfile.getMembershipService(msid).limit_nr; 26466 26467 if (UTIL.isEmpty(cost)) { 26468 cost = ''; 26469 } else { 26470 cost = UTIL.coalesceMoney(cost); 26471 } 26472 26473 if (UTIL.isEmpty(limitEachPeriod) || limitEachPeriod == defaultLimit) { //= if different then default or limit is empty (setting field to empy = reset to default) 26474 limitEachPeriod = ''; 26475 } 26476 26477 if (UTIL.isEmpty(remaining) || limitThisPeriod == UTIL.coalesceInt(limitEachPeriod, defaultLimit)) { 26478 limitThisPeriod = ''; 26479 } else if (remaining == 0 && remaining != UTIL.coalesceInt(limitEachPeriod, defaultLimit, 0) - UTIL.coalesceInt(apptCount, 0)) {
26480 more = ' adjust_to_zero_fl="1"'; 26481 } 26482 26483 if (cost > 0 || limitThisPeriod !== '' || limitEachPeriod !== '' || defaultLimit != li.attr('original_limit_nr')) { 26484 svcXml += '<li membership_service_id="' + msid + '" limit_adjust_nr="' + limitThisPeriod + '" limit_nr="' + limitEachPeriod + '" price_mn="' + cost + '"' + more + '/>'; 26485 } 26486 } 26487 } 26488 26489 if (!UTIL.isEmpty(svcXml)) { 26490 jsonPost.services = UTIL.htmlEncode('<ul>' + svcXml + '</ul>'); 26491 } 26492 26493 var cid = jpop.find('#Client_id').val(); 26494 var uri = GLO.Link.WebsiteDomain + 'membership/EditClient?cid=' + cid; 26495 var jbtn = jpop.find('.btnSave'); 26496 26497 GLO.UI.Form.beginProcessing(jbtn); 26498 26499 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonPost }) 26500 .success(function(data, textStatus, jqXHR) { 26501 GLO.Popup.close(jpop); 26502 var jclient = $('form#client-form'); 26503 jclient.find('#Membership_id').val(membershipId); 26504 26505 GLO.ClientProfile.initMembershipButton(jclient, membershipId); 26506 GLO.Provider.Membership.refreshReportOnEdit(); 26507 }) 26508 .error(function(jqXHR, textStatus, errorThrown) { 26509 GLO.UI.Form.resetProcessing(); 26510 }); 26511 } 26512 26513 _cMemberClient.remove = function() { 26514 //var jclient = $('#clientProfileGrid'); 26515 //var cname = UTIL.coalesce(jclient.find('#Full_Name_vc').val(), jclient.find('#First_Name_vc').val() + ' ' + jclient.find('#Last_Name_vc').val()); 26516 26517 var jpop = $('#pop-member-view').closest('.glopop'); 26518 var cname = UTIL.directTagOnly(jpop.find('h1 a.client-name-link')); 26519 var cid = jpop.find('#Client_id').val(); 26520 26521 var htm = '<div id="pop-confirm-cancel-member">' + 'Are you sure you want to cancel the membership for ' + cname + '?</div>'; 26522 26523 GLO.Popup.Warning.open(htm, 'Confirm Cancel Membership', GLO.Provider.Membership.Client.removeConfirmed); 26524 } 26525 26526 _cMemberClient.removeConfirmed = function() { 26527 var jpop = $('#pop-member-view').closest('.glopop'); 26528 var membershipId = jpop.find('#Membership_id').val(), cid = jpop.find('#Client_id').val(); 26529 var uri = GLO.Link.WebsiteDomain + 'membership/DeleteClient?membership=' + membershipId + '&cid=' + cid; 26530 26531 jpop = jpop; 26532 var jbtn = jpop.find('.btnDelete'); 26533 26534 GLO.UI.Form.beginProcessing(jbtn); 26535 26536 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} }) 26537 .success(function(data, textStatus, jqXHR) { 26538 GLO.Popup.close(jpop); 26539 var jclient = $('form#client-form'); 26540 jclient.find('#Membership_id').val(''); 26541 GLO.ClientProfile.initMembershipButton(jclient); 26542 26543 GLO.Provider.Membership.refreshReportOnEdit(); 26544 }) 26545 .error(function(jqXHR, textStatus, errorThrown) { 26546 GLO.UI.Form.resetProcessing(); 26547 }); 26548 } 26549 26550 return _cMemberClient; 26551 })(); 26552 26553 _cMembership.Help = (function() { 26554 function _cMemberHelp() {} 26555 26556 _cMemberHelp.openHowToSetup = function(stepNumber) { 26557 SA.Help.openReportHelp('#pop-how-to-guide-membership', stepNumber, 'info/MembershipHelp'); 26558 } 26559 _cMemberHelp.openHowToSetupLocal = function() { 26560 var isMembershipSetupScreen = $('#manage-membership #membership-list').length; 26561 var htm = _getHtmHowToSetup(isMembershipSetupScreen); 26562 } 26563 26564 _cMemberHelp.openPeriodInfo = function() { 26565 //var isMembershipSetupScreen = $('#manage-membership #membership-list').length; 26566 var htm = '<div id="pop-help-membership-period">' + $('#pop-membership-edit-help-period').html() + '</div>'; 26567 GLO.Popup.Processing.open(htm, 'Membership Period + Billing Period'); 26568 } 26569 26570 function _getHtmHowToSetup(isMembershipSetupScreen) { 26571 if (isMembershipSetupScreen) { 26572 var aNewMembership = '<a onclick="GLO.Provider.Membership.openEditType()">'; 26573 } else { 26574 var aNewMembership = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'membership?create=membership\', this, event, true)">'; 26575 } 26576
26577 var btnAddService = '<span class="btnAdd btnAddMembership"><a>Add Service to Membership</a></span>'; 26578 var btnAddMember = '<span class="btnMembership btnAdd"><a><b>+</b> Add Membership</a></span>'; 26579 var btnViewMember = '<span class="btnMembership btnAdd"><a>View Membership</a></span>'; 26580 var sellMembership = '<b style="white-space: nowrap; letter-spacing: 0;">Go to <a onclick="GLO.Provider.Membership.openSell()">Products <b class="arrow-right">➜</b> Sell Membership</a></b>'; 26581 var rptMembership = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'membership/report\', this, event, true)">Membership Report</a>'; 26582 26583 var h0 = '<h2>Setup Membership</h2>'; 26584 var p0 = '<p></p>'; 26585 var h1 = '<h2>Create Membership</h2>'; 26586 var p1 = '<p>' + aNewMembership + 'Create a new membership</a> by entering the membership name and the normal membership price, period, and auto-bill setting</p>'; 26587 26588 var h2 = '<h2>Add Service(s) to Membership</h2>'; 26589 var p2 = '<p>The membership services can </p>'; 26590 var ul2 = '<ul>' 26591 + '<li>Be free or discounted</li>' 26592 + '<li>Can limit the number of appointments available to a member for each service per period</li>' 26593 + '</ul>'; 26594 26595 var h3 = '<h2>Add Client to Membership</h2>'; 26596 var p3 = '<p>Can make clients a member by </p>'; 26597 var ul3 = '<ul>' 26598 + '<li>Selling a membership to a client from the main menu ' + sellMembership + '</li>' 26599 + '<li>On a client\'s profile press the button ' + btnAddMember + '</li>' 26600 + '</ul>'; 26601 26602 var h4 = '<h2>Customize Membership for Client</h2>'; 26603 var p4 = '<p>When a client becomes a member, can view the client\'s member profile</p>'; 26604 var ul4 = '<ul>' 26605 + '<li>On the client\'s profile press the button ' + btnViewMember + '</li>' 26606 + '<li>Press the member profile on the ' + rptMembership + '</li>' 26607 + '</ul>'; 26608 var p4b = '<p>On the member profile can customize the membership for the specific client, such as change the</p>'; 26609 var ul4b = '<ul>' 26610 + '<li>Member price</li>' 26611 + '<li>Member period</li>' 26612 + '<li>Start date and/or end date</li>' 26613 + '<li>Member balance <i class="narrow-text">(for example, if pre-paying for membership)</i></li>' 26614 + '</ul>'; 26615 26616 var htm = '<div id="pop-help-membership-setup">' + h0 + p0 + h1 + p1 + h2 + p2 + ul2 + h3 + p3 + ul3 + h4 + p4 + ul4 + p4b + ul4b + '</div>'; 26617 var jpop = GLO.Popup.Custom.openSimple(htm); 26618 GLO.Popup.Custom.singleButton(jpop, 'Close'); 26619 } 26620 26621 return _cMemberHelp; 26622 })(); 26623 26624 26625 return _cMembership; 26626})(); 26627 26628 26629GLO.Provider.TagManager = (function() { 26630 function _cTagManager() { } 26631 26632 _cTagManager.init = function() { 26633 GLO.Info.init(); 26634 var tbl = $('#tag-manager-table'); 26635 26636 UI.initTableSorter(tbl, null, true); 26637 _initOrder(tbl); 26638 26639 if (GLO.Uri.query('open') === 'help') { 26640 GLO.Provider.TagManager.openReportHelp() 26641 } 26642 } 26643 26644 function _initOrder(tbl) { 26645 var trs = tbl.find('tbody > tr'); 26646 26647 tbl.find('tbody').sortable({ 26648 handle: '.wiz4-drag' 26649 , update: function(event, ui) { 26650 if (_isValidMove()) { 26651 var tbl = $('#tag-manager-table'); 26652 var trs = tbl.find('tbody > tr'); 26653 26654 for (var i=0; i < trs.length; i++) { 26655 trs.eq(i).attr('order_sr', i+1); 26656 //trs.eq(i).find('td:first').attr('order_by', i+1); 26657 } 26658 26659 _updateOrder(); 26660 } 26661 } 26662 26663 , stop: function (event, ui) { 26664 if (!_isValidMove()) { 26665 $(this).sortable('cancel'); 26666 } 26667 } 26668 //, sort: function(event, ui) { } 26669 }); 26670 26671 //trs.find('.btnAdd').disableSelection(); 26672 } 26673 26674 function _isValidMove() { 26675 return true; 26676 } 26677 26678 _cTagManager.openClientReport = function(element, event) { 26679 var tr = $(element).closest('tr'); 26680 var cttid = tr.attr('id'); 26681 var url = 'message/ClientList?tagrelationship=both&tagtype=' + cttid; 26682 26683 GLO.Uri.gotoUriWithSpinner(url, element, event); 26684 } 26685 26686 _cTagManager.openTagType = function(tagTypeId, element) { 26687 if (!UTIL.isEmpty(tagTypeId)) { 26688 var h1 = 'Edit Tag Type'; 26689 var tagName = UTIL.htmlEncode2($(element).text()); 26690 var tr = $(element).closest('tr'); 26691 var relationshipName = UTIL.htmlEncode2(UTIL.cleanString(tr.find('.column-relationship').text())); 26692 var clientCount = UTIL.coalesceInt(tr.find('.column-client-count').text()); 26693 var tagPresetId = UTIL.coalesceInt(tr.attr('tag_preset_id')); 26694 } else { 26695 var h1 = 'Add Tag Type'; 26696 var tagName = '', relationshipName = '', clientCount = 0, tagPresetId = ''; 26697 var btnSave = $('.btnAddTagType'); 26698 } 26699 26700 var labelTag = '<label for="Tag_Name_vc">Tag Name</label>'; 26701 var inputTag = '<input type="text" id="Tag_Name_vc" placeholder="required" value="' + tagName + '"/>'; 26702 var divTag = '<div id="pop-tag-name">' + labelTag + inputTag + '</div>'; 26703 26704 var htmRelationshipAndPreset = _openTagType2(relationshipName, tagPresetId); 26705 var divMain = '<div id="pop-edit-tag-type" tag_type_id="' + UTIL.cleanString(tagTypeId) + '" clients="' + clientCount + '">'; 26706 var htm = divMain + divTag + htmRelationshipAndPreset + '</div>'; 26707 26708 var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.TagManager.saveTagType); 26709 var btnSave = jpop.find('.btnSave'); 26710 26711 jpop.find(':text').change(function() { UI.buttonDisplayChange(btnSave); }); 26712 //jpop.find(':text').keyup(function() { UI.buttonDisplayChange(btnSave); }); 26713 26714 if (!UTIL.isEmpty(tagTypeId)) { 26715 var jbtns = jpop.find('.pop-buttons'); 26716 var btnDelete = '<a onclick="GLO.Provider.TagManager.deleteTagType()" style="padding: 3px 6px 1px 6px;">Delete</a>'; 26717 26718 btnSave.css({ "position": "relative", "right": "inherit", "margin": 0 }); 26719 jbtns.append('<span class="btnDelete" style="position: absolute; right: 6px; margin: 0;">' + btnDelete + '</span>'); 26720 } 26721 26722 jpop.find('#Tag_Name_vc').focus(); 26723 } 26724 function _openTagType2(relationshipName, tagPresetId) { 26725 var rlabel = 'Relationship Name', hasRelationship = '', hasPreset = '', labelPreset = '', btnPresetLabel = 'Create Preset List'; 26726 26727 if (innerWidth < 500) { rlabel = 'Relationship'; } 26728 if (!UTIL.isEmpty(relationshipName)) { hasRelationship =' checked="checked"'; } 26729 26730 if (!UTIL.isEmpty(tagPresetId)) { 26731 hasPreset =' checked="checked"'; 26732 btnPresetLabel = 'Edit Preset List'; 26733 labelPreset = '<label for="Tag_Preset_id" title="List of values for this tag">Preset List</label>'; 26734 } 26735 26736 var labelRelationshipName = '<label for="Relationship_Name_vc">' + rlabel + '</label>'; 26737 var inputRelationshipName = '<input type="text" id="Relationship_Name_vc" value="' + relationshipName + '" placeholder="optional"/>'; 26738 var divRelationship = '<div id="pop-relationship-name">' + labelRelationshipName + inputRelationshipName + '</div>'; 26739 26740 var rdo = '<input type="radio" name="tag-type-type" id="Tag_Is_Relationship_fl"' + hasRelationship + '/>
26740'; 26741 var small = '<small>(for example, tag name = "mom", relationship name = "son")</small>'; 26742 var lbl = '<label for="Tag_Is_Relationship_fl" class="tag-type-type">This tag is a type of relationship' + small + '</label>'; 26743 var htm1 = '<div id="tag-type-relationship" class="tag-type-type"><div>' + rdo + lbl + '</div>' + divRelationship + '</div>'; 26744 26745 var ddPreset = _cTagManager.getPresetDropDown(tagPresetId); 26746 var btnPreset = '<span id="btnEditPreset" class="btnAdd"><a onclick="GLO.Provider.TagManager.openEditPreset(' + tagPresetId + ')">' + btnPresetLabel + '</a></span>'; 26747 var divPreset = '<div id="pop-tag-preset">' + labelPreset + ddPreset + btnPreset + '</div>'; 26748 26749 var rdo = '<input type="radio" name="tag-type-type" id="Tag_Is_Preset_fl"' + hasPreset + '/>'; 26750 var small = '<small>(for example, tag name = "grade", preset values = "9th", "10th", "11th", "12th")</small>'; 26751 var lbl = '<label for="Tag_Is_Preset_fl" class="tag-type-type">This tag has a preset list of values' + small + '</label>'; 26752 var htm2 = '<div id="tag-type-preset" class="tag-type-type"><div>' + rdo + lbl + '</div>' + divPreset + '</div>'; 26753 26754 return htm1 + htm2; 26755 } 26756 26757 _cTagManager.getPresetDropDown = function(tagPresetId) { 26758 if (UTIL.isEmpty(tagPresetId)) { return ''; } 26759 } 26760 26761 function _spinRefreshIcon(jicon) { 26762 if (jicon.length > 0) { 26763 if (jicon.hasClass('simple-spin')) { 26764 return; 26765 } else { 26766 jicon.addClass('simple-spin'); 26767 } 26768 } 26769 } 26770 26771 function _stopRefreshIcon(jicon, spinWait) { 26772 if (jicon.length > 0) { 26773 setTimeout(function() { 26774 jicon.removeClass('simple-spin'); 26775 }, UTIL.coalesceInt(spinWait, 10)); 26776 } 26777 } 26778 26779 _cTagManager.refresh = function(tagTypeId) { 26780 var uri = GLO.Link.WebsiteDomain + 'provider/manage/tag?ispartial=1'; 26781 var jicon = $('#tag-manager-table .refresh-icon'); 26782 _spinRefreshIcon(jicon); 26783 26784 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 26785 .success(function(data, textStatus, jqXHR) { 26786 var tbl = $(data).find('#tag-manager-table'); 26787 $('#tag-manager-table').replaceWith(tbl); 26788 tbl = $('#tag-manager-table'); 26789 26790 UI.initTableSorter(tbl, null, true); 26791 _initOrder(tbl); 26792 }) 26793 .error(function(jqXHR, textStatus, errorThrown) { 26794 _stopRefreshIcon(jicon); 26795 }); 26796 } 26797 26798 function _updateOrder() { 26799 var tbl = $('#tag-manager-table'); 26800 var trs = tbl.find('tbody > tr'); 26801 var xml = '<ol>'; 26802 26803 for (var i=0; i < trs.length; i++) { 26804 trs.eq(i).attr('order_sr', i+1); 26805 xml += '<li id="' + trs.eq(i).attr('id') + '" order_sr="' + (i+1) + '"/>'; 26806 } 26807 26808 xml = UTIL.htmlEncode(xml + '</ol>'); 26809 var uri = GLO.Link.WebsiteDomain + 'provider/manage/TagTypeOrder'; 26810 26811 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } }) 26812 .success(function(data, textStatus, jqXHR) { 26813 var htm = '<div id="pop-sucess-tag-type-order">Tag Order Updated</div>'; 26814 26815 GLO.Popup.close($('#pop-sucess-tag-type-order').closest('.glopop')); 26816 GLO.Popup.Success.open(htm, 'Tag Order Updated'); 26817 }) 26818 .error(function(jqXHR, textStatus, errorThrown) { 26819 //GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 26820 //new GLO.Popup.Error('Unable to order the calendars staff'); 26821 }); 26822 } 26823 26824 _cTagManager.saveTagType = function() { 26825 var uri = GLO.Link.WebsiteDomain + 'provider/manage/tagtype'; 26826 var jpop = $('#pop-edit-tag-type'); 26827 var tagTypeId = UTIL.cleanString(jpop.attr('tag_type_id')), clients = jpop.attr('clients'); 26828 26829 jpop = jpop.closest('.glopop'); 26830 26831 var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val(); 26832 var jd = { "tag_type_id": tagTypeId, "tag_name_vc": tagName, "relationship_name_vc": relationship }; 26833 var jsave = jpop.find('.btnSave'); 26834 26835 if (UTIL.isEmpty(tagName)) { 26836 GLO.Popup.Warning.open('Please Enter a tag name', 'Tag Name Missing'); 26837 return; 26838 } 26839 26840 GLO.UI.Form.beginProcessing(jsave); 26841
26842 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 26843 .success(function(data, textStatus, jqXHR) { 26844 GLO.Popup.close(jpop); 26845 var trnew = $(data); 26846 26847 if (UTIL.isNumber(tagTypeId)) { 26848 var trold = $('#tag-manager-table').find('tbody > tr[id="' + tagTypeId + '"]'); 26849 trold.find('.btnTagType').replaceWith(trnew.find('.btnTagType')); 26850 trold.find('.column-relationship').text(trnew.find('.column-relationship').text()); 26851 } else { 26852 $('#tag-manager-table').find('tbody').prepend(trnew); 26853 } 26854 26855 var htm = '<b style="white-space: nowrap; font-size: larger; color: black;">' + tagName + '</b> Saved'; 26856 GLO.Popup.Success.open(htm, 'Tag Type Saved'); 26857 }) 26858 .error(function(jqXHR, textStatus, errorThrown) { 26859 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 26860 GLO.Popup.Error.open('<div><div style="margin-bottom: 12px;">Unable to save tag type at this time</div><div>Please try again</div></div>', 'Save Tag'); 26861 }); 26862 } 26863 26864 _cTagManager.openReportHelp = function(isRequireGoldPackage) { 26865 var linkTagManager = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Tag Manager</a>'; 26866 var linkClientList = '<a onclick="GLO.Report.Template2.goToReport(\'Client List\', \'message/ClientList\', event)">Client List Report</a>'; 26867 var linkTicketHistory = '<a onclick="GLO.Report.Template2.goToReport(\'' + SA.Resource.TicketHistory + '\', \'reports/TicketHistory\', event)">' + SA.Resource.TicketHistory + ' ' + SA.Resource.Report + '</a>'; 26868 var linkReminderView = '<a onclick="GLO.Report.Template2.goToReport(\'Reminder View\', \'provider/reminders\', event)">Reminder View</a>'; 26869 26870 var ul1 = '<li>Tags help group, categorize, and add notes to client profiles</li>'; 26871 var ul2 = '<li>Create relationships between clients like <b style="letter-spacing: 0;">friends, teacher/student, parent/child, referer, etc..</b></li>'; 26872 var ul3 = '<li>If related clients have appointment on the same day <b style="letter-spacing: 0;">top of appointment displays those client name(s)</b></li>'; 26873 var ul4 = '<li>Can use tags to filter both the ' + linkClientList + ' and ' + linkTicketHistory + '</li>'; 26874 var ul5 = '<li>Automatically apply discounts based on tags, for example tags like <b style="letter-spacing: 0;">College Student, Club Member,..</b></li>'; 26875 var ul = '<ul id="tags-why-use">' + ul1 + ul2 + ul3 + ul4 + ul5 + '</ul>'; 26876 26877 var h4 = '<h4 style="margin-top: 32px;">How to Add Tag to a Client Profile</h4>'; 26878 var ol1 = '<li>Go to client\'s profile <small style="letter-spacing: 0;">by clicking client\'s name or enter client in search box <i>(in upper left corner)</i></small></li>'; 26879 var ol2 = '<li>Press the <b style="letter-spacing: 0; color: rgb(0, 160, 220);">+ Add Tag / Relationship</b> button</li>'; 26880 var ol3 = '<li>Select Tag Name or enter new tag name</li>'; 26881 var ol4 = '<li>If is a relationship <small style="letter-spacing: 0;">(like mother/daughter, friend, or co-worker)</small> enter related client name</li>'; 26882 var ol5 = '<li>Enter a tag note (when helpful)</li>'; 26883 var ol6 = '<li>Press Save</li>'; 26884 var ol = h4 + '<ol id="tags-how-to">' + ol1 + ol2 + ol3 + ol4 + ol5 + ol6 + '</ol>'; 26885 26886 var tip1 = '<li>Client\'s tags displayed on the ' + linkReminderView + '</li>'; 26887 var tip2 = '<li>Use the ' + linkTagManager + ' to create, change, and remove tags</li>'; 26888 var ulTips = '<h4>Tips</h4>' + '<ul id="tags-tips">' + tip1 + tip2 + '</ul>'; 26889 26890 if (isRequireGoldPackage) { 26891 ul = '<div class="gold-package-only-header"><span class="gold-package-link"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/6\', this, event, true)">Gold Package Only</a></span></div>' + ul; 26892 } 26893 26894 var htm = '<div id="pop-info-tags" style="padding-bottom: 12px; line-height: 1.6; font-size: initial;">' + ul + ol + ulTips + '</div>'; 26895 var jpop = GLO.Popup.Custom.openSimple(htm, 'Client Tags'); 26896 GLO.Popup.Custom.singleButton(jpop, 'Close'); 26897 26898 if (document.location.pathname.toLowerCase().indexOf('provider/manage/tag') === -1) { 26899 var jbtns = jpop.find('.pop-buttons2'); 26900 var aGoTo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Setup Cient Tags</a>'; 26901 var btnGoTo = '<span id="btnGoToTagManager" class="btnAdd" style="margin-right: 80px;">' + aGoTo + '</span>'; 26902 jbtns.prepend(btnGoTo); 26903 } 26904 } 26905 26906 _cTagManager.deleteTagType = function() { 26907 var jpop = $('#pop-edit-tag-type'); 26908 var clients = jpop.attr('clients'); 26909 var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val(); 26910 26911 var div1 = '<div>Are you sure you want to delete the tag: <b style="white-space: nowrap; font-size: larger; color: black;">
26911' + tagName + '</b></div>'; 26912 var div2 = '<div>' + UTIL.pluralLabel(clients, 'client') + ' have this tag</div>'; 26913 var htm = '<div id="pop-confirm-tag-type-delete">' + div1 + div2 + '</div>'; 26914 26915 GLO.Popup.Confirm.open(htm, 'Confirm Delete Tag', GLO.Provider.TagManager.deleteTagTypeConfirmed); 26916 } 26917 26918 _cTagManager.deleteTagTypeConfirmed = function() { 26919 var uri = GLO.Link.WebsiteDomain + 'provider/manage/TagTypeDelete'; 26920 var jpop = $('#pop-edit-tag-type'); 26921 var jbtn = jpop.find('.btnDelete'); 26922 26923 var tagTypeId = UTIL.cleanString(jpop.attr('tag_type_id')), clients = jpop.attr('clients'); 26924 var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val(); 26925 var jd = { "tag_type_id": tagTypeId, "tag_name_vc": tagName }; 26926 26927 GLO.UI.Form.beginProcessing(jbtn); 26928 26929 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 26930 .success(function(data, textStatus, jqXHR) { 26931 GLO.Popup.close(jpop.closest('.glopop')); 26932 26933 var jdata = $(data); 26934 var tagDeleteCount = jdata.attr('client_tag_delete_count_nr'); 26935 26936 var div1 = '<div>Tag Type: <b style="white-space: nowrap; font-size: larger; color: black;">' + tagName + '</b> Deleted<div>'; 26937 var div2 = '<div>Removed ' + tagDeleteCount + ' ' + UTIL.makePlural('tag', tagDeleteCount) + ' on client profiles</div>'; 26938 var htm = '<div id="pop-delete-tag-type-success">' + div1 + div2 + '</div>'; 26939 GLO.Popup.Success.open(htm, 'Tag Type Saved'); 26940 26941 $('#tag-manager-table').find('tbody').find('tr[id="' + tagTypeId + '"]').remove(); 26942 }) 26943 .error(function(jqXHR, textStatus, errorThrown) { 26944 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 26945 GLO.Popup.Error.open('<div><div style="margin-bottom: 12px;">Unable to delete tag type at this time</div><div>Please try again</div></div>', 'Delete Tag'); 26946 }); 26947 } 26948 26949 return _cTagManager; 26950})(); 26951 26952 26953GLO.Inventory = (function() { 26954 var _MAX_DEFAULT_ROWS, _filterInProgress = false, _morphPopup = null; 26955 26956 function _conInventory() { } 26957 26958 _conInventory.filterIndent = " "; 26959 _conInventory.docWidth = 1275; 26960 _conInventory.doNotTrackStock = false; 26961 _conInventory.prevHash = '', _conInventory.prevHashId = null, _conInventory.prevIsItem = false, _conInventory.prevItemId = null; 26962 _conInventory.isProductList = false; 26963 26964 _conInventory.init = function(doNotTrackStock) { 26965 if ( $('#col-cost').length === 1) { _conInventory.docWidth = 1350; } 26966 if (GLO.Info.isMobile(true)) { _conInventory.docWidth -= 280; } 26967 26968 _conInventory.isProductList = true; 26969 _conInventory.doNotTrackStock = UTIL.parseBool(doNotTrackStock);
26970 UI.initTableSorter( $('#inventory-table.tablesorter'), null, true); 26971 var queryStringHash = document.location.hash; 26972 26973 $('#inventory-item-form:visible').on('click', '#ba-Save', GLO.Inventory.Item.save); 26974 26975 $('#inventory-location-list').on('click', 'li', function() { 26976 var li = $(this); 26977 GLO.Inventory.updateHash('edit-location', li.attr('location_id')); 26978 }); 26979 26980 $('#inventory-vendor-list').on('click', 'li', function() { 26981 var li = $(this); 26982 //GLO.Inventory.Vendor.openEdit(li.attr('vendor_id'), li.text(), UTIL.cleanString(li.attr('distributor_id'))); 26983 GLO.Inventory.updateHash('edit-vendor', li.attr('vendor_id')); 26984 }); 26985 26986 $('#inventory-distributor-list').on('click', 'li', function() { 26987 var li = $(this); 26988 //GLO.Inventory.Vendor.openDistributorEdit(li.attr('distributor_id'), li.text()); 26989 GLO.Inventory.updateHash('edit-distributor', li.attr('distributor_id')); 26990 }); 26991 26992 $('#inventory-product-line-list').on('click', 'li', function() { 26993 var li = $(this); 26994 GLO.Inventory.updateHash('edit-product-line', li.attr('product_line_id')); 26995 }); 26996 26997 $('#inventory-unit-list').on('click', 'li', function() { 26998 var li = $(this); 26999 //GLO.Inventory.Unit.openEdit(li.attr('unit_id'), li.text(), UTIL.cleanString(li.attr('title'))); 27000 GLO.Inventory.updateHash('edit-unit', li.attr('unit_id')); 27001 }); 27002 27003 $('#inventory-type-list').on('click', 'li', function() { 27004 var li = $(this); 27005 //GLO.Inventory.Type.openEdit(li.attr('inventory_type_id'), li.text(), UTIL.cleanString(li.attr('type_category_id'))); 27006 GLO.Inventory.updateHash('edit-type', li.attr('inventory_type_id')); 27007 }); 27008 27009 $('#inventory-type-category-list').on('click', 'li', function() { 27010 var li = $(this); 27011 //GLO.Inventory.Type.openCategoryEdit(li.attr('type_category_id'), li.text()); 27012 GLO.Inventory.updateHash('edit-type-category', li.attr('type_category_id')); 27013 }); 27014 27015 27016 $(window).hashchange(function() { //Bind the event. 27017 var jMainProcessing = _openInventoryProcessing(); //GLO.Popup.Processing.open('Loading...', 'Manage Inventory').getPopup().addClass('pop-stick-to-top'); 27018 27019 setTimeout(function() { 27020 GLO.Inventory.hashOnChange(); 27021 GLO.Popup.closeIfExist(jMainProcessing); 27022 }, 100); 27023 }); 27024 27025 var shipmentId = GLO.Uri.query('EditShipmentId'); 27026 var filterId = GLO.Uri.hash('filterid'); 27027 27028 if (!UTIL.isEmpty(shipmentId)) { 27029 GLO.Inventory.updateHash('order', shipmentId); 27030 } else if (GLO.Uri.hash('action') === 'product-list' && UTIL.isEmpty(filterId)) { 27031 _conInventory.updateHash('product-list-intro'); 27032 } else { 27033 _initFilter(filterId); 27034 setTimeout(function() { GLO.Inventory.hashOnChange(); }, 10); //setTimeout(function() { $(window).hashchange(); }, 10); 27035 } 27036 27037 $('#manage-inventory').on('change', 'input:visible, select:visible, textarea:visible', function() { 27038 if ($(this).closest('#inventory-automatic-ordering').length == 0) { 27039 $('#inventory-header-action-container .btnSave a').css({ "border": "3px solid Red" }); 27040 } 27041 }); 27042 27043 $('#inventory-item-form').on('change', 'input:visible, select:visible, textarea:visible', function() { 27044 $('#inventory-item-form .btnSave a').css({ "border": "3px solid Red" }); 27045 }); 27046 27047 $('#inventory-type-category-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27048 $('#inventory-type-category-edit .btnSave a').css({ "border": "3px solid Red" }); 27049 }); 27050 27051 $('#inventory-type-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27052 $('#inventory-type-edit .btnSave a').css({ "border": "3px solid Red" }); 27053 }); 27054 27055 $('#inventory-unit-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27056 $('#inventory-unit-edit .btnSave a').css({ "border": "3px solid Red" }); 27057 }); 27058 27059 $('#inventory-vendor-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27060 $('#inventory-vendor-edit .btnSave a').css({ "border": "3px solid Red" }); 27061 }); 27062 27063 $('#inventory-distributor-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27064 $('#inventory-distributor-edit .btnSave a').css({ "border": "3px solid Red" }); 27065 }); 27066 27067 $('#inventory-product-line-edit').on('change', 'input:visible, select:visible, textarea:visible', function() { 27068 $('#inventory-product-line-edit .btnSave a').css({ "border": "3px solid Red" }); 27069 }); 27070 27071 $('#inventory-options').on('change', 'input:visible, select:visible, textarea:visible', function() { 27072 $('#inventory-options .btnSave a').css({ "border": "3px solid Red" }); 27073 }); 27074 27075 $('#product-list-intro').on('click', 'li', GLO.Inventory.filterIntro); 27076 27077 var arrProducts = []; 27078 $('#manage-inventory tbody').find('.item-name').each(function() { 27079 var me = $(this); 27080 var nm = UTIL.coalesce(me.attr('title'), me.text()); 27081 arrProducts.push({ "id": me.closest('tr').attr('id'), "label": nm, "value": nm }); 27082 }); 27083 27084 $("#inventory-restock-buttons #Existing_Inventory_id").autocomplete({ source: arrProducts, select: function(event, ui) { 27085 var rowId = ui.item.id; 27086 var row = $('#manage-inventory tbody tr#' + rowId); 27087 27088 if (row.hasClass('hide')) { 27089 row.removeClass('hide').css({ "background-color": "Yellow" }); 27090 } else { 27091 row.css({ "background-color": "Pink" });
27092 } 27093 27094 window.setTimeout(function() { 27095 $("#inventory-restock-buttons #Existing_Inventory_id").val(''); 27096 }, 900); 27097 27098 window.setTimeout(function() { 27099 $('#manage-inventory tbody tr#' + rowId).css({ "background-color": "" }); 27100 //$('#Existing_Inventory_id').val(''); 27101 }, 4500); 27102 } }); 27103 27104 var jOrderHeader = $('#inventory-order-header'); 27105 jOrderHeader.find('.btnSave, .btnDelete').hover(function() { 27106 var me = $(this); 27107 if (me.hasClass('btnSave')) { 27108 var color = 'Green'; 27109 } else { 27110 var color = 'Red'; 27111 } 27112 27113 var fontSize = "100%"; 27114 if (GLO.Info.isMobile()) { fontSize = "85%"; } 27115 27116 $('#inventory-order-disclaimer').css({ "color": color, "font-size": fontSize }); 27117 }, 27118 function() { 27119 $('#inventory-order-disclaimer').css({ "font-weight": "", "color": "", "font-size": "" }); 27120 }); 27121 27122 jOrderHeader.find('#auto_start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 27123 jOrderHeader.find('#auto_end_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 27124 27125 var jOrderDates = jOrderHeader.find('#inventory-order-dates'); 27126 jOrderDates.find('#Order_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 27127 jOrderDates.find('#Order_Received_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek }); 27128 27129 jOrderHeader.find('#auto_ordering_dates_fl').click(function() { UI.changeFocus(this, 'auto_start_dt'); }); 27130 jOrderHeader.find('#auto_ordering_minimum_fl').click(function() { UI.changeFocus(this, 'minimum_pct'); }); 27131 27132 jOrderHeader.find('#auto_start_dt').change(function() { UI.markCheckbox(this, 'auto_ordering_dates_fl'); }).change(); 27133 jOrderHeader.find('#minimum_pct').change(function() { UI.markCheckbox(this, 'auto_ordering_minimum_fl'); }).change(); 27134 27135 UTIL.DefaultText.init( $('#Existing_Inventory_id') ); 27136 27137 GLO.Inventory.setMaximumProductListRows(false); 27138 _init_Mobile(); 27139 _init_iPad(); 27140 GLO.Info.init(); 27141 _initBasicPackage(); 27142 _initNoBrand();
27143 27144 if (UTIL.parseBool(doNotTrackStock)) { 27145 var jitem = $('#inventory-item-edit'); 27146 jitem.find('.track-stock-level').removeClass('track-stock-level'); 27147 27148 var toHide = 'label[for="Track_Stock_fl"], label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"], #Track_Stock_fl, #In_Stock_dr, #Minimum_Stock_dr, #Avg_Cost_mn, #In_Stock_link'; 27149 jitem.find(toHide).addClass('hideX'); 27150 27151 var jmanage = $('#manage-inventory'); 27152 jmanage.find('.item-minimum-stock, .item-in-stock-parent').addClass('hideX'); 27153 jmanage.find('#inventory-product-list-header-center').css({ "margin-right": "50px" }); 27154 //jmanage.find('#inventory-audit-button').addClass('hideX'); 27155 27156 if (GLO.Info.isIPad) { 27157 _conInventory.docWidth = _conInventory.docWidth - 70; 27158 } else if (!GLO.Info.isMobile()) { 27159 _conInventory.docWidth = _conInventory.docWidth - 115; // -140; //$('#doc3').width(_conInventory.docWidth); 27160 } 27161 } else { 27162 $('#manage-inventory').addClass('track-stock'); 27163 } 27164 27165 _conInventory.initEnterTax(); 27166 $('#header-navigation-links').find('#hd-report-product-list > a, #hd-report-link-create-order, #hd-report-receive-order > a').addClass('ignore-animate'); 27167 27168 _initLanguage(); 27169 _conInventory.initHeaderHelpIcon(); 27170 _initUrl(queryStringHash); 27171 _initFooterPopup(); 27172 UserPortal.Lookup.initMonitorQRScan(); 27173 } 27174 27175 function _openInventoryProcessing(msg, header) { 27176 if ($('#pop-processing-manage-inventory').length > 0) { 27177 return; 27178 } 27179 27180 if (UTIL.isEmpty(msg)) { 27181 msg = 'Loading...'; 27182 } 27183 27184 header = UTIL.coalesceString(header, 'Manage Inventory'); 27185 var htm = '<div id="pop-processing-manage-inventory">' + msg + '</div>'; 27186 return GLO.Popup.Processing.open(htm, header).getPopup().addClass('pop-stick-to-top'); 27187 } 27188 function _initFilter(filterId) { 27189 if (UTIL.isEmpty(filterId)) { return; } 27190 27191 var jhead = $('#inventory-header-filter'); 27192 jhead.find('#Filter_Company').val(filterId); 27193 jhead.find('#Filter_Category').val(filterId); 27194 jhead.find('#Filter_Stock_Level').val(filterId); 27195 27196 GLO.Uri.removeHashKey('filterid'); 27197 } 27198 27199 function _initFooterPopup() { 27200 var tfoot = $('#inventory-table').find('tfoot'); 27201 var backbarCost = UTIL.coalesceMoney(tfoot.attr('backbar_cost_mn')), backbarPrice = UTIL.coalesceMoney(tfoot.attr('backbar_price_mn')), backbarCount = UTIL.coalesceInt(tfoot.attr('backbar_nr')); 27202 var retailCost = UTIL.coalesceMoney(tfoot.attr('retail_cost_mn')), retailPrice = UTIL.coalesceMoney(tfoot.attr('retail_price_mn')), retailCount = UTIL.coalesceInt(tfoot.attr('retail_nr')); 27203 27204 if (retailCount > 0) { 27205 if (backbarCount > 0) { 27206 var caption = 'Retail & Backbar'; 27207 } else { 27208 var caption = 'Retail'; 27209 } 27210 27211 var ihtm = '<span class="info-icon" onclick="GLO.Info.openInfoIcon(this)" info="' + tfoot.attr('info') + '" header="' + caption + '"><b>i</b></span>'; 27212 27213 var r1 = '<label class="ft-retail-count">Count</label><b class="ft-retail-count">' + retailCount + ' <small>products</small></b>'; 27214 var r2 = '<label class="ft-retail-cost">Cost</label><b class="ft-retail-cost">' + UTIL.displayMoney(retailCost, false, false, true) + '</b>'; 27215 var r3 = '<label class="ft-retail-price">Price</label><b class="ft-retail-price">' + UTIL.displayMoney(retailPrice, false, false, true) + '</b>'; 27216 var rhtm = '<div id="product-list-intro-retail"><h6>Retail</h6>' + r1 + r2 + r3 + ihtm + '</div>'; 27217 27218 if (backbarCount > 0) { 27219 var b1 = '<label class="ft-backbar-count">Count</label><b class="ft-backbar-count">' + backbarCount + ' <small>products</small></b>'; 27220 var b2 = '<label class="ft-backbar-cost">Cost</label><b class="ft-backbar-cost">' + UTIL.displayMoney(backbarCost, false, false, true) + '</b>'; 27221 var b3 = '<label class="ft-backbar-price">Price</label><b class="ft-backbar-price">' + UTIL.displayMoney(backbarPrice, false, false, true) + '</b>'; 27222 var bhtm = '<div id="product-list-intro-backbar"><h6>Backbar</h6>' + b1 + b2 + b3 + ihtm + '</div>'; 27223 } else { 27224 var bhtm = ''; 27225 } 27226 27227 var htm = '<div id="product-list-intro-info">' + rhtm + bhtm + '</div>'; 27228 $('#product-list-intro').append(htm); 27229 } 27230 } 27231 27232 function _initUrl(queryString) { 27233 var open = GLO.Uri.getQueryStringValue('open', queryString).toLowerCase(); //UTIL.cleanString(GLO.Uri.hash('open')).toLowerCase(); 27234 var highlight = GLO.Uri.getQueryStringValue('highlight', queryString).toLowerCase(); //UTIL.cleanString(GLO.Uri.hash('highlight')); 27235 var ifilter = GLO.Uri.getQueryStringValue('inventoryfilter', queryString).toLowerCase(); //UTIL.cleanString(GLO.Uri.hash('inventoryfilter')).toLowerCase(); 27236 var help = GLO.Uri.getQueryStringValue('help', queryString).toLowerCase(); //UTIL.cleanString(GLO.Uri.hash('help')).toLowerCase();
27237 var isClick = UTIL.parseBool(GLO.Uri.getQueryStringValue('isclick', queryString)); //UTIL.parseBool(GLO.Uri.hash('isclick')); 27238 27239 if (!UTIL.isEmpty(open)) { 27240 if (open === 'edit-product') { 27241 $('#inventory-table').find('tbody tr:first').find('.item-name').click(); 27242 } else if (open === 'help-order') { 27243 setTimeout(function() { 27244 $('#inventory-header-help-icon').click(); 27245 }, 400); 27246 } else if (open === 'usage-invoice') { 27247 //GLO.Inventory.Invoice.createUsageInvoice(); 27248 27249 //open menu just so user can see it 27250 setTimeout(function() { 27251 $('#inventory-header-action-container #btnAddCreate .btnCreate > a').click(); 27252 27253 setTimeout(function() { 27254 var jlink = $('#inventory-create-menu .inventory-usage-link').css({ "background-color": "deeppink" }); 27255 27256 setTimeout(function() { 27257 jlink.find('>a').click(); 27258 27259 setTimeout(function() { 27260 jlink.css({ "background-color": "" }); 27261 }, 800); 27262 }, 800); 27263 }, 1200); 27264 }, 1200); 27265 } else if (open === 'create-menu') { 27266 _openCreateMenu(highlight, isClick); 27267 } else if (open === 'edit-menu') { 27268 _openEditMenu(highlight, isClick); 27269 } 27270 } else if (!UTIL.isEmpty(ifilter)) { 27271 var co = $('#Filter_Company option[value="' + ifilter + '"]').text(); 27272 var cat = $('#Filter_Category option[value="' + ifilter + '"]').text(); 27273 var h1 = '', msg = 'Filtering product list to display'; 27274 27275 if (!UTIL.isEmpty(co)) { 27276 h1 = co; 27277 } 27278 27279 if (!UTIL.isEmpty(cat)) { 27280 if (h1 !== '') { 27281 h1 = h1 + ' and ' + cat; 27282 } else { 27283 h1 = cat; 27284 } 27285 } 27286 27287 var ojprocessing = GLO.Popup.Processing.open(msg += ' ' + h1 + '...', h1); 27288 27289 setTimeout(function() { 27290 $('#Filter_Company').val(ifilter); 27291 $('#Filter_Category').val(ifilter); 27292 27293 ojprocessing.close(); 27294 GLO.Inventory.filter(); 27295 }, 1500); 27296 } 27297 27298 if (!UTIL.isEmpty(highlight)) { 27299 setTimeout(function() { _initHighlight(highlight); }, 2400); 27300 } 27301 27302 if (!UTIL.isEmpty(help)) { 27303 setTimeout(function() { 27304 $('#inventory-header-help-icon').click() 27305 }, 100); 27306 } 27307 } 27308 27309 function _openCreateMenu(highlight, isClick) { //open menu so user can see it 27310 setTimeout(function() { 27311 $('#inventory-header-action-container #btnAddCreate .btnCreate > a').click(); 27312 _highlightInventoryHeaderMenuItem('inventory-create-menu', highlight, isClick); 27313 }, 1200); 27314 } 27315 function _openEditMenu(highlight, isClick) { 27316 setTimeout(function() { 27317 $('#inventory-header-action-container #btnAddCreate .btnEdit > a').click(); 27318 _highlightInventoryHeaderMenuItem('inventory-edit-menu', highlight, isClick); 27319 }, 1200); 27320 } 27321 function _highlightInventoryHeaderMenuItem(menuId, highlight, isClick) { 27322 if (UTIL.isEmpty(highlight)) { return; } 27323 27324 setTimeout(function() { 27325 var jlink = $('#' + menuId + ' .' + highlight).css({ "background-color": "deeppink" }); 27326 27327 setTimeout(function() { 27328 if (UTIL.parseBool(isClick)) { 27329 jlink.find('>a').click(); 27330 } 27331 27332 setTimeout(function() { 27333 jlink.css({ "background-color": "" }); 27334 }, 2800); 27335 }, 1200); 27336 }, 1200); 27337 } 27338 27339 function _initHighlight(highlight) { 27340 if (highlight === 'override-commission') { 27341 var jcommission = $('#inventory-item-override-row'); 27342 jcommission.find('label').click(); 27343 UI.highlight(jcommission, 300, 6000, true); 27344 } 27345 } 27346 27347 function _initLanguage() { 27348 if ($.cookies.get('language') === 'vi') { 27349 var j = $('#manage-inventory'); 27350 var jselect = j.find('#Filter_Category'); 27351 27352 jselect.css({ "padding-right": "1px", "letter-spacing": "1px", "text-transform": "lowercase" }); 27353 jselect.find('option:first').text('(' + SA.Resource.AllCategories + ')'); 27354 } 27355 } 27356 27357 _conInventory.initEnterTax = function(mustLaunch) { 27358 if (!mustLaunch && (GLO.inventoryTax != 0 || $('#inventory-table > tbody > tr').length > 1) ) { return; } 27359 27360 if (GLO.inventoryTax > 0) { 27361 var taxRate = GLO.inventoryTax; 27362 } else { 27363 var taxRate = ''; 27364 } 27365 27366 var numberInputType = "text"; 27367 if (GLO.Info.isAndroid) { numberInputType = "number"; } 27368 27369 var jmsg = $('<div id="pop-inventory-tax-rate" style="max-width: 500px;"> <h2 class="friendly-msg2">' + SA.Resource.ProductSalesTax + '</h2> <div class="friendly-msg2">' 27370 + '<div style="padding: 8px 16px;"> <label for="Edit_Inventory_Tax_Rate_pct" style="white-space: normal;">' + SA.Resource.EnterProductSalesTaxHelp + '</label> </div>' 27371 + '<div> <input id="Edit_Inventory_Tax_Rate_pct" type="' + numberInputType + '" value="' + taxR
27371ate + '" onkeypress="UI.numberOnly(event)" maxlength="5" style="width: 60px;"/> <b>%</b> </div>' 27372 + '</div> </div>'); 27373 27374 var jpop = new GLO.Popup.Custom(jmsg, GLO.Inventory.editTaxRate).getPopup().addClass('no-persist'); 27375 jpop.find('.pop-buttons').addClass('pop-buttons2'); 27376 } 27377 27378 function _initNoBrand() { 27379 var rowCount = 0; 27380 var tbl = $('#inventory-table').addClass('hide'); 27381 var jrows = tbl.find('tbody tr'); 27382 27383 jrows.each(function() { 27384 if (UTIL.isEmpty($(this).find('.item-vendor').attr('vendor_id'))) { ++rowCount; } 27385 }); 27386 27387 if (rowCount > 0) { 27388 var dd = '<dd onclick="GLO.Inventory.filterNoBrand()">( ' + SA.Resource.NoBrand + ' )</dd>'; 27389 27390 $('.intro-block-brands').find('dt').after(dd); 27391 } 27392 } 27393 27394 function _initBasicPackage() { 27395 if (GLO.Info.providerPackage != 4 && GLO.Provider.isPaidAccount(true)) { return; } 27396 27397 var jHeaderBtns = $('#inventory-product-list-buttons'); 27398 var btnAddCreate = jHeaderBtns.find('#btnAddCreate'); 27399 var btnAddCreateParent = btnAddCreate.closest('tr'); 27400 27401 jHeaderBtns.find('.btnDelete').css({ "margin-top": "8px" }); 27402 27403 var productList = $('#inventory-table').find('tbody tr'); 27404 27405 if (productList.length === 1 && productList.hasClass('no-items')) { var productListCount = 0; } else { var productListCount = productList.length; } 27406 27407 var htmCount = '<span id="inventory-product-list-count" style="letter-spacing: 1px;">' + productListCount + ' ' + SA.Resource.Products.toLowerCase() + '</span>' 27408 jHeaderBtns.find('#inventory-product-list-header-right').replaceWith(htmCount).parent() 27409 27410 jHeaderBtns.find('#inventory-product-list-header-left').css({ "height": "32px", "margin-top": "8px" }); 27411 27412 var tds = jHeaderBtns.find('> table').css({ "width": "100%" }).find('> tbody > tr > td').css({ "width": "30%" }); 27413 tds.eq(1).css({ "text-align": "center" }); 27414 tds.eq(2).css({ "text-align": "center" }); 27415 } 27416 27417 function _init_Mobile() { 27418 if (GLO.Info.isMobile(true)) { 27419 setTimeout(function() { GLO.Info.setupFastClick($('#inventory-product-list-buttons')[0]); }, 900); 27420 } 27421 } 27422 27423 function _init_iPad() { 27424 if (!GLO.Info.isIPad) { return; } 27425 27426 var j = $('#inventory-product-list-header-center'); 27427 27428 if (j.length === 1) { 27429 $('#inventory-product-list-header-left').css({ "margin-right": "75px" }); 27430 j.css({ "margin-right": "20px" }); 27431 } 27432 } 27433 27434 _conInventory.openHelp = function(helpLabel) { 27435 _morphPopup.onBeforeOpen(helpLabel); 27436 } 27437 27438 _conInventory.initHeaderHelpIcon = function() { 27439 _morphPopup = new UI.MorphPopup('#inventory-header-help.help-container', '#inventory-header-help-icon.helpIcon2'); //, '#inventory-help.help-content .x-close-img, #inventory-help.help-content .btnClose' 27440 27441 _morphPopup.onBeforeOpen = function(helpLabel) { 27442 var jicon = _morphPopup.getOpenButton(); // $('#inventory-header-help-icon'); 27443 var helpLabel = UTIL.coalesce(helpLabel, jicon.attr('help_label_vc')); 27444 27445 if (!UTIL.isEmpty(helpLabel)) { 27446 jicon.removeAttr('help_label_vc'); 27447 } else { 27448 var orderType = _conInventory.getOrderType(); 27449 var shipmentId = _conInventory.getShipmentId(); 27450 helpLabel = SA.Help.Inventory.getHelpLabel(orderType, shipmentId); 27451 } 27452 27453 if (helpLabel === 'create-order') { 27454 SA.Help.loadStep(0); 27455 } else if (helpLabel === 'send-order') { 27456 SA.Help.loadStep(2); 27457 } else if (helpLabel === 'receive-order') { 27458 SA.Help.loadStep(3); 27459 } else if (helpLabel === 'fill-order') { 27460 SA.Help.loadStep(3, 2); 27461 } else if (helpLabel === 'stock-order') { 27462 SA.Help.loadStep(3, 3); 27463 } else if (helpLabel === 'complete-order') { 27464 SA.Help.loadStep(3, 4); 27465 } else { //if (helpLabel === 'audit' || helpLabel === 'restock') { 27466 SA.Help.load(helpLabel); 27467 } 27468 } 27469 27470 //mp.onBeforeClose = function() { setTimeout(function() { $('.help-content').find('.wizard-step, .help-card').css({ "display": "none" }); }, 1200); } 27471 } 27472 27473 _conInventory.toggleAutoOrdering = function(element) { 27474 var jfieldset = $(element).closest('fieldset'); 27475 jfieldset.toggleClass('minimize'); 27476 } 27477 27478 _conInventory.setMaximumProductListRows = function(enable) {
27479 var productList = $('#inventory-table').find('tbody tr'); 27480 27481 if (!enable) { 27482 _MAX_DEFAULT_ROWS = productList.length; 27483 } else if (GLO.Info.isMobile(false)) { 27484 if (productList.length > 50) { 27485 _MAX_DEFAULT_ROWS = 25; 27486 } else { 27487 _MAX_DEFAULT_ROWS = productList.length; 27488 } 27489 } else { 27490 if (productList.length > 100) { 27491 _MAX_DEFAULT_ROWS = 50; 27492 } else { 27493 _MAX_DEFAULT_ROWS = productList.length; 27494 } 27495 } 27496 27497 if (_MAX_DEFAULT_ROWS !== productList.length) { _setInfiniteScroll(); } 27498 27499 $('#inventory-product-list-count').text(productList.length + ' products'); 27500 } 27501 27502 function _setInfiniteScroll() { 27503 $(window).scroll(function() { 27504 if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) { 27505 var productList = $('#inventory-table').find('tbody tr.hideTemp'); 27506 27507 if (productList.length) { 27508 var rowCount = 0, max = _MAX_DEFAULT_ROWS; 27509 if (_MAX_DEFAULT_ROWS > productList.length) { max = productList.length; } 27510 27511 for (var i=0; i < max; i++) { 27512 productList.eq(i).removeClass('hideTemp'); 27513 } 27514 } 27515 } 27516 }); 27517 } 27518 27519 _conInventory.editTaxRate = function() { 27520 var uri = GLO.Link.Object.Provider.Ajax + 'Tax'; 27521 var jpop = $('#pop-inventory-tax-rate').closest('.glopop'); 27522 27523 var inventoryTaxRate = jpop.find('#Edit_Inventory_Tax_Rate_pct').val(); //var serviceTaxRate = $('#Service_Tax_Rate_pct').val(); 27524 27525 if (jpop.length > 0) { 27526 var isSilent = true; 27527 GLO.Popup.close(jpop); 27528 } else { 27529 var isSilent = false; 27530 } 27531 27532 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Inventory_Tax_Rate_pct": inventoryTaxRate } }) //, "Service_Tax_Rate_pct": serviceTaxRate 27533 .success(function(data, textStatus, jqXHR) { 27534 if (UTIL.Validate.hasPermissionError(data)) { return; } 27535 27536 GLO.inventoryTax = UTIL.coalesceFloat(inventoryTaxRate, 0); 27537 27538 if (!isSilent) { 27539 new GLO.Popup.Success(SA.Resource.TaxRateUpdated); 27540 } 27541 }) 27542 .error(function(jqXHR, textStatus, errorThrown) { 27543 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 27544 }); 27545 } 27546 27547 _conInventory.goHome = function() { 27548 GLO.Inventory.updateHash(''); 27549 } 27550 27551 _conInventory.gotoList = function() { 27552 _conInventory.updateHash('product-list'); 27553 } 27554 27555 _conInventory.isProductListView = function(action) { 27556 if (action === 'restock' || action === 'audit' || action === 'order' || action === 'order-create' || action === 'order-list' || action === 'product-list-detail' || action === 'product-list') { 27557 return true; 27558 } else { 27559 return false; 27560 } 27561 } 27562 27563 function _setPrevHash() { 27564 var action = UTIL.cleanString(GLO.Uri.hash('action')).toLowerCase(); 27565 _conInventory.prevHash = action; 27566 _conInventory.prevHashId = UTIL.cleanString(GLO.Uri.hash('id')); 27567 27568 if (action === 'restock' || action === 'audit' || action === 'order' || action === 'order-create' || action === 'order-list' || action === 'product-list-detail' || action === 'product-list') { 27569 _conInventory.prevIsItem = false; 27570 _conInventory.prevItemId = null; 27571 } else if (action === 'inventory-options') { 27572 _conInventory.prevHash = ''; 27573 _conInventory.prevHashId = null; 27574 27575 _conInventory.prevIsItem = false; 27576 _conInventory.prevItemId = null; 27577 } else if (action === 'view-product' || action === 'edit-product' || action === 'new-product') { 27578 _conInventory.prevIsItem = true; 27579 _conInventory.prevItemId = _conInventory.prevHashId; 27580 } 27581 } 27582 27583 _conInventory.updateHash = function(action, id, back, subAction) { 27584 _setPrevHash(); 27585 27586 if (document.location.search.toLowerCase().indexOf('editshipmentid') !== -1) { 27587 try { 27588 var origin = window.location.protocol + "//" + window.location.host; //document.location.origin <-- doesn't work in non-Webkit browsers. 27589 var uri = origin + document.location.pathname + document.location.hash; 27590 window.history.replaceState("", "Report", uri); 27591 back = 'order-report'; 27592 } catch (e) { } 27593 } 27594 27595 if (UTIL.isEmpty(action)) { 27596 if (UTIL.cleanString(GLO.Uri.hash('action').toLowerCase()) === "product-list-intro") { 27597 _listProductIntro(); 27598 } else { 27599 action = 'product-list-intro'; 27600 } 27601 } 27602 27603 action = action.replace(' ', '-').toLowerCase(); 27604 27605 if (!UTIL.isEmpty(back)) { back = '&back=' + back; } 27606 if (!UTIL.isEmpty(subAction)) { subAction = '&and=' + subAction; } 27607 27608 if (!UTIL.isEmpty(id)) { 27609 document.location.hash = 'action=' + action + '&id=' + id + UTIL.cleanString(back) + UTIL.cleanString(subAction); 27610 } else { 27611 document.location.hash = 'action=' + action + UTIL.cleanString(back) + UTIL.cleanString(subAction); 27612 } 27613 } 27614 27615 function _hide() { 27616 $('#inventory-vendor-edit:visible, #inventory-distributor-edit:visible, #inventory-unit-edit:visible, #inventory-type-edit:visible, #inventory-type-category-edit:visible').addClass('hide'); 27617 $('#inventory-vendor-list:visible, #inventory-distributor-list:visible, #inventory-unit-list:visible, #inventory-type-list:visible, #inventory-type-category-list:visible').addClass('hide'); 27618 $('#inventory-location-edit:visible, #inventory-location-list:visible').addClass('hide'); 27619 $('#inventory-product-list-buttons:visible, #inventory-restock-buttons:visible, #inventory-item-form:visible, #inventory-item-view:visible').addClass('hide'); 27620 $('#inventory-product-line-list:visible, #inventory-product-line-edit:visible').addClass('hide'); 27621 $('#inventory-options:visible, #inventory-order-list-buttons:visible, #no-rows-found, #inventory-header-help-icon').addClass('hide'); 27622 $('#order-detail-header:visible, #inventory-order-header:visible, #inventory-search-results:visible').addClass('hide'); 27623 $('.inventory-header .btnBuyNow:visible, .inventory-header .btnReturnProduct:visible, #product-list-intro:visible').addClass('hide'); //#inventory-item-edit-cost:visible, 27624 27625 $('#inventory-table').removeClass('detail-view'); 27626 $('#manage-inventory:visible').addClass('hide').removeClass('order-body').removeClass('audit-body'); 27627 27628 $('#inventory-table.hide, #inventory-header-filter.hide, #inventory-header-options-link.hide, #inventory-header-reports-link.hide').removeClass('hide'); 27629 $('#bd-page > .shadow-content0').css({ "background-color": "" }); 27630 } 27631 27632 function _getFriendlyActionLabel(action) { 27633 action = UTIL.replaceAll(action, '-', ' '); 27634 27635 if (action === 'type list') { 27636 action = 'sub-category list'; 27637 } else if (action === 'type category list') { 27638 action = 'category list'; 27639 } else if (action === 'edit type') { 27640 action = 'edit sub-category'; 27641 } else if (action === 'edit type category') { 27642 action = 'edit category'; 27643 } else if (action === 'new type') {
27644 action = 'new sub-category'; 27645 } else if (action === 'new type category') { 27646 action = 'new category'; 27647 } 27648 27649 return action.replace('vendor', 'brand'); 27650 } 27651 27652 _conInventory.hashOnChange = function() { 27653 var action = GLO.Uri.hash('action'); 27654 var id = GLO.Uri.hash('id'); 27655 27656 _hide(); 27657 27658 /* 27659 if (document.location.search.toLowerCase().indexOf('editshipmentid') !== -1) { 27660 try { 27661 var uri = document.location.origin + document.location.pathname + document.location.hash; 27662 window.history.replaceState("", "Report", uri); 27663 } catch (e) { } 27664 }*/ 27665 27666 var actionLabel = _getFriendlyActionLabel(action); 27667 27668 var h2 = $('h2.inventory-header'); 27669 h2.find('.quietest-left').removeClass('hide'); 27670 h2.find('#inventory-header-text').text(actionLabel); 27671 //$('#doc3').css({ "width": "875px" }); 27672 27673 if (action === 'restock') { //if (location.pathname.indexOf('/inventory/shipment') !== -1) { 27674 GLO.Inventory.Restock.openEdit(id, 1); 27675 } else if (action === 'audit') { 27676 GLO.Inventory.Audit.openEdit(id, 200); 27677 } else if (action === 'order') { 27678 GLO.Inventory.Order.openEdit(id); 27679 } else if (action === 'order-create') { 27680 GLO.Inventory.Order.openEdit(); 27681 } else if (action === 'order-list') { 27682 GLO.Inventory.Order.openList(); 27683 27684 } else if (action === 'location-list') { 27685 GLO.Inventory.Location.openList(); 27686 27687 } else if (action === 'vendor-list') { 27688 GLO.Inventory.Vendor.openList(); 27689 } else if (action === 'distributor-list') { 27690 GLO.Inventory.Vendor.openDistributorList(); 27691 } else if (action === 'product-line-list') { 27692 GLO.Inventory.Vendor.openProductLineList(); 27693 27694 } else if (action === 'unit-list') { 27695 GLO.Inventory.Unit.openList(); 27696 } else if (action === 'type-list') { 27697 27698 GLO.Inventory.Type.openList(); 27699 } else if (action === 'type-category-list') { 27700 GLO.Inventory.Type.openCategoryList(); 27701 27702 } else if (action === 'view-product') { 27703 GLO.Inventory.Item.openView(id); 27704 } else if (action === 'edit-product' || action === 'new-product') { 27705 GLO.Inventory.Item.openEdit(id); 27706 27707 } else if (action === 'new-location') { 27708 GLO.Inventory.Location.openEdit(); 27709 } else if (action === 'edit-location') { 27710 _editLocation(id); 27711 27712 } else if (action === 'new-vendor') { 27713 GLO.Inventory.Vendor.openEdit(); 27714 } else if (action === 'edit-vendor') { 27715 _editVendor(id); 27716 } else if (action === 'new-distributor') { 27717 GLO.Inventory.Vendor.openDistributorEdit(); 27718 } else if (action === 'edit-distributor') { 27719 _editDistributor(id); 27720 } else if (action === 'new-product-line') { 27721 GLO.Inventory.Vendor.openProductLineEdit(); 27722 } else if (action === 'edit-product-line') { 27723 _editProductLine(id); 27724 27725 } else if (action === 'new-unit') { 27726 GLO.Inventory.Unit.openEdit(); 27727 } else if (action === 'edit-unit') { 27728 _editUnit(id); 27729 27730 } else if (action === 'new-type') { 27731 GLO.Inventory.Type.openEdit(); 27732 } else if (action === 'edit-type') { 27733 _editType(id); 27734 } else if (action === 'new-type-category') { 27735 GLO.Inventory.Type.openCategoryEdit(); 27736 } else if (action === 'edit-type-category') { 27737 _editTypeCategory(id); 27738 } else if (action === 'inventory-options') { 27739 _gotoStaffSetup(); 27740 } else if (action === 'product-list-detail') { 27741 GLO.Inventory.displayAllColumns(); 27742 } else if (action === 'product-list') { 27743 _listProduct(); 27744 } else { 27745 h2.find('.quietest-left').addClass('hide'); 27746 _listProductIntro(); 27747 } 27748 } 27749 27750 function _gotoStaffSetup() { 27751 if (GLO.Info.roleType > 219) { 27752 $('#inventory-options').removeClass('hide'); 27753 $('h2.inventory-header #inventory-header-text').text(SA.Resource.InventoryOptions); 27754 } else { 27755 var msg = '<div><b>Please Login as a Manager or Admin to setup</b> <ul style="text-align: left;">' 27756 + '<li style="list-style: disc outside;">Staff Product Sales Commission</li>' 27757 + '<li style="list-style: disc outside;">Employee Product Price Discounts</li>' 27758 + '</ul>'; 27759 27760 var jpop = GLO.Popup.Warning.open(msg, 'Admin or Manager Only').getPopup(); 27761 jpop.find('.msg').css({ "padding-top": "0", "padding-bottom": "0" }); 27762 27763 GLO.Inventory.updateHash('product-list-intro'); 27764 } 27765 } 27766 27767 function _listProductIntro() { 27768 if (_MAX_DEFAULT_ROWS < 50) { _listProduct(); return; } 27769 27770 var jManageInventory = $('#manage-inventory'); 27771 jManageInventory.find('#inventory-table').addClass('hide'); 27772 jManageInventory.removeClass('hide'); //do after hide inventory-table so do NOT require browser to render complete product list. 27773 27774 $('#product-list-intro').removeClass('hide'); 27775 $('h2.inventory-header #inventory-header-text').text(SA.Resource.ProductList); 27776 27777 if (!GLO.Info.isMobile()) { 27778 var w = GLO.Inventory.docWidth + 'px'; 27779 //$('#doc3').css({ "width": w }); 27780 27781 $('#inventory-product-list-buttons .btnDelete').addClass('hide'); 27782 } 27783 27784 _conInventory.filterClear(); 27785 GLO.Inventory.displayColumns(0, jManageInventory); 27786 } 27787 27788 function _listProduct() { 27789 var w = GLO.Inventory.docWidth + 'px'; 27790 //$('#doc3').css({ "width": w }); 27791 27792 $('h2.inventory-header #inventory-header-text').text(SA.Resource.ProductList); 27793 $('#inventory-product-list-buttons .btnDelete').removeClass('hide'); 27794 $('body').removeClass('display-all-columns'); 27795 27796 var jProductList = $('#manage-inventory').removeClass('hide').removeClass('display-all-columns'); 27797 jProductList.find('#item-row-box-all, .item-row-box input').removeClass('hide'); 27798 jProductList.find('.item-row-box .ui-icon-circle-close').addClass('hide'); 27799 27800 GLO.Inventory.displayColumns(0, jProductList); 27801 GLO.Inventory.filter(0); //calls: _conInventory.setFooter(0); //GLO.Inventory.filterReset(); 27802 } 27803 27804 function _listDisplayHeader(orderType, jManageInventory, id) { 27805 jManageInventory.find('.unfilled').removeClass('unfilled'); 27806 27807 if (orderType === 0) { 27808 jManageInventory.find('#inventory-product-list-buttons').removeClass('hide'); 27809 } else {
27810 jManageInventory.find('#inventory-product-list-buttons').addClass('hide'); 27811 } 27812 27813 if (orderType === 2 && UTIL.isEmpty(id)) { 27814 jManageInventory.find('#inventory-order-header').removeClass('hide'); 27815 } else { 27816 jManageInventory.find('#inventory-order-header').addClass('hide'); 27817 } 27818 } 27819 27820 _conInventory.clickCreateEdit = function(element) { 27821 var jbtn = $(element).parent(); 27822 var isCreate = jbtn.hasClass('btnCreate'); 27823 var jmenu = _conInventory.closeCreateEditMenu(isCreate, false); 27824 27825 setTimeout(function() { 27826 jbtn.toggleClass('is-active'); 27827 jmenu.toggleClass('is-active'); 27828 }, 100); 27829 } 27830 _conInventory.closeCreateEditMenu = function(isCreate, isCloseOnly) { 27831 if (isCreate) { 27832 var jmenu = $('#inventory-create-menu'); 27833 var jbtn = $('.fade-menu-container .btnCreate'); 27834 27835 //close the other menu (if open) 27836 $('#btnAddCreate .btnEdit.is-active').removeClass('is-active'); 27837 $('#inventory-edit-menu.is-active').removeClass('is-active').addClass('hide'); 27838 } else { 27839 var jmenu = $('#inventory-edit-menu'); 27840 var jbtn = $('.fade-menu-container .btnEdit'); 27841 27842 //close the other menu (if open) 27843 $('#btnAddCreate .btnCreate.is-active').removeClass('is-active'); 27844 $('#inventory-create-menu.is-active').removeClass('is-active').addClass('hide'); 27845 } 27846 27847 if (jmenu.hasClass('is-active')) { 27848 setTimeout(function() { jmenu.addClass('hide'); }, 900); 27849 } else { 27850 jmenu.removeClass('hide'); 27851 } 27852 27853 if (isCloseOnly) { 27854 setTimeout(function() { 27855 jbtn.removeClass('is-active'); 27856 jmenu.removeClass('is-active'); 27857 }, 100); 27858 } 27859 27860 return jmenu; 27861 } 27862 27863 _conInventory.gotoHash = function(hashUrl) { 27864 GLO.Inventory.updateHash(hashUrl); 27865 } 27866 27867 _conInventory.displayColumns = function(orderType, jManageInventory, id) { 27868 _listDisplayHeader(orderType, jManageInventory, id); 27869 27870 var hide = '.item-staff-price,', display = ''; 27871 27872 if (orderType === 0) { 27873 //jManageInventory.find('#item-in-stock-th-text').text('Current'); 27874 display += '.item-row-box, .item-row-box input, #displayAllLink, #header-stock-levels1, #header-stock-levels2,'; 27875 hide += '#displaySummaryView,'; 27876 } else { // = 1, 2, 4, 200. 27877 hide += '.item-row-box input, #displayAllLink, #displaySummaryView, #header-stock-levels1, #header-stock-levels2,'; 27878 } 27879 27880 if (orderType === 0 || orderType === 4) { 27881 hide += '.item-row-box .ui-icon-circle-close,'; 27882 } else { 27883 display += '.item-row-box .ui-icon-circle-close,'; 27884 } 27885 27886 if (orderType === 0 || orderType === 200) { 27887 display += '.item-in-stock, .item-cost,'; 27888 hide += '.item-cost-edit, .item-in-stock-edit,'; 27889 } else { 27890 display += '.item-cost-edit, .item-in-stock-edit,'; 27891 hide += '.item-cost, .item-in-stock,'; 27892 27893 jManageInventory.find('#inventory-table tbody tr').find('.item-in-stock-edit').each(function() { 27894 var me = $(this); //.removeClass('hide'); 27895 me.find('.new-in-stock-total').text(''); 27896 me.find('input').val(''); 27897 }); 27898 } 27899 27900 if (orderType === 4) { 27901 display += '.item-order-count,'; 27902 } else { 27903 hide += '.item-order-count,'; 27904 } 27905 27906 if (orderType === 4 || orderType == 200) { 27907 hide += '.item-type,'; 27908 } else { 27909 display += '.item-type,'; 27910 } 27911 27912 if (UTIL.isEmpty(id) && orderType !== 200) { 27913 display += '.item-type-category,'; 27914 } else { 27915 hide += '.item-type-category,'; 27916 } 27917 27918 if (orderType === 200) { 27919 display += '.item-upc, .item-sku, .item-audit, .item-audit-diff,'; 27920 hide += '.item-price, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission'; 27921 } else { 27922 display += '.item-price,'; 27923 hide += '.item-upc, .item-sku, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission, .item-audit, .item-audit-diff,'; 27924 } 27925 27926 display = display.substring(0, display.length - 1); 27927 hide = hide.substring(0, hide.length - 1); 27928 27929 jManageInventory.find(display).removeClass('hide'); 27930 jManageInventory.find(hide).addClass('hide'); 27931 } 27932 27933 function _editLocation(id) { 27934 var li = $('#inventory-location-list li[location_id="' + id + '"]'); 27935 27936 if (li.length > 0) { 27937 var nm = li.text(); 27938 GLO.Inventory.Location.openEdit(id, nm); 27939 } else { 27940 var jl = $('select#Location_id option[value="' + id + '"]'); 27941 27942 if (jl.length > 0) { 27943 var nm = jl.text(); 27944 GLO.Inventory.Location.openEdit(id, nm); 27945 } else { 27946 _conInventory.updateHash('location-list'); 27947 } 27948 } 27949 } 27950 27951 function _editVendor(id) { 27952 var li = $('#inventory-vendor-list li[vendor_id="' + id + '"]'); 27953 27954 if (li.length > 0) { 27955 var nm = UTIL.directTagOnly(li); 27956 var did = UTIL.cleanString(li.attr('distributor_id')); 27957 GLO.Inventory.Vendor.openEdit(id, nm, did); 27958 } else { 27959 var jv = $('select#Vendor_id option[value="' + id + '"]'); 27960 27961 if (jv.length > 0) { 27962 var did = jv.attr('distributor_id'); 27963 var nm = jv.text(); 27964 GLO.Inventory.Vendor.openEdit(id, nm, did); 27965 } else { 27966 _conInventory.updateHash('vendor-list'); 27967 } 27968 } 27969 } 27970 27971 function _editDistributor(id) { 27972 var li = $('#inventory-distributor-list li[distributor_id="' + id + '"]'); 27973 27974 if (li.length > 0) { 27975 GLO.Inventory.Vendor.openDistributorEdit(id, li.text()); 27976 } else { 27977 var jd = $('select#Distributor_id option[value="' + id + '"]'); 27978 27979 if (jd.length > 0) { 27980 GLO.Inventory.Vendor.openDistributorEdit(id, jd.text()); 27981 } else { 27982 _conInventory.updateHash('distributor-list'); 27983 } 27984 } 27985 } 27986 27987 function _editProductLine(id) { 27988 var li = $('#inventory-product-line-list li[product_line_id="' + id + '"]'); 27989 27990 if (li.length > 0) { 27991 var vid = UTIL.cleanString(li.attr('vendor_id')); 27992 GLO.Inventory.Vendor.openProductLineEdit(id, li.text(), vid); 27993 } else { 27994 var jpl = $('select#Product_Line_id option[value="' + id + '"]'); 27995 27996 if (jpl.length > 0) { 27997 var vid = jpl.attr('vendor_id'); 27998 GLO.Inventory.Vendor.openProductLineEdit(id, jpl.text(), vid); 27999 } else { 28000 _conInventory.updateHash('product-line-list'); 28001 } 28002 } 28003 } 28004 28005 function _editUnit(id) { 28006 var li = $('#inventory-unit-list li[unit_id="' + id + '"]'); 28007 28008 if (li.length > 0) { 28009 GLO.Inventory.Unit.openEdit(id, li.text(), UTIL.cleanString(li.attr('title'))); 28010 } else { 28011 _conInventory.updateHash('unit-list'); 28012 return; 28013 } 28014 } 28015 28016 function _editType(id) { 28017 var li = $('#inventory-type-list li[inventory_type_id="' + id + '"]'); 28018 28019 if (li.length > 0) { 28020 var nm = li.text(); 28021 var tcid = UTIL.cleanString(li.attr('type_category_id')); 28022 GLO.Inventory.Type.openEdit(id, nm, tcid); 28023 } else { 28024 var jt = $('select#Inventory_Type_id option[value="' + id + '"]'); 28025 28026 if (jt.length > 0) { 28027 var tcid = jt.attr('type_category_id'); 28028 var nm = jt.text(); 28029 GLO.Inventory.Type.openEdit(id, nm, tcid); 28030 } else { 28031 _conInventory.updateHash('type-list'); 28032 } 28033 } 28034 } 28035 28036 function _editTypeCategory(id) { 28037 var li = $('#inventory-type-category-list li[type_category_id="' + id + '"]'); 28038 28039 if (li.length > 0) { 28040 GLO.Inventory.Type.openCategoryEdit(id, li.text()); 28041 } else { 28042 var jt = $('select#Type_Category_id option[value="' + id + '"]'); 28043 28044 if (jt.length > 0) { 28045 GLO.Inventory.Type.openCategoryEdit(id, jt.text()); 28046 } else { 28047 _conInventory.updateHash('type-category-list'); 28048 } 28049 } 28050 } 28051 28052 _conInventory.filterHide = function() { 28053 var jhead = $('#inventory-header-filter'); 28054 28055 var vendorId = jhead.find('#Filter_Company').val(''); 28056 var distributorId = jhead.find('#Filter_Category').val(''); 28057 var typeId = jhead.find('#Filter_Stock_Level').val('hide'); 28058 28059 var orderType = _conInventory.getOrderType(); 28060 _conInventory.filter(orderType, true); 28061 } 28062 28063 _conInventory.filterClear = function() { 28064 var jhead = $('#inventory-header-filter'); 28065 28066 var vendorId = jhead.find('#Filter_Company').val(''); 28067 var distributorId = jhead.find('#Filter_Category').val(''); 28068 var typeId = jhead.find('#Filter_Stock_Level').val(''); 28069 28070 _conInventory.filterOnChange(jhead); 28071 } 28072 28073 _conInventory.filterReset = function() { 28074 var orderType = _conInventory.getOrderType(); 28075 28076 if (orderType == 200) { 28077 _conInventory.filterClear(); 28078 _conInventory.updateHash(''); //_listProductIntro(); 28079 } else if (orderType > 1) { 28080 _conInventory.filterClear(); 28081 _conInventory.filter(orderType); 28082 } else { 28083 _conInventory.filterClear(); 28084 _conInventory.updateHash(''); //_listProductIntro(); 28085 } 28086 28087 $('#inventory-product-list-buttons-table .fade-menu-container .btnAdd.is-active > a').click(); 28088 } 28089 28090 _conInventory.getOrderType = function() { 28091 var orderName = $('h2.inventory-header').find('#inventory-header-text').text().toLowerCase(); 28092 var orderType = 0; 28093 28094 if (orderName === 're-stock') { 28095 orderType = 1; 28096 } else if (orderName.indexOf('order') !== -1) { 28097 orderType = 2; 28098 var jDTs = $('#inventory-order-dates'); 28099 28100 if (!UTIL.isEmpty(jDTs.find('#Order_Received_dt:visible').val()) || !UTIL.isEmpty(jDTs.find('#Stock_dt:visible').text()) ) { 28101 orderType = 4; 28102 } 28103 } else if (orderName.indexOf('inventory check') !== -1 || orderName.indexOf('audit') !== -1) { 28104 orderType = 200; 28105 } 28106 28107 return orderType; 28108 } 28109 28110 _conInventory.filterIntro = function() { 28111 var me = $(this); 28112 var val = me.attr('vid'); 28113 28114 if (!UTIL.isEmpty(val)) { 28115 $('#Filter_Company').val('v' + val); 28116 } else { 28117 val = me.attr('val'); 28118 $('#Filter_Stock_Level').val(val); 28119 } 28120 28121 var currText = me.text(); 28122 28123 me.html('<span style="text-transform: lowercase; color: #275264; background-color: Yellow; display: block; height: 100%; width: 100%; border-radius: 8px; padding: 7px 0; font-weight: bold;">loading...</span>'); //var throbber = $('.loadingDiv').find('img').css({ "margin": "0" }).outerHTML(); 28124 window.setTimeout(function() { me.text(currText); }, 2500); 28125 28126 window.setTimeout(function() { 28127 GLO.Inventory.updateHash('product-list'); 28128 //GLO.Inventory.filter(0); 28129 }, 50); 28130 28131 _conInventory.filterOnChange(); 28132 } 28133 28134 _conInventory.filterNoBrand = function() { 28135 _filterInProgress = true; 28136 28137 var rowCount = 0; 28138 var orderType = _conInventory.getOrderType(); 28139 28140 $('#product-list-intro').addClass('hide'); 28141
28142 var tbl = $('#inventory-table').addClass('hide'); 28143 var jrows = tbl.find('tbody tr'); 28144 28145 jrows.each(function() { 28146 var me = $(this); 28147 28148 if (UTIL.isEmpty(me.find('.item-vendor').attr('vendor_id'))) { 28149 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28150 } else { 28151 _conInventory.hideRow(me); 28152 } 28153 }); 28154 28155 tbl.removeClass('hide'); 28156 $('#inventory-table.hide, #inventory-product-list-buttons .btnDelete').removeClass('hide'); 28157 28158 _conInventory.setFooter(orderType); 28159 _filterInProgress = false; 28160 } 28161 28162 _conInventory.filter = function(orderType, isHide) { 28163 //console.log('Inventory Filter Start: ' + new Date()); 28164 28165 if (document.location.hash.indexOf('action=product-list-intro') !== -1) { 28166 document.location.hash = document.location.hash.replace('product-list-intro', 'product-list'); 28167 return; 28168 } 28169 28170 //var jMainProcessing = GLO.Popup.Processing.open('Filtering Products...', 'Manage Inventory').getPopup().addClass('pop-stick-to-top'); 28171 28172 if (UTIL.isEmpty(orderType)) { orderType = _conInventory.getOrderType(); } 28173 $('#product-list-intro').addClass('hide'); 28174 28175 var tbl = $('#inventory-table').addClass('hide'); 28176 var jrows = tbl.find('tbody tr'); 28177 var jhead = $('#inventory-header-action-container'); 28178 28179 var company = jhead.find('#Filter_Company').val(); 28180 var category = jhead.find('#Filter_Category').val(); 28181 28182 if (isHide) { 28183 var stockLevel = 'hide'; 28184 jhead.find('#Filter_Company').prepend('<option value="hide"></option>'); 28185 } else { 28186 var stockLevel = jhead.find('#Filter_Stock_Level').val(); 28187 jhead.find('#Filter_Company option[value="hide"]').remove(); 28188 } 28189 28190 GLO.UI.Form.beginProcessing( jhead.find('.btnFilterHide') ); 28191 GLO.UI.Form.beginProcessing( jhead.find('.btnFilterAll') ); 28192 28193 var prefix, id, rowCount = 0, hasPreviousFilter = false; 28194 var action = GLO.Uri.hash('action').toLowerCase(); 28195 //console.log('Inventory Pre-Filter: ' + new Date()); 28196 28197 if (action === 'product-list' || action === 'product-list-intro' || action === '') { _filterInProgress = true; } 28198 28199 if (company || category || stockLevel) { 28200 jrows.addClass('hide'); 28201 /* jrows.each(function() { //= this was really slow (sometimes took 90 seconds if > 1,000 products) so just calling addClass 28202 var me = $(this); 28203 28204 if (!me.hasClass('hide')) { 28205 _conInventory.hideRow(me); 28206 } 28207 }); */ 28208 28209 //console.log('Inventory Filter Hide Complete: ' + new Date()); 28210 28211 if (!UTIL.isEmpty(company)) { 28212 //console.log('Inventory Filter Company: ' + new Date()); 28213 prefix = company.substring(0, 1); 28214 id = company.substring(1); 28215 28216 if (prefix == 'd') { 28217 jrows.each(function() { 28218 var me = $(this); 28219 28220 if (me.attr('distributor_id') == id) { 28221 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28222 } 28223 }); 28224 } else if (prefix == 'v') { 28225 jrows.each(function() { 28226 var me = $(this); 28227 28228 if (me.find('.item-vendor').attr('vendor_id') == id) { 28229 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28230 } 28231 }); 28232 } else if (prefix == 'p') { 28233 jrows.each(function() { 28234 var me = $(this); 28235 28236 if (me.find('.item-product-line').attr('product_line_id') == id) { 28237 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28238 } 28239 }); 28240 } 28241 28242 if (company !== 'hide') { hasPreviousFilter = true; } 28243 } 28244 28245 if (!UTIL.isEmpty(category)) { 28246 //console.log('Inventory Filter Category: ' + new Date()); 28247 prefix = category.substring(0, 1); 28248 id = category.substring(1); 28249 28250 if (prefix == 'c') { 28251 jrows.each(function() { 28252 var me = $(this); 28253 if (me.find('.item-type-category').attr('type_category_id') == id) { 28254 if (!hasPreviousFilter) { 28255 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28256 } 28257 } else if (hasPreviousFilter) { 28258 _conInventory.hideRow(me); 28259 } 28260 }); 28261 } else if (prefix == 't') { 28262 jrows.each(function() { 28263 var me = $(this); 28264 if (me.find('.item-type').attr('type_id') == id) { 28265 if (!hasPreviousFilter) { 28266 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28267 } 28268 } else if (hasPreviousFilter) { 28269 _conInventory.hideRow(me); 28270 } 28271 }); 28272 } 28273 28274 hasPreviousFilter = true; 28275 } 28276 28277 if (!UTIL.isEmpty(stockLevel) && stockLevel !== 'hide') { 28278 //console.log('Inventory Filter Stock Level: ' + new Date()); 28279 stock = jrows.eq(i).find('.item-in-stock').text(); 28280 28281 jrows.each(function() { 28282 var me = $(this); 28283 28284 var desired = me.find('.item-minimum-stock').text(); 28285 var stock = me.find('.item-in-stock-edit input:visible'); 28286 28287 if (stock.length === 1) { 28288 stock = stock.val(); 28289 } else { 28290 stock = me.find('.item-in-stock').text(); 28291 } 28292 28293 stock = UTIL.coalesceInt(stock, 0); 28294 28295 if (stockLevel === 'in' && stock > 0) { 28296 if (!hasPreviousFilter) { 28297 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28298 } 28299 } else if (stockLevel === 'out' && stock <= 0) { 28300 if (!hasPreviousFilter) { 28301 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28302 } 28303 } else if (UTIL.isNumber(desired)) { 28304 desired = parseFloat(desired); 28305 28306 if (stockLevel === 'low' && desired > stock) { 28307 if (!hasPreviousFilter) { 28308 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28309 } 28310 } else if (stockLevel === 'high' && stock > desired) { 28311 if (!hasPreviousFilter) { 28312 rowCount = _conInventory.displayRow(me, rowCount, orderType); 28313 } 28314 } else if (hasPreviousFilter) { 28315 _conInventory.hideRow(me); 28316 } 28317 } else if (hasPreviousFilter) { 28318 _conInventory.hideRow(me); 28319 } 28320 }); 28321 } 28322 } else { 28323 //console.log('Inventory Filter Display: ' + new Date()); 28324 28325 for (var i=0; i < jrows.length; i++) { 28326 rowCount = _conInventory.displayRow(jrows.eq(i), rowCount, orderType); 28327 } 28328 } 28329 28330 //console.log('Inventory Filter Almost Complete: ' + new Date()); 28331 28332 $('h2.inventory-header .quietest-left').removeClass('hide'); 28333 _displayNoRows(); 28334 _filterInProgress = false; 28335 tbl.removeClass('hide'); 28336 $('#inventory-table.hide').removeClass('hide'); 28337 28338 _conInventory.filterOnChange(jhead); 28339 _conInventory.setFooter(orderType); 28340 GLO.UI.Form.resetProcessing(); 28341 //GLO.Popup.close(jMainProcessing); 28342 //GLO.Popup.Info.open('Filter Finished', 'Complete'); 28343 //console.log('Inventory Filter Finished: ' + new Date()); 28344 } 28345 28346 _conInventory.filterOnChange = function(jfilter) { 28347 if (jfilter === undefined) { jfilter = $('#inventory-header-filter'); } 28348 28349 var jco = jfilter.find('#Filter_Company'); 28350 var jcategory = jfilter.find('#Filter_Category'); 28351 var jlevel = jfilter.find('#Filter_Stock_Level'); 28352 28353 var tr = jfilter.find('tr:first'); 28354 28355 if (_filterOnChange2(jco) || _filterOnChange2(jcategory) || _filterOnChange2(jlevel)) { 28356 tr.addClass('filter-on'); 28357 } else { 28358 tr.removeClass('filter-on'); 28359 } 28360 } 28361 28362 function _filterOnChange2(jdd) { 28363 var td = jdd.closest('td'); 28364 28365 if (!UTIL.isEmpty(jdd.val())) { 28366 td.css({ "background-color": "springgreen" }); 28367 return true; 28368 } else { 28369 td.css({ "background-color": "" }); 28370 return false; 28371 } 28372 } 28373 28374 function _displayNoRows() { 28375 var j = $('#manage-inventory'); 28376 var jhead = j.find('#inventory-header-filter'); 28377 var rowCount = j.find('#inventory-table').find('tbody > tr:not(.hide)').length; 28378 28379 if (rowCount > 0 || !UTIL.isEmpty(jhead.find('#Filter_Stock_Level').val())) { 28380 _displayNoRowInfo(false, j); 28381 return; 28382 } 28383 28384 var fcat = jhead.find('#Filter_Category').val(); 28385 var fco = jhead.find('#Filter_Company').val(); 28386 28387 var jco = jhead.find('#Filter_Company'); 28388 var jco2 = jco.find('option:selected'); 28389 var jco3 = jco2.text(); 28390 28391 if ((!UTIL.isEmpty(fcat) && !UTIL.isEmpty(fco)) || (UTIL.isEmpty(fcat) && UTIL.isEmpty(fco))) { 28392 _displayNoRowInfo(false, j); 28393 return; 28394 } else if (!UTIL.isEmpty(fcat)) { 28395 var name = jhead.find('#Filter_Category :selected').text(); 28396 } else { 28397 var name = jhead.find('#Filter_Company :selected').text(); 28398 } 28399 28400 name = $.trim(name); 28401 _displayNoRowInfo(true, j, fcat, fco, name); 28402 } 28403 28404 function _displayNoRowInfo(mustDisplay, j, fcat, fco, name) { 28405 var jNoRows = j.find('#no-rows-found'); 28406 jNoRows.find('#no-rows-found-info').remove(); 28407 28408 if (mustDisplay) { 28409 var filter = UTIL.coalesce(fcat, fco); 28410 var f1 = filter.substring(0,1); 28411 var id = filter.substring(1); 28412 28413 if (f1 === 'v') { 28414 var label = 'vendor'; 28415 } else if (f1 === 'p') { 28416 var label = 'product-line'; 28417 } else if (f1 === 'c') { 28418 var label = 'type-category'; 28419 } else if (f1 === 't') { 28420 var label = 'type'; 28421 } else if (f1 === 'd') { 28422 var label = 'distributor'; 28423 } 28424 28425 var onclick = 'GLO.Inventory.updateHash(\'edit-' + label + '\', ' + id + ')'; 28426 var btn = '<span class="btnAdd" onclick="' + onclick + '"> <a style="text-transform: capitalize;">Edit / Delete ' + name + '</a> </span>'; //label.replace('-', ' ').replace('vendor', 'brand') 28427 28428 jNoRows.find('#create-new-product-for').text(name); 28429 jNoRows.append('<div id="no-rows-found-info">' + btn + '</div>'); 28430 jNoRows.removeClass('hide'); 28431 } else { 28432 jNoRows.addClass('hide'); 28433 } 28434 } 28435 28436 _conInventory.hideRow = function(tr) { 28437 tr.addClass('hide'); 28438 28439 if (!_filterInProgress) { 28440 tr.find('.item-cost-edit input').val( tr.find('.item-cost').text().replace('$', '') ); 28441 28442 var cntEdit = tr.find('.item-in-stock-edit'); 28443 cntEdit.find('input').val(''); 28444 cntEdit.find('.new-in-stock-total').text(''); 28445 28446 $('#inventory-restock-buttons-row:visible, #inventory-order-dates-buttons:visible').find('.btnSave a:visible').css({ "border": "3px solid Red" }); 28447 } 28448 } 28449 28450 _conInventory.displayRow = function(tr, rowNumber, orderType) { 28451 if (orderType === 200) { 28452 if (tr.attr('track_stock_fl') === '0') { return rowNumber; } 28453 } 28454 28455 if (rowNumber < _MAX_DEFAULT_ROWS) { 28456 tr.removeClass('hide hideTemp'); 28457 } else { 28458 tr.addClass('hideTemp'); 28459 tr.removeClass('hide'); 28460 } 28461 28462 return ++rowNumber; 28463 } 28464 28465 _conInventory.setFooter = function(orderType) { // = Order_Type_cd: 1 = Restock, 2 = Order, 3 = Product List (but here orderType = 0), 200 = Audit. 28466 if (UTIL.isEmpty(orderType)) { orderType = GLO.Inventory.getOrderType(); } 28467
28468 var jtbl = $('#inventory-table'); 28469 var tfoot = jtbl.find('tfoot'); 28470 var jrows = jtbl.find('tbody tr:visible'); 28471 var cost, price, stock, actual, diff, sdiff, torder = 0, tcost = 0, tprice = 0, tstock = 0, tActual = 0, tdiff = 0; 28472 28473 for (var i=0; i < jrows.length; i++) { 28474 price = jrows.eq(i).find('.item-price').text().replace('$', ''); 28475 28476 cost = jrows.eq(i).find('.item-cost:visible').text().replace('$', ''); 28477 if (cost === "") { cost = jrows.eq(i).find('.item-cost-edit input:visible').val(); } 28478 28479 if (orderType === 0 || orderType === 200) { 28480 stock = jrows.eq(i).find('.item-in-stock').text(); 28481 } else { 28482 stock = jrows.eq(i).find('.item-in-stock-edit input').val(); 28483 torder += UTIL.coalesceInt(jrows.eq(i).find('.item-order-count input').val(), 0); 28484 } 28485 28486 if (UTIL.isNumber(stock)) { 28487 stock = parseFloat(stock); 28488 28489 if (stock > 0) { 28490 tstock += stock; 28491 28492 if (UTIL.isNumber(cost, true)) { 28493 tcost += UTIL.coalesceMoney(cost) * stock; 28494 } 28495 28496 if (UTIL.isNumber(price, true)) { 28497 tprice += UTIL.coalesceMoney(price) * stock; 28498 } 28499 } 28500 } 28501 28502 if (orderType === 200) { 28503 actual = jrows.eq(i).find('.item-audit input').val(); 28504 28505 if (UTIL.isNumber(actual)) { 28506 actual = Number(actual); 28507 diff = actual - stock; 28508 tdiff += diff; 28509 tActual += actual; 28510 28511 if (diff === 0) { 28512 sdiff = ''; 28513 } else if (diff > 0) { 28514 sdiff = '<span style="color: Black;">+' + diff + '</span>'; 28515 } else { 28516 sdiff = '<span style="color: Red;">' + diff + '</span>'; 28517 } 28518 } else { 28519 sdiff = ''; diff = 0; 28520 } 28521 28522 jrows.eq(i).find('.item-audit-diff').html(sdiff).attr('order_by', diff); 28523 } 28524 } 28525 28526 if (UTIL.isNumber(tcost, true)) { tcost = '$' + UTIL.numberWithCommas(UTIL.roundMoney(tcost)); } 28527 if (UTIL.isNumber(tprice, true)) { tprice = '$' + UTIL.numberWithCommas(UTIL.roundMoney(tprice)); } 28528 28529 if (UTIL.isNumber(tstock)) { 28530 tstock = UTIL.numberWithCommas(UTIL.roundMoney(tstock)); 28531 28532 if (tstock.substring(tstock.length - 3) === '.00') { tstock = tstock.substring(0, tstock.length - 3); } 28533 } 28534 28535 if (orderType === 200) { 28536 tcost = ''; 28537 tfoot.find('.item-audit').text(tActual); 28538 tfoot.find('.item-audit-diff').text(tdiff); 28539 } 28540 28541 tfoot.find('.item-cost-parent').text(tcost); 28542 tfoot.find('.item-price').text(tprice); 28543 tfoot.find('.item-in-stock-parent').text(tstock); 28544 tfoot.find('.item-order-count').text(torder); 28545 } 28546 28547 _conInventory.closeSummary = function() { 28548 var jsummarypop = $('#inventory-item-summary'); 28549 var jpop = jsummarypop.closest('.glopop'); 28550 28551 if (jpop.length > 0) { 28552 GLO.Popup.close(jpop); 28553 } else { 28554 $.modal.close(); 28555 } 28556 } 28557 _conInventory.openSummary = function(id) { 28558 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + id + '&dt=' + UTIL.getDateString(); 28559 28560 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}); 28561 var pop = $('#pop-temp'); 28562 28563 pop.html(throbber).load(uri, GLO.Inventory.openSummary2); 28564 pop.modal(); 28565 28566 if (GLO.Info.isMobile()) { 28567 $.modal.update(300, 300); 28568 } else { 28569 $.modal.update(300, 720); 28570 } 28571 } 28572 _conInventory.openSummaryAdjust = function(isAdjustHeight) { 28573 var maxHeight = parseInt(innerHeight * .9); 28574 var pop2 = $('#simplemodal-container').css({ "padding": "0", "max-height": maxHeight + "px" }); 28575 var pop = pop2.find('#pop-temp').css('padding', '0'); 28576 28577 /* 28578 if (GLO.Info.isMobile()) { 28579 pop2.css({ "min-width": "300px", "max-width": "720px", "max-height": "inherit", "margin": "auto", "padding": "0" }); 28580 } 28581 28582 if (outerHeight > 980) { 28583 pop2.css({ "max-height": "900px" }); 28584 } else if (outerHeight > 860) { 28585 pop2.css({ "max-height": "800px" }); 28586 } 28587 28588 pop2.find('#product-summary-buttons-parent').removeClass('hide'); 28589 */ 28590 28591 if (isAdjustHeight) { 28592 var hsummary = pop2.find('#inventory-item-summary').height(); //+ 50 28593 28594 if (hsummary > pop2.height()) { 28595 $.modal.update(hsummary, null); 28596 } 28597 } 28598 28599 var hpop = pop2.height(); 28600 var hbody = pop2.find('#inventory-item-summary-body').height(); 28601 28602 if (hbody > hpop) { 28603 var hBody = hpop - pop2.find('h1').height(); 28604 28605 pop2.find('#inventory-item-summary-body').addClass('friendly-mini-scroll').css({ "max-height": hBody + 'px' }); 28606 } 28607 28608 if (pop2.width() > innerWidth) { 28609 $.modal.update(null, innerWidth - 20); 28610 } 28611 28612 pop2.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" }); 28613 GLO.UI.initAnimateNewLink(pop2, 'h1 > a'); 28614 GLO.Inventory.Location.initProductSummary(pop2); 28615 } 28616 _conInventory.openSummary2 = function(responseText, textStatus, XMLHttpRequest) { 28617 var pop2 = $('#simplemodal-container').css('padding', '0'); 28618 var pop = pop2.find('#pop-temp').css('padding', '0'); 28619 28620 if (GLO.Log.processesSecurityException(pop, responseText, textStatus, XMLHttpRequest)) { return; } 28621 28622 pop2.html(responseText); 28623 _conInventory.openSummaryAdjust(true); 28624 } 28625 _conInventory.openSummaryFromItem = function() { 28626 var id = $('#inventory-item-form').find('#Inventory_id').val(); 28627 _conInventory.openSummary(id); 28628 } 28629 28630 _conInventory.gotoReports = function() { 28631 document.location = GLO.Link.Page.Provider.Home + 'reports/inventory'; 28632 } 28633 28634 _conInventory.gotoOptions = function() { 28635 _conInventory.updateHash('inventory-options'); 28636 } 28637 28638 _conInventory.saveOptions = function() { 28639 var j = $('#inventory-options'); 28640 28641 var epriceMoney = j.find('#Employee_Price_Default_mn'); 28642 var epricePercent = j.find('#Employee_Price_Default_pct'); 28643 var epriceBelow = j.find('#Employee_Price_Default_Below_pct'); 28644 28645 if (epriceMoney.val() !== epriceMoney.attr('original') || epricePercent.val() !== epricePercent.attr('original')) { 28646 _conInventory.openStaffPricesBulkUpdate(); 28647 28648 var jpop = $('#inventory-options-mass-update'); 28649 jpop.find('#Bulk_Update_Employee_Price_mn').val(epriceMoney.val()); 28650 jpop.find('#Bulk_Update_Employee_Price_pct').val(epricePercent.val()); 28651 jpop.find('#Bulk_Update_Employee_Price_Below_pct').val(epriceBelow.val()); 28652 jpop.find('#Employee_Price_Update_cd').val('new'); 28653 } else { 28654 _conInventory.saveOptionsConfirmed(); 28655 } 28656 } 28657 28658 _conInventory.openStaffPricesBulkUpdate = function() { 28659 var dd = $('#Filter_Company').clone().attr('id', 'Employee_Price_Update_cd'); 28660 var opt1 = dd.find('option:first').attr('value', 'all');
28661 var inputCSS = 'letter-spacing: 1px; font-size: 16px;'; 28662 var labelCSS = 'letter-spacing: 1px; font-size: 16px;'; 28663 28664 var joptions = $('#inventory-options'); 28665 var dollarAboveCost = UTIL.displayMoney(joptions.find('#Employee_Price_Default_mn').val(), true); 28666 var percentAboveCost = UTIL.displayMoney(joptions.find('#Employee_Price_Default_pct').val(), true); 28667 var percentBelowPrice = UTIL.displayMoney(joptions.find('#Employee_Price_Default_Below_pct').val(), true); 28668 28669 var divEdit = '<div id="inventory-options-mass-update-input" style="margin-bottom: 35px;">' 28670 + '<div style="letter-spacing: 2px; text-align: center; text-transform: capitalize; font-size: 20px; font-weight: bold;">' + SA.Resource.UpdateStaffPriceTo + '</div>' 28671 + '<div style="max-width: 280px; margin: auto; margin-top: 12px; text-align: left; letter-spacing: 1px;">' 28672 + '<div>' 28673 + '<label for="Bulk_Update_Employee_Price_mn" style="' + labelCSS + 'margin-right: 2px; font-weight: bold;">$</label>' 28674 + '<input id="Bulk_Update_Employee_Price_mn" type="text" value="' + dollarAboveCost + '" maxlength="6" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 60px;' + inputCSS + 'margin-right: 12px;"/>' 28675 + '<label for="Bulk_Update_Employee_Price_mn" style="' + labelCSS + '">' + SA.Resource.above_cost + '</label>' 28676 + '</div>' 28677 + '<div style="margin-top: 10px; margin-bottom: 10px; margin-left: 2px;">' 28678 + '<label style="' + labelCSS + '"> ' + SA.Resource.or_text + ' </label>' 28679 + '<input id="Bulk_Update_Employee_Price_pct" type="text" value="' + percentAboveCost + '" maxlength="4" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 40px;' + inputCSS + 'margin-left: 4px;"/>' 28680 + '<label for="Bulk_Update_Employee_Price_pct" style="font-size: 16px; font-weight: bold; margin-left: 2px; margin-right: 9px;">%</label>' 28681 + '<label for="Bulk_Update_Employee_Price_pct" style="' + labelCSS + '">' + SA.Resource.above_cost + '</label>' 28682 + '</div>' 28683 + '<div style="margin-left: 2px; white-space: nowrap;">' 28684 + '<label style="' + labelCSS + '"> ' + SA.Resource.or_text + ' </label>' 28685 + '<input id="Bulk_Update_Employee_Price_Below_pct" type="text" value="' + percentBelowPrice + '" maxlength="4" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 40px;' + inputCSS + 'margin-left: 4px;"/>' 28686 + '<label for="Bulk_Update_Employee_Price_Below_pct" style="' + labelCSS + 'font-weight: bold; margin-left: 2px; margin-right: 8px;">%</label>' 28687 + '<label for="Bulk_Update_Employee_Price_Below_pct" style="' + labelCSS + '">' + SA.Resource.below_regular_price + '</label>' 28688 + '</div>' 28689 + '</div>' 28690 + '</div>'; 28691 28692 opt1.text(SA.Resource.AllProducts); 28693 opt1.after('<optgroup></optgroup>'); 28694 opt1.after('<option value="empty">' + SA.Resource.ProductNoStaffPrice + '</option>'); 28695 opt1.after('<option value="new" title="' + SA.Resource.NewProductStaffPriceHelp + '">' + SA.Resource.OnlyNewProducts + '</option>') 28696 28697 var div = $('<div id="inventory-options-mass-update">' 28698 + '<h1 style="letter-spacing: 2px; text-transform: capitalize; font-size: 20px;">' + SA.Resource.ChangeCurrentStaffPrices + '?</h1>' 28699 + '<div id="inventory-options-mass-update-body" style="text-align: center;">' 28700 + divEdit 28701 + '<label for="Employee_Price_Update_cd" style="display: block; margin: 10px; margin-top: 50px; text-align: center; letter-spacing: 1px; white-space: inherit;">' + SA.Resource.ProductUpdateStaffPrice + '</label>' 28702 + dd.outerHTML() 28703 + '</div></div>'); 28704 28705 var jpop = GLO.Popup.Custom(div, GLO.Inventory.saveOptionsConfirmed); 28706 jpop = jpop.getPopup(); 28707 jpop.find('.pop-buttons').css({ "width": "300px", "white-space": "nowrap", "margin-top": "35px" }); 28708 } 28709 28710 _conInventory.saveOptionsConfirmed = function() { 28711 var jpop = $('#inventory-options-mass-update'); 28712 28713 if (jpop.length === 1) { 28714 var epriceUpdateId = jpop.find('#Employee_Price_Update_cd:visible').val(); 28715 var epriceMoney = jpop.find('#Bulk_Update_Employee_Price_mn').val(); 28716 var epricePercent = jpop.find('#Bulk_Update_Employee_Price_pct').val(); 28717 var ePriceBelowPercent = jpop.find('#Bulk_Update_Employee_Price_Below_pct').val(); 28718 } else { 28719 var epriceUpdateId = ''; 28720 var jdoc = $('#inventory-options'); 28721 var epriceMoney = jdoc.find('#Employee_Price_Default_mn').val(); 28722 var epricePercent = jdoc.find('#Employee_Price_Default_pct').val(); 28723 var ePriceBelowPercent = jdoc.find('#Employee_Price_Default_Below_pct').val(); 28724 } 28725 28726 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Options'; 28727 var j = $('#inventory-options'); 28728 28729 var inventoryTax = j.find('#Inventory_Tax_Rate_pct').val(); 28730 var serviceTax = j.find('#Service_Tax_Rate_pct').val(); 28731 var commission = j.find('#Inventory_Staff_Commission_pct').val(); 28732 28733 var jd = { "inventoryTaxRate": inventoryTax, "serviceTaxRate": serviceTax, "employeeCommission": commission 28734 , "employeePriceDefaultMoney": epriceMoney, "employeePriceDefaultPercent": epricePercent, "employeePriceDefaultBelowPercent": ePriceBelowPercent 28735 , "employeePriceUpdateId": epriceUpdateId }; 28736
28737 GLO.Popup.close( $('#inventory-options-mass-update').closest('.glopop') ); 28738 28739 var saveBtn = j.find('.btnSave'); 28740 saveBtn.find('a').css({ "border": "3px solid transparent" }); 28741 GLO.UI.Form.beginProcessing( saveBtn ); 28742 28743 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 28744 .success(function(data, textStatus, jqXHR) { 28745 if (UTIL.Validate.hasPermissionError(data)) { return; } 28746 28747 GLO.inventoryTax = inventoryTax; 28748 GLO.serviceTax = serviceTax; 28749 28750 new GLO.Popup.Success(SA.Resource.SuccessfullySaved); 28751 location.reload(); //_conInventory.updateHash('product-list'); 28752 }) 28753 .error(function(jqXHR, textStatus, errorThrown) { 28754 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 28755 GLO.UI.Form.resetProcessing(); 28756 }); 28757 } 28758 28759 _conInventory.confirmCommission = function(element) { } //called on Inventory Options (can delete call + this function). 28760 28761 _conInventory.confirmTaxRate = function(element) { //called on Inventory Options (can delete call + this function). 28762 return; 28763 /* 28764 var j = $(element); 28765 var tax0 = UTIL.coalesceInt(j.attr('original'), 0); 28766 var tax1 = UTIL.coalesceInt(j.val(), 0); 28767 28768 new GLO.Popup.Confirm(SA.Resource.ChangeTaxRateQuestion + ' ' + tax0 + '% ' + SA.Resource.to_text + ' ' + tax1 + '%?', GLO.Inventory.editTaxRate, function() { 28769 j.val(j.attr('original')); 28770 }); 28771 */ 28772 } 28773 28774 _conInventory.displayAllColumns = function() { 28775 _listProduct(); 28776 $('#doc3').css({ "width": "" }); 28777 $('body').addClass('display-all-columns'); 28778 28779 var j = $('#manage-inventory').addClass('display-all-columns'); 28780 var jtbl = j.find('#inventory-table').addClass('detail-view'); 28781 //jtbl.find('.item-product-line, .item-type-category').addClass('hide'); 28782 jtbl.find('.item-staff-price, .item-upc, .item-sku, .item-product-line, .item-type-category, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission').removeClass('hide'); 28783 jtbl.find('.item-row-box').addClass('hide'); 28784 jtbl.find('#displayAllLink').addClass('hide'); 28785 jtbl.find('#displaySummaryView').removeClass('hide'); 28786 } 28787 28788 _conInventory.filterIsEmpty = function() { 28789 var jhead = $('#inventory-header-filter'); 28790 28791 var co = jhead.find('#Filter_Company').val(); 28792 var distributorId = jhead.find('#Filter_Category').val(); 28793 var typeId = jhead.find('#Filter_Stock_Level').val(); 28794 28795 if ( (co === '' || co === 'hide') && distributorId === '' && (typeId === '' || typeId === 'hide')) { 28796 return true; 28797 } else { 28798 return false; 28799 } 28800 } 28801 28802 _conInventory.backViaUri = function() { 28803 var back = GLO.Uri.hash('back').toLowerCase(); 28804 28805 if (!UTIL.isEmpty(back)) { 28806 if (back === 'order-report') { 28807 document.location = document.location.protocol + '//' + document.location.host + '/reports/inventory/#tab=order-and-restock'; 28808 } else { 28809 GLO.Inventory.updateHash(back); 28810 } 28811 28812 return true; 28813 } 28814 28815 return false; 28816 } 28817 28818 _conInventory.getShipmentId = function() { 28819 var shipmentId = GLO.Uri.url('id'); 28820 28821 if (!UTIL.isNumber(shipmentId)) { 28822 shipmentId = $('#shipment-detail-header').attr('shipment_id'); 28823 } 28824 28825 if (!UTIL.isNumber(shipmentId)) { 28826 shipmentId = $('#order-detail-header').attr('shipment_id'); 28827 } 28828 28829 if (!UTIL.isNumber(shipmentId)) { 28830 shipmentId = $('#inventory-restock-buttons #Shipment_id').val(); 28831 } 28832 28833 return shipmentId; 28834 } 28835 28836 _conInventory.gotoGiftCardList = function(isVoucher) { 28837 var categoryId = 'c' + GLO.Inventory.Type.getGiftCardCategory(); 28838 //GLO.Inventory.updateHash('product-list', categoryId); //GLO.Uri.gotoUriWithSpinner('/provider/inventory#action=product-list&filterid=c52535', this, event, true) 28839 //document.location.hash = 'action=product-list&filterid=' + categoryId; 28840 _conInventory.closeCreateEditMenu(false, true); 28841 28842 $('#inventory-header-filter #Filter_Category').val(categoryId).change(); 28843 } 28844 28845 return _conInventory; 28846})(); 28847 28848 28849GLO.Inventory.Restock = (function() { 28850 function _conIRestock() { } 28851 28852 _conIRestock.openList = function() { 28853 $('#bd-page > .shadow-content0').css({ "background-color": "#FFE4E1" }); 28854 } 28855 28856 _conIRestock.back = function() { 28857 if (!GLO.Inventory.backViaUri()) { 28858 GLO.Inventory.updateHash('product-list'); 28859 } 28860 } 28861 28862 function _listRestockandAuditButtons(orderType, note) { 28863 var jHead = $('#inventory-restock-buttons').removeClass('hide'); 28864 jHead.find('#inventory-restock-edit-buttons').removeClass('hide'); 28865 jHead.find('#Order_id').val(''); 28866 28867 note = UTIL.coalesce(note, $('#shipment-detail-header').find('#edit-shipment-note').text()) 28868 jHead.find('#Shipment_Note_vc').val(note); 28869 jHead.find('.btnDelete').addClass('hide'); 28870 28871 $('#order-editable-fields').addClass('hide'); 28872 } 28873 28874 function _listOrderButtions(orderType, id, note) { 28875 var jHead = $('#inventory-order-header').removeClass('hide'); 28876 jHead.find('#Order_id').val( UTIL.cleanString(id) ); 28877 28878 var jOrderBtns = $('#inventory-order-buttons'); 28879 var jStockBtns = $('#inventory-restock-buttons').removeClass('hide'); 28880 28881 jStockBtns.find('#inventory-restock-edit-buttons').addClass('hide'); 28882 $('#order-editable-fields').removeClass('hide'); 28883 28884 if (!UTIL.isEmpty(id)) { 28885 $('#inventory-automatic-ordering').addClass('hide').find('#last_order_date').text(''); 28886 28887 /* 28888 if (orderType === 4) { 28889 jOrderBtns.find('.btnDelete').addClass('hide'); //jHead.find('#inventory-order-dates-buttons .btnDelete').removeClass('hide'); 28890 } else { 28891 jOrderBtns.find('.btnDelete').removeClass('hide'); //jHead.find('#inventory-order-dates-buttons .btnDelete').removeClass('hide'); 28892 } 28893 28894 jOrderBtns.find('#inventory-order-dates-buttons').css({ "width": "90%" }); 28895 */ 28896 28897 jOrderBtns.find('#inventory-order-dates').removeClass('hide'); 28898 jOrderBtns.find('.btnDelete').removeClass('hide'); 28899 28900 var jtbl = $('#order-detail-header'); 28901 jStockBtns.find('#Shipment_Note_vc').val( UTIL.coalesce(note, jtbl.find('#edit-order-note').text(), '') ); 28902 } else { 28903 $('#inventory-automatic-ordering').removeClass('hide'); 28904 28905 jOrderBtns.find('#inventory-order-dates').addClass('hide'); 28906 28907 //jOrderBtns.find('#inventory-order-dates-buttons').css({ "width": "75%" }); 28908 jOrderBtns.find('.btnDelete').addClass('hide'); 28909 28910 jStockBtns.find('#Shipment_Note_vc').val(UTIL.cleanString(note)); 28911 } 28912 } 28913 28914 function _listSetCSSandLabels(orderType, jProductList, id) { 28915 var backColor, w, itemCountLabel = SA.Resource.Count, h2Text; 28916 28917 if (orderType == 200) { 28918 backColor = 'PaleGreen'; //#98FB98 28919 w = GLO.Inventory.docWidth + 'px'; 28920 28921 itemCountLabel = SA.Resource.Expected; 28922 h2Text = SA.Resource.InventoryCheck; 28923 28924 jProductList.find('th.item-in-stock-parent').css({ "border-top-right-radius": "" }); 28925 } else if (orderType > 0 && orderType < 200) { 28926 backColor = ''; 28927 w = GLO.Inventory.docWidth + 'px'; 28928 28929 if (orderType === 1) { 28930 h2Text = SA.Resource.ReStock; 28931 } else { 28932 if (!UTIL.isEmpty(id)) { 28933 h2Text = '<b>' + SA.Resource.Edit + '</b> ' + SA.Resource.Order; 28934 28935 if (!UTIL.isEmpty(GLO.Inventory.shipment.shipment_number_vc)) { h2Text += ' #' + GLO.Inventory.shipment.shipment_number_vc; } 28936 } else { 28937 h2Text = SA.Resource.OrderForm; 28938 } 28939 28940 if (orderType === 4) { itemCountLabel = SA.Resource.Received; } 28941 } 28942 28943 jProductList.find('th.item-in-stock-parent').css({ "border-top-right-radius": "15px" }); 28944 } else { 28945 backColor = '#FFE4E1'; //#FFE1FF, #FFFACD 28946 w = (GLO.Inventory.docWidth + 50) + 'px'; 28947 28948 h2Text = SA.Resource.ProductList; 28949 } 28950 28951 $('#bd-page > .shadow-content0').css({ "background-color": backColor }); 28952 //$('#doc3').css({ "width": w }); 28953 28954 $('h2.inventory-header #inventory-header-text').html(h2Text); 28955 jProductList.find('#item-in-stock-th-text').text(itemCountLabel); 28956 } 28957 28958 function _hasFilter(id) { 28959 if (UTIL.isEmpty(id)) { 28960 var jhead = $('#inventory-header-action-container'); 28961 var company = jhead.find('#Filter_Company').val(); 28962 var category = jhead.find('#Filter_Category').val(); 28963 var stockLevel = jhead.find('#Filter_Stock_Level').val(); 28964 28965 if (UTIL.isEmpty(company) && UTIL.isEmpty(category) && UTIL.isEmpty(stockLevel)) { 28966 jhead.find('#Filter_Company').prepend('<option value="hide"></option>').val('hide'); 28967 return false; 28968 } 28969 } 28970 28971 return true; 28972 } 28973 28974 function _listPopulate(orderType, tbody, id) { 28975 var arr = GLO.Inventory.shipment; 28976 28977 if (!UTIL.isEmpty(id) && arr !== undefined) { 28978 var jEditInput, inventoryIds = ''; 28979 28980 for (var i=0; i < arr.length; i++) { inventoryIds += arr[i]["inventory_id"] + ','; } 28981 28982 if (arr.length > 0) { inventoryIds = inventoryIds.substring(0, inventoryIds.length - 1); } 28983 if (!UTIL.isEmpty(inventoryIds)) { inventoryIds = inventoryIds.split(','); } 28984 28985 tbody.each(function() { 28986 var me = $(this); 28987 var ocount, cnt, totalCnt, cost, rowId = me.attr('id'); 28988 28989 if (inventoryIds.length === 0) { 28990 me.addClass('hide'); 28991 } else if (!inventoryIds.has(rowId)) { 28992 me.addClass('hide'); 28993 } else { 28994 for (var j=0; j < arr.length; j++) { 28995 if (arr[j]["inventory_id"] == rowId) { break; } 28996 } 28997 28998 for (var s=0; s < inventoryIds.length; s++) { 28999 if (inventoryIds[s] == rowId) { 29000 inventoryIds.remove(s); 29001 break; 29002 } 29003 } 29004 29005 if (orderType === 200) { 29006 me.find('.item-audit input').val(arr[j]["actual_dr"]); 29007 } else { 29008 cnt = arr[j]["count_dr"]; 29009 totalCnt = me.find('.item-in-stock').text(); 29010 29011 cost = arr[j]["cost_mn"]; 29012 if (UTIL.isNumber(cost, true)) { cost = UTIL.roundMoney(cost); } 29013 29014 if (orderType === 4) { 29015 totalCnt = UTIL.roundMoney(totalCnt) - UTIL.roundMoney(cnt); 29016 me.find('.current-in-stock').text(totalCnt); 29017 29018 ocount = arr[j]["order_count_nr"]; 29019 jEditInput = me.find('.item-in-stock-edit input').val(cnt); 29020 } else { 29021 me.find('.current-in-stock').text(totalCnt); 29022 ocount = ''; 29023 29024 if (orderType === 2) { 29025 jEditInput = me.find('.item-in-stock-edit input').val( arr[j]["order_count_nr"] ); 29026 } else { 29027 jEditInput = me.find('.item-in-stock-edit input').val(cnt); 29028 } 29029 } 29030 29031 me.find('.item-cost-edit input').val(cost); 29032 me.find('.item-order-count input').val(ocount); 29033 jEditInput.change(); 29034 } 29035 29036 me.removeClass('hide'); 29037 } 29038 }); 29039 29040 _displayDeletedProducts(inventoryIds); 29041 29042 var jOrderHeader = $('#order-detail-header'); 29043 var vid = jOrderHeader.attr('vendor_id'); 29044 var did = jOrderHeader.attr('distributor_id'); 29045 29046 if (!UTIL.isEmpty(vid)) { 29047 $('#Filter_Company').val('v' + vid); 29048 GLO.Inventory.filterOnChange(); 29049 } else if (!UTIL.isEmpty(did)) { 29050 $('#Filter_Company').val('d' + did); 29051 GLO.Inventory.filterOnChange(); 29052 } 29053 29054 $('#inventory-table').before( jOrderHeader.removeClass('hide') ); 29055 29056 if (orderType !== 200) { 29057 $('#inventory-header-filter').addClass('hide'); 29058 $('#inventory-header-action-container').find('#Order_Received_dt').change(); 29059 } 29060 } else { 29061 $('#inventory-header-filter, #inventory-order-dates-buttons, #inventory-order-disclaimer').removeClass('hide'); 29062 29063 tbody.find('tr').each(function() { 29064 var me = $(this); 29065 me.find('.item-order-count input').val(''); 29066 29067 if (orderType !== 200) { 29068 me.find('.current-in-stock').text(me.find('.item-in-stock').text()); 29069 } 29070 }); 29071 } 29072 } 29073 29074 _conIRestock.openEdit = function(id, orderType, note) { 29075 var jProductList = $('#manage-inventory'); 29076 var tbody = jProductList.find('#inventory-table tbody tr'); 29077 var selectedRows = tbody.find('.item-row-box input:checked'); 29078 29079 GLO.Inventory.displayColumns(orderType, jProductList, id); 29080 _listSetCSSandLabels(orderType, jProductList, id); 29081 29082 if (selectedRows.length === 0) { var hasFilter = _hasFilter(id); } else { var hasFilter = false; } 29083 29084 if (selectedRows.length > 0 || !hasFilter) { 29085 tbody.find('.item-row-box input:not(:checked)').closest('tr').addClass('hide'); 29086 } 29087 29088 if (orderType === 2 || orderType === 4) { 29089 jProductList.addClass('order-body'); 29090 29091 _listOrderButtions(orderType, id, note); 29092 } else { 29093 // jProductList.removeClass('order-body'); 29094 if (orderType === 200) { jProductList.addClass('audit-body'); } 29095 29096 _listRestockandAuditButtons(orderType, note) 29097 29098 if (orderType !== 200 && !UTIL.isEmpty(id) && GLO.Inventory.shipment === undefined) { 29099 _conIRestock.back(); 29100 return; 29101 } 29102 } 29103 29104 _listPopulate(orderType, tbody, id); 29105 jProductList.removeClass('hide'); 29106 GLO.Inventory.setFooter(orderType); 29107 29108 $('#inventory-header-help-icon').removeClass('hide'); 29109 $('.btnSave:visible a').css({ "border": "3px solid transparent" }); 29110 29111 if (!hasFilter) { $('#Filter_Company').focus(); } 29112 29113 if (!UTIL.isEmpty(id) && GLO.Uri.hash('and').toLowerCase() === 'email') { 29114 GLO.Inventory.Order.email(true); 29115 } else { 29116 var helpLabel = SA.Help.Inventory.getHelpLabel(orderType, id); 29117 SA.Help.display(helpLabel); 29118 } 29119 } 29120 29121 function _displayDeletedProducts(inventoryIds) { 29122 if (inventoryIds && inventoryIds.length) { 29123 var arr = GLO.Inventory.shipment; 29124 var deleteCount = 0; 29125 var delHtml = '<fieldset> <legend style="color: Red;">' + SA.Resource.DeletedProducts + '</legend> <table style="width: 100%;">' 29126 + '<tr> <th class="del-col-n
29126ame">' + SA.Resource.ProductName + '</th> <th class="del-col-size">Size</th> <th class="del-col-brand">' + SA.Resource.Brand + '</th> <th class="del-col-category">' + SA.Resource.Category + '</th> <th class="del-col-cost">' + SA.Resource.Cost + '</th> <th class="del-col-ordered">' + SA.Resource.Ordered + '</th> <th class="del-col-received">' + SA.Resource.Received + '</th> </tr>'; 29127 29128 for (var s=0; s < arr.length; s++) { 29129 if (!UTIL.isEmpty(arr[s].name_vc)) { 29130 delHtml += '<tr> <td class="del-col-name">' + arr[s].name_vc + '</td>' 29131 + '<td class="del-col-size">' + arr[s].size_dr + ' ' + arr[s].unit_abbreviation + '</td>' 29132 + '<td class="del-col-brand">' + arr[s].vendor_name_vc + '</td>' 29133 + '<td class="del-col-category">' + arr[s].type_category_name_vc + '<br/>' + arr[s].type_name_vc + '</td>' 29134 + '<td class="del-col-cost">$' + UTIL.roundMoney(arr[s].cost_mn) + '</td>' 29135 + '<td class="del-col-ordered">' + arr[s].order_count_nr + '</td>' 29136 + '<td class="del-col-received">' + UTIL.roundMoney(arr[s].count_dr) + '</td>' 29137 + '</tr>'; 29138 ++deleteCount; 29139 } 29140 } 29141 29142 if (deleteCount == 0) { 29143 return; 29144 } else if (deleteCount == 1) { 29145 var lbl = SA.Resource.OrderItemDeleted + ':'; 29146 } else { 29147 var lbl = SA.Resource.OrderIncludes + ' ' + deleteCount + ' ' + SA.Resource.ItemsDeletedHelp + ':'; 29148 } 29149 29150 delHtml = '<div id="deleted-items-table"><div style="margin-left: -32px; margin-right: 28px; margin-bottom: 20px;">' + lbl + '</div>' + delHtml + '</table> </fieldset> </div>'; 29151 29152 var ojpop = new GLO.Popup.Warning(delHtml); 29153 29154 if (GLO.Info.isMobile()) { 29155 var jpop = ojpop.getPopup().css({ "width": "98%", "max-width": "100%" }); 29156 jpop.find('.msg').css({ "padding-right": "2px" }); 29157 ojpop.realign(); 29158 } 29159 } 29160 29161 GLO.Inventory.shipment = undefined; 29162 } 29163 29164 _conIRestock.newProduct = function() { 29165 var url = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=new-product'; 29166 var childWindow = UI.openChildWindow(url, '', true); 29167 } 29168 29169 _conIRestock.hideRow = function(me) { 29170 GLO.Inventory.hideRow( $(me).closest('tr') ); 29171 $('#inventory-restock-edit-buttons:visible').find('.btnSave a:visible').css({ "border": "3px solid Red" }); 29172 GLO.Inventory.setFooter(1); 29173 } 29174 29175 /* 29176 _conIRestock.reload = function() { 29177 $('#inventory-table tbody tr').each(function() { 29178 $(this).removeClass('hide'); 29179 }); 29180 } 29181 29182 _conIRestock.addProduct = function() { // => pops up simple modal w/ inventory auto-complete box (containing all hiden products). 29183 29184 } 29185 */ 29186 29187 _conIRestock.editCost = function(element, event) { 29188 GLO.Inventory.setFooter(1); 29189 } 29190 29191 _conIRestock.editCount = function(element, event) { 29192 var me = $(element); 29193 var nr = parseFloat(me.val()); 29194 var jtd = me.closest('td'); 29195 var jtr = jtd.closest('tr'); 29196 var jocnt = jtr.find('.item-order-count input'); 29197 var ocnt = UTIL.coalesceInt(jocnt.val()); 29198 29199 if (jocnt.is(":visible") || !isNaN(ocnt)) { 29200 if (ocnt > nr) { 29201 jtr.addClass('unfilled'); 29202 } else { 29203 jtr.removeClass('unfilled'); 29204 } 29205 } 29206 29207 if (nr < 0) { 29208 jtd.find('.inventory-in-stock-plus').text('-'); 29209 } else { 29210 jtd.find('.inventory-in-stock-plus').text('+'); 29211 } 29212 29213 nr = UTIL.coalesceFloat(jtd.find('.current-in-stock').text(), 0) + UTIL.coalesceFloat(nr, 0); 29214 nr = UTIL.roundMoney(nr); 29215 var orderType = GLO.Inventory.getOrderType(); 29216 29217 if (orderType === 2) { nr = '[ ' + nr + ' ]'; } 29218 jtd.find('.new-in-stock-total').text(nr); 29219 29220 GLO.Inventory.setFooter(orderType); 29221 } 29222 29223 /* 29224 _conIRestock.addNote = function() { 29225 var jnote = $('#shipment-detail-header:visible').find('#edit-shipment-note'); 29226 29227 if (jnote.length === 1) { 29228 var note = jnote.text(); 29229 } else {
29230 var note = $('#inventory-header-action-container').find('#Shipment_Note_vc').text(); 29231 } 29232 29233 GLO.Popup.Prompt('Shipment Note', GLO.Inventory.Restock.saveNote, null, note); 29234 } 29235 29236 _conIRestock.saveNote = function(note) { 29237 var jnote = $('#shipment-detail-header:visible').find('#edit-shipment-note'); 29238 29239 if (jnote.length === 1) { 29240 jnote.text(note); 29241 } 29242 29243 $('#inventory-header-action-container').find('#Shipment_Note_vc').text(note); 29244 return true; 29245 } 29246 */ 29247 29248 _conIRestock.getShipmentId = function() { 29249 //var shipmentId = $('#inventory-header-action-container').find('#Shipment_id').val(); 29250 //if (UTIL.isEmpty(shipmentId)) { shipmentId = GLO.Uri.url('id'); } 29251 29252 return GLO.Uri.url('id'); 29253 } 29254 29255 _conIRestock.remove = function(deleteButton) { 29256 var shipmentId = _conIRestock.getShipmentId(); 29257 var msg = SA.Resource.DeleteShipmentConfirm; 29258 29259 GLO.Popup.Confirm(msg, function() { 29260 GLO.Inventory.Restock.removeConfirmed(deleteButton, shipmentId); 29261 }); 29262 } 29263 29264 _conIRestock.removeConfirmed = function(deleteButton, shipmentId) { 29265 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ShipmentDelete'; 29266 GLO.UI.Form.beginProcessing( $(deleteButton).parent() ); 29267 29268 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } }) 29269 .success(function(data, textStatus, jqXHR) { 29270 if (UTIL.Validate.hasPermissionError(data)) { return; } 29271 29272 GLO.Inventory.Restock.back(); 29273 }) 29274 .error(function(jqXHR, textStatus, errorThrown) { 29275 new GLO.Popup.Error('Unable to delete the order at this time. Please try again later.'); 29276 GLO.UI.Form.resetProcessing(); 29277 }); 29278 } 29279 29280 _conIRestock.save = function(isPrinting, isOrder, isDelete, isEmail) { 29281 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Restock'; 29282 var jrows = $('#inventory-table tbody tr:visible'); 29283 var ocount, updStock, updCount = 0, restockXml = '', totalCount, useCount = false; 29284 29285 var otype = GLO.Inventory.getOrderType(); 29286 29287 if (otype < 3 && jrows.eq(0).find('.item-order-count:visible').length == 0) { 29288 useCount = true; 29289 } else if (otype === 200) { 29290 GLO.Inventory.Audit.save(jrows); 29291 return; 29292 } 29293 29294 for (var i=0; i < jrows.length; i++) { 29295 updStock = coalesceStringNumber(jrows.eq(i).find('.item-in-stock-edit input').val()); 29296 29297 if (useCount) { 29298 ocount = updStock; 29299 } else { 29300 ocount = coalesceStringNumber(jrows.eq(i).find('.item-order-count input').val()); 29301 } 29302 29303 if (updStock != 0 || ocount != 0) { 29304 totalCount = coalesceStringNumber(jrows.eq(i).find('.new-in-stock-total').text()).replace('(', '').replace(')', ''); 29305 29306 restockXml += '<tr inventory_id="' + jrows.eq(i).attr('id') + '" track_stock_fl="' + jrows.eq(i).attr('track_stock_fl') 29307 + '" cost_mn="' + coalesceStringNumber(jrows.eq(i).find('.item-cost-edit input').val()) 29308 + '" order_count_nr="' + ocount + '" count_dr="' + updStock + '" total_dr="' + totalCount + '"/>'; 29309 ++updCount; 29310 } 29311 } 29312 29313 if (jrows.length === 0) { 29314 GLO.Popup.Warning(SA.Resource.EmptyOrderWarning); 29315 return; 29316 } else if (restockXml === '') { 29317 GLO.Popup.Warning(SA.Resource.EmptyOrderWarning2); 29318 return; 29319 } 29320 29321 var restockEncodedXml = UTIL.htmlEncode(restockXml); 29322 var jHead = $('#inventory-header-action-container'); 29323 var shipmentId = _conIRestock.getShipmentId(); 29324 var shipmentName = jHead.find('#Shipment_Name_vc').val(); 29325 var note = UTIL.htmlEncode(jHead.find('#Shipment_Note_vc:visible').val()); //, #Order_Note_vc:visible 29326 29327 var jlocation = jHead.find('#order-editable-fields'); 29328 var locationId = jlocation.find('#Location_id').val(), isle = jlocation.find('#Isle_vc').val(), shelf = jlocation.find('#Shelf_vc').val(), rack = jlocation.find('#Rack_vc').val(); 29329 29330 var vid = '', did = '', co = jHead.find('#Filter_Company').val(); 29331 29332 if (!UTIL.isEmpty(co)) { 29333 if (co.substring(0, 1) === 'v') { 29334 vid = co.substring(1); 29335 } else if (co.substring(0, 1) === 'd') { 29336 did = co.substring(1); 29337 } else if (co.substring(0, 1) === 'p') { 29338 vid = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id'); 29339 } 29340 } 29341 29342 var saveBtn = jHead.find('.btnSave:visible');
29343 GLO.UI.Form.beginProcessing( saveBtn ); 29344 29345 var jsdata = { 29346 "Shipment_id": shipmentId, "Shipment_Name_vc": shipmentName, "Note_vc": note, "Vendor_id": vid, "Distributor_id": did 29347 , "Location_id": locationId, "Isle_vc": isle, "Shelf_vc": shelf, "Rack_vc": rack 29348 , "Restock_xml": restockEncodedXml 29349 }; 29350 29351 var orderType = 1; 29352 var jAutoOrdering = jHead.find('#inventory-automatic-ordering:visible'); 29353 var jOrderDates = jHead.find('#inventory-order-dates:visible'); 29354 29355 if (jAutoOrdering.length === 1) { 29356 orderType = 10; 29357 29358 if (jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked')) { 29359 orderType = 11; 29360 } 29361 29362 if (jAutoOrdering.find('#auto_ordering_dates_fl').prop('checked')) { 29363 if (orderType === 11) { 29364 orderType = 21; 29365 } else { 29366 orderType = 12; 29367 } 29368 29369 jsdata["Order_Auto_Start_dt"] = jAutoOrdering.find('#auto_start_dt').val(); 29370 jsdata["Order_Auto_End_dt"] = jAutoOrdering.find('#auto_end_dt').val(); 29371 } 29372 29373 if (jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked')) { 29374 if (orderType === 11) { 29375 orderType = 23; 29376 } else if (orderType === 21) { 29377 orderType = 22; 29378 } else if (orderType === 12) { 29379 orderType = 24; 29380 } else { 29381 orderType = 13; 29382 } 29383 29384 jsdata["Order_Min_Stock_pct"] = jAutoOrdering.find('#minimum_pct').val(); 29385 } 29386 } else if (jOrderDates.length === 1) { 29387 jsdata["Order_dt"] = jHead.find('#Order_dt').val(); 29388 jsdata["Order_Received_dt"] = jHead.find('#Order_Received_dt').val(); 29389 //jsdata["Stock_dt"] = jHead.find('#Stock_dt').val(); 29390 29391 if (UTIL.isDate(jsdata["Order_Received_dt"])) { 29392 orderType = 4; 29393 } else { 29394 orderType = 2; 29395 } 29396 } 29397 29398 jsdata["Order_Type_cd"] = orderType; 29399 29400 if (isPrinting) { 29401 jsdata["Order_Printed_fl"] = "1"; 29402 } 29403 29404 if (isDelete) { jsdata["Is_Delete_fl"] = "1"; } 29405 29406 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata }) 29407 .success(function(data, textStatus, jqXHR) { 29408 if (UTIL.Validate.hasPermissionError(data)) { return; } 29409 29410 var tbody = $(data); 29411 29412 if (isDelete) { 29413 GLO.Inventory.Order.back(); 29414 } else if (UTIL.isEmpty(shipmentId) && UTIL.coalesceInt(otype, 0) < 3) { 29415 var shipmentId = $(data).attr('shipment_id'); 29416 29417 if (!UTIL.isEmpty(shipmentId)) { 29418 GLO.Inventory.updateHash('order', shipmentId, 'order-list'); 29419 } 29420 } 29421 29422 /* 29423 if (orderType < 5) { 29424 location.reload(); //toDo (low priority): later --> don't do a refresh; instead just update the rows. 29425 return; 29426 } 29427 */
29428 var tr, tbl = $('#inventory-table tbody'); 29429 var trs = tbody.find('tr'); //var trs = $('<table>' + restockXml + '</table>').find('tr'); 29430 29431 for (var j=0; j < trs.length; j++) { 29432 tr = tbl.find('tr#' + trs.eq(j).attr('inventory_id')); 29433 _conIRestock.updateLineItem(tr, trs.eq(j).attr('in_stock_dr'), trs.eq(j).attr('cost_mn')); 29434 29435 trs.eq(j).html('<td>' + tr.find('.item-name').text() + '</td>'); 29436 } 29437 29438 if (orderType !== 1 && orderType !== 4) { //= if unreceived order need to reset row's total count. 29439 var resetRows = tbl.find('tr:visible .item-in-stock-edit input'); 29440 29441 for (var r=0; r < resetRows.length; r++) { 29442 resetRows.eq(r).change(); 29443 } 29444 } 29445 29446 _orderUpdateSuccessMessage(orderType, trs, updCount); 29447 saveBtn.find('a').css({ "border": "3px solid transparent" }); 29448 29449 if (UTIL.isEmpty(shipmentId)) { 29450 shipmentId = tbody.attr('shipment_id'); //var currid = jHead.find('#Shipment_id').val(); //jHead.find('#Shipment_id').val(shipmentId); 29451 29452 if (isOrder) { 29453 if ($('#inventory-automatic-ordering:visible').length === 1) { 29454 $('#inventory-automatic-ordering:visible').addClass('hide'); 29455 $('#inventory-order-dates').removeClass('hide'); 29456 } 29457 } 29458 29459 if (isEmail) { 29460 GLO.Inventory.updateHash('order', shipmentId, '', 'email'); //GLO.Inventory.updateHash('restock', shipmentId); 29461 } 29462 } else if (isEmail) { 29463 GLO.Inventory.Order.email(true); 29464 } 29465 }) 29466 .error(function(jqXHR, textStatus, errorThrown) { 29467 if (isDelete) { 29468 new GLO.Popup.Error('Unable to delete the order. Please try again later.'); 29469 } else { 29470 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 29471 } 29472 29473 GLO.UI.Form.resetProcessing(); 29474 }); 29475 } 29476 29477 function _orderUpdateSuccessMessage(orderType, trs, updCount) { 29478 if (orderType === 0 || orderType === 2 || orderType > 9) { 29479 new GLO.Popup.Success(updCount + ' ' + SA.Resource.ProductsUpdated.toLowerCase()); 29480 } else { 29481 var h1 = '<h1 style="margin-bottom: 0; letter-spacing: 1px;">' + SA.Resource.StockUpdatedSuccessfully + '</h1>'; 29482 var msg = '<div style="margin-bottom: 20px; line-height: 200%; font-size: 150%; letter-spacing: 1px;">' + SA.Resource.NewStockTotals + '</div>'; 29483 var htm = '<table style="width: 100%;"> <thead> <tr> <th>' + SA.Resource.Product + '</th> <th>' + SA.Resource.InStock + '</th> <th>' + SA.Resource.Cost + '</th> </tr> </thead> <tbody>'; 29484 29485 for (var i=0; i < trs.length; i++) { 29486 htm += '<tr> <td>' + trs.eq(i).text() + '</td> <td>' + trs.eq(i).attr('in_stock_dr') + '</td> <td style="white-space: nowrap;">$ ' + trs.eq(i).attr('cost_mn') + '</td> </tr>'; 29487 } 29488 29489 var css = { "padding-left": "0" }; 29490 29491 if (!GLO.Info.isMobile()) { 29492 css["max-height"] = (window.innerHeight - 200); 29493 css.overflow = "auto"; 29494 } 29495 29496 htm = '<div id="pop-info-new-stock-totals">' + h1 + msg + htm + '</tbody> </table> </div>'; 29497 var ojpop = new GLO.Popup.Info(htm); 29498 var jpop = ojpop.getPopup(); 29499 jpop.find('.pop-icon').remove(); //jpop.css({ "background-image": "none" }); 29500 jpop.find('.msg').css(css); 29501 ojpop.realign(); 29502 } 29503 } 29504 29505 _conIRestock.updateLineItem = function(tr, stock, cost) { 29506 if (!UTIL.isEmpty(cost)) { cost = '$' + cost; } 29507 29508 tr.find('.item-cost').text(cost).attr('title', ''); 29509 tr.find('.item-cost-edit').attr('title', ''); 29510 29511 //tr.find('.current-in-stock').text(stockNew); 29512 tr.find('.new-in-stock-total').text(stock); 29513 tr.find('.item-in-stock').text(stock); 29514 } 29515 29516 _conIRestock.DEL_updateLineItem = function(tr) { 29517 var costNew = UTIL.coalesceFloat(tr.find('.item-cost-edit input').val(), 0); 29518 var stockNew = UTIL.coalesceFloat(tr.find('.item-in-stock-edit input').val(), 0); 29519 29520 var costCurr = UTIL.coalesceFloat(tr.find('.item-cost').text().replace('$', ''), 0); 29521 var stockCurr = UTIL.coalesceFloat(tr.find('.item-in-stock').text(), 0); 29522 29523 costNew = (costCurr * stockCurr + costNew * stockNew) / (stockCurr + stockNew); 29524 29525 if (isNaN(costNew) || costNew == 0) { 29526 costNew = ''; 29527 } else { 29528 costNew = '$' + UTIL.roundMoney(costNew); 29529 } 29530 29531 stockNew = UTIL.roundMoney(stockCurr + stockNew); 29532 29533 tr.find('.item-cost').text(costNew).attr('title', ''); 29534 tr.find('.item-cost-edit').attr('title', ''); 29535 29536 //tr.find('.current-in-stock').text(stockNew); 29537 tr.find('.new-in-stock-total').text(stockNew); 29538 tr.find('.item-in-stock').text(stockNew); 29539 } 29540 29541 function coalesceStringNumber(val) { 29542 if (UTIL.isNumber(val)) { 29543 return val; 29544 } else { 29545 return '0'; 29546 } 29547 } 29548 29549 return _conIRestock; 29550})(); 29551 29552GLO.Inventory.Audit = (function() {
29553 function _conIAudit() { } 29554 29555 _conIAudit.rowEdit = function(thisElement, event) { 29556 GLO.Inventory.setFooter(200); 29557 } 29558 29559 function _displayAllRows() { 29560 var MAX_ROWS = 100 //= if less than 100 products -> display all products by default. 29561 var pcount = $('#inventory-table').find('tbody > tr').length; 29562 29563 if (pcount < MAX_ROWS) { 29564 var jco = $('#inventory-header-filter #Filter_Company'); 29565 jco.val('').change(); 29566 } 29567 } 29568 29569 _conIAudit.openEdit = function(id) { 29570 if (UTIL.isEmpty(id) || (GLO.Inventory.shipment && GLO.Inventory.shipment.length && GLO.Inventory.shipment.id == id) ) { 29571 GLO.Inventory.Restock.openEdit(id, 200); 29572 _displayAllRows(); 29573 29574 return; 29575 } 29576 29577 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Order?id=' + id + '&isAudit=1'; 29578 29579 $('#inventory-header-help-icon').removeClass('hide'); 29580 $('#inventory-search-results').addClass('processing'); //GLO.UI.Form.beginProcessing(frm.find('.btnSave')); 29581 $('.inventory-header').after('<div id="inventory-temporary-throbber" style="width: 100px; margin: auto;">' + $('.loadingDiv').clone().find('img').css({"margin": "50px auto"}).outerHTML() + '</div>') 29582 29583 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 29584 .success(function(data, textStatus, jqXHR) { 29585 $('#inventory-search-results').addClass('hide').removeClass('processing'); //GLO.UI.Form.resetProcessing(); 29586 $('#inventory-temporary-throbber').remove(); 29587 $('#inventory-table').removeClass('hide'); 29588 29589 var ul = $(data); 29590 var li = ul.find('li'); 29591 var dt, cnt, obj, arr = []; 29592 29593 for (var i=0; i < li.length; i++) { 29594 obj = { "inventory_id": li.eq(i).attr('inventory_id'), "actual_dr": li.eq(i).attr('actual_dr') }; 29595 29596 if (li.eq(i).attr('name_vc')) { 29597 obj.name_vc = li.eq(i).attr('name_vc'); 29598 obj.vendor_name_vc = li.eq(i).attr('vendor_name_vc'); 29599 obj.size_dr = li.eq(i).attr('size_dr'); 29600 obj.unit_abbreviation = li.eq(i).attr('unit_abbreviation'); 29601 obj.type_name_vc = li.eq(i).attr('type_name_vc') 29602 obj.type_category_name_vc = li.eq(i).attr('type_category_name_vc'); 29603 } 29604 29605 arr.push(obj); 29606 } 29607 29608 GLO.Inventory.shipment = arr; 29609 29610 var note = ul.text(); 29611 GLO.Inventory.Restock.openEdit(id, 200, note); 29612 }) 29613 .error(function(jqXHR, textStatus, errorThrown) { 29614 //new GLO.Popup.Error('Unable to open at this time. Please try again later.'); 29615 $('#inventory-search-results').removeClass('processing'); //GLO.UI.Form.resetProcessing(); 29616 }); 29617 } 29618 29619 _conIAudit.save = function(jrows) { 29620 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Audit'; 29621 var updCount = 0, xml = '', row, expected, actual, diff; 29622 29623 for (var i=0; i < jrows.length; i++) { 29624 row = jrows.eq(i); 29625 actual = row.find('.item-audit input').val(); 29626 29627 if (UTIL.isNumber(actual)) { 29628 expected = row.find('.item-in-stock').text(); 29629 diff = row.find('.item-audit-diff').text().replace('+', ''); 29630 29631 if (UTIL.isEmpty(expected)) { expected = '0'; } 29632 if (UTIL.isEmpty(diff)) { diff = '0'; } 29633 29634 xml += '<tr inventory_id="' + row.attr('id') + '" expected_dr="' + expected + '" actual_dr="' + actual + '" diff_dr="' + diff + '"/>'; 29635 ++updCount; 29636 } 29637 } 29638 29639 if (jrows.length === 0) { 29640 GLO.Popup.Warning(SA.Resource.InventoryAuditEmptyWarning); 29641 return; 29642 } else if (xml === '') { 29643 GLO.Popup.Warning(SA.Resource.InventoryAuditEmptyWarning2); 29644 return; 29645 } 29646 29647 var jHead = $('#inventory-header-action-container'); 29648 var note = jHead.find('#Shipment_Note_vc:visible').val(); 29649 var jsdata = GLO.Inventory.Vendor.getSelected(jHead); 29650 29651 var shipmentId = GLO.Uri.hash('id'); 29652 if (!UTIL.isEmpty(shipmentId)) { jsdata["Shipment_id"] = shipmentId; } 29653 29654 jsdata["Note_vc"] = UTIL.htmlEncode(note); 29655 jsdata["Restock_xml"] = UTIL.htmlEncode(xml); 29656 29657 var saveBtn = jHead.find('.btnSave:visible');
29658 GLO.UI.Form.beginProcessing( saveBtn ); 29659 29660 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata }) 29661 .success(function(data, textStatus, jqXHR) { 29662 if (UTIL.Validate.hasPermissionError(data)) { return; } 29663 29664 new GLO.Popup.Success(updCount + ' ' + SA.Resource.ProductsUpdated.toLowerCase()); 29665 29666 //GLO.Inventory.updateHash('audit', $(data).attr('shipment_id')); 29667 document.location = document.location.protocol + '//' + document.location.host + '/provider/inventory'; 29668 }) 29669 .error(function(jqXHR, textStatus, errorThrown) { 29670 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 29671 GLO.UI.Form.resetProcessing(); 29672 }); 29673 } 29674 29675 return _conIAudit; 29676})(); 29677 29678 29679GLO.Inventory.Order = (function() { 29680 function _conIOrder() { } 29681 29682 function _displayPopulatedOrder(id) { 29683 var createDate = GLO.Inventory.shipment.create_dt; 29684 var orderDate = GLO.Inventory.shipment.submit_dt; 29685 var receiveDate = GLO.Inventory.shipment.received_dt; 29686 var stockDate = GLO.Inventory.shipment.stock_dt; 29687 29688 var vid = GLO.Inventory.shipment.vendor_id; 29689 var did = GLO.Inventory.shipment.distributor_id 29690 29691 var orderType = _conIOrder.populateHeaderAndReturnOrderType(createDate, orderDate, receiveDate, stockDate 29692 , GLO.Inventory.shipment.create_by_staff_vc, GLO.Inventory.shipment.update_by_staff_vc, GLO.Inventory.shipment.update_dt 29693 , vid, did); 29694 29695 var note = GLO.Inventory.shipment.note.replace('<br/>', '\n'); 29696 29697 _populateLocationByShipment(); 29698 GLO.Inventory.Restock.openEdit(id, orderType, note); 29699 } 29700 29701 function _resetSaveButton() { 29702 var j = $('#inventory-order-dates-buttons'); 29703 j.find('#btn-order-update-stock').addClass('hide'); 29704 j.find('#btn-order-save').removeClass('hide'); 29705 } 29706 29707 _conIOrder.openEdit = function(id) { 29708 _resetSaveButton(); 29709 $('#inventory-header-help-icon').removeClass('hide'); 29710 29711 if (UTIL.isEmpty(id)) { 29712 GLO.Inventory.Restock.openEdit(id, 2); 29713 return; 29714 } else if (GLO.Inventory.shipment && GLO.Inventory.shipment.length && GLO.Inventory.shipment.id == id) { 29715 _displayPopulatedOrder(id); 29716 return; 29717 } 29718 29719 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Order?id=' + id; 29720 29721 $('#inventory-search-results').addClass('processing'); //GLO.UI.Form.beginProcessing(frm.find('.btnSave')); 29722 $('.inventory-header').after('<div id="inventory-temporary-throbber" style="width: 100px; margin: auto;">' + $('.loadingDiv').clone().find('img').css({"margin": "50px auto"}).outerHTML() + '</div>') 29723 29724 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 29725 .success(function(data, textStatus, jqXHR) { 29726 $('#inventory-search-results').addClass('hide').removeClass('processing'); //GLO.UI.Form.resetProcessing(); 29727 $('#inventory-temporary-throbber').remove(); 29728 29729 $('#inventory-order-list-buttons').addClass('hide'); 29730 $('#inventory-table').removeClass('hide'); 29731 29732 var ul = $(data); 29733 var li = ul.find('li'); 29734 var dt, cnt, obj, arr = []; 29735 29736 for (var i=0; i < li.length; i++) { 29737 cnt = UTIL.coalesceInt(li.eq(i).attr('count_dr'), li.eq(i).attr('order_count_nr'));
29738 29739 obj = { "event_id": li.eq(i).attr('event_id'), "inventory_id": li.eq(i).attr('inventory_id') 29740 , "count_dr": cnt, "cost_mn": li.eq(i).attr('cost_mn'), "order_count_nr": li.eq(i).attr('order_count_nr') }; 29741 29742 if (li.eq(i).attr('name_vc')) { 29743 obj.name_vc = li.eq(i).attr('name_vc'); 29744 obj.vendor_name_vc = li.eq(i).attr('vendor_name_vc'); 29745 obj.size_dr = li.eq(i).attr('size_dr'); 29746 obj.unit_abbreviation = li.eq(i).attr('unit_abbreviation'); 29747 obj.type_name_vc = li.eq(i).attr('type_name_vc') 29748 obj.type_category_name_vc = li.eq(i).attr('type_category_name_vc'); 29749 } 29750 29751 arr.push(obj); 29752 } 29753 29754 var createDt = UTIL.cleanString(ul.attr('create_date')); 29755 var orderDt = ul.attr('order_dt'); 29756 var receiveDt = ul.attr('order_received_dt'); 29757 var stockDt = ul.attr('stock_dt'); 29758 29759 var orderType = _conIOrder.populateHeaderAndReturnOrderType(createDt, orderDt, receiveDt, stockDt 29760 , ul.attr('create_by_staff_vc'), ul.attr('update_by_staff_vc'), ul.attr('update_date') 29761 , ul.attr('vendor_id'), ul.attr('distributor_id'), ul.attr('vendor_name_vc'), ul.attr('distributor_name_vc')); 29762 _populateLocation(ul); 29763 29764 GLO.Inventory.shipment = arr; 29765 GLO.Inventory.shipment.shipment_number_vc = ul.attr('shipment_number_vc'); 29766 29767 var note = ul.text(); 29768 GLO.Inventory.Restock.openEdit(id, orderType, note); 29769 }) 29770 .error(function(jqXHR, textStatus, errorThrown) { 29771 //new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 29772 $('#inventory-search-results').removeClass('processing'); //GLO.UI.Form.resetProcessing(); 29773 }); 29774 } 29775 function _populateLocation(ul) { 29776 var j = $('#order-editable-fields'); 29777 var locationId = ul.attr('location_id'), isle = UTIL.cleanString(ul.attr('isle_vc')), shelf = UTIL.cleanString(ul.attr('shelf_vc')), rack = UTIL.cleanString(ul.attr('rack_vc')); 29778 29779 j.find('#Location_id').val(locationId); 29780 j.find('#Isle_vc').val(isle); 29781 j.find('#Shelf_vc').val(shelf); 29782 j.find('#Rack_vc').val(rack); 29783 } 29784 function _populateLocationByShipment() { 29785 var j = $('#order-editable-fields'); 29786 var locationId = GLO.Inventory.shipment.location_id, isle = UTIL.cleanString(GLO.Inventory.shipment.isle_vc); 29787 var shelf = UTIL.cleanString(GLO.Inventory.shipment.shelf_vc), rack = UTIL.cleanString(GLO.Inventory.shipment.rack_vc); 29788 29789 j.find('#Location_id').val(locationId); 29790 j.find('#Isle_vc').val(isle); 29791 j.find('#Shelf_vc').val(shelf); 29792 j.find('#Rack_vc').val(rack); 29793 } 29794 _conIOrder.populateHeaderAndReturnOrderType = function(createDate, orderDate, receiveDate, stockDate 29795 , createBy, updateBy, updateDate 29796 , vendorId, distributorId, vendorName, distributorName) { 29797 var jHead = $('#inventory-header-action-container'); 29798 //jHead.find('#Shipment_Note_vc').val( UTIL.cleanString(ul.text()) ); 29799 29800 createBy = ' ' + SA.Resource.CreatedBy + ': ' + createBy; 29801 if (!UTIL.isEmpty(updateBy)) { createBy += '\x0A' + SA.Resource.UpdatedBy + ': ' + updateBy + ' ' + SA.Resource.on_text + ' ' + updateDate; } 29802 29803 jHead.find('#Order_Create_Date').attr('title', createBy).text(createDate); 29804 29805 if (UTIL.isDate(orderDate)) { orderDate = new Date(orderDate).toGloDate(); } else { orderDate = ''; } 29806 jHead.find('#Order_dt').val(orderDate); 29807 29808 if (UTIL.isDate(receiveDate)) { 29809 receiveDate = new Date(receiveDate).toGloDate(); 29810 var orderType = 4; 29811 } else { 29812 receiveDate = ''; 29813 var orderType = 2; 29814 } 29815 29816 jHead.find('#Order_Received_dt').attr('original_value', receiveDate).val(receiveDate); 29817 jHead.find('#Stock_dt').text( UTIL.cleanString(stockDate) ); 29818 29819 //var jCompanies = $('#Filter_Company'); 29820 //if (!UTIL.isEmpty(did)) { var dnm = jCompanies.val('option[value="d' + did + '"]').attr('value'); } 29821 //if (!UTIL.isEmpty(vid)) { var vnm = jCompanies.val('option[value="v' + vid + '"]').attr('value'); } 29822 29823 return orderType; 29824 } 29825 29826 _conIOrder.openList = function() { //= for order received. 29827 var start = new Date(); 29828 var end = new Date(start.getFullYear(), start.getMonth(), start.getDate() + 1); 29829 start.setMonth(start.getMonth() - 3); 29830 29831 var uhash = 'onlyopenorders=1&start=' + start + '&end=' + end; 29832 29833 //document.location.hash = uhash; 29834 //try { window.history.pushState("", "Inventory-Report", url); } catch (e) { } 29835 29836 var url = GLO.Link.Page.Provider.Home + 'report/ShipmentHistory?' + uhash; 29837 GLO.UI.Form.beginProcessing( $('#button-order-received') ); 29838 29839 $('#inventory-table, #inventory-header-filter').addClass('hide'); 29840 $('#inventory-order-list-buttons, #manage-inventory').removeClass('hide'); 29841 $('#inventory-header-help-icon').removeClass('hide'); 29842
29843 var throbber = $('<div style="text-align: center;">' + $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}).outerHTML() + '</div>'); 29844 $('#inventory-search-results').removeClass('hide').html(throbber); 29845 29846 $('h2.inventory-header #inventory-header-text').text(SA.Resource.UnfilledOrders); 29847 var w = GLO.Inventory.docWidth + 'px'; 29848 //$('#doc3').css({ "width": w }); 29849 29850 SA.Help.display('fill-order'); 29851 29852 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 29853 .success(function(data, textStatus, jqXHR) { 29854 GLO.UI.Form.resetProcessing(); 29855 29856 if (!UTIL.isEmpty(data)) { 29857 $('#inventory-search-results:visible').html(data); 29858 29859 var tbl = $('#inventory-search-results:visible').find('table.tablesorter:visible'); 29860 UI.initTableSorter(tbl); 29861 } else { 29862 GLO.Popup.Info(SA.Resource.NoUnfilledOrderMessage); 29863 } 29864 }) 29865 .error(function(jqXHR, textStatus, errorThrown) { 29866 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 29867 GLO.UI.Form.resetProcessing(); 29868 }); 29869 } 29870 29871 _conIOrder.back = function() { 29872 if (!GLO.Inventory.backViaUri()) { 29873 if (GLO.Inventory.filterIsEmpty()) { 29874 GLO.Inventory.updateHash('product-list-intro'); 29875 } else { 29876 GLO.Inventory.updateHash('product-list'); 29877 } 29878 } 29879 } 29880 29881 _conIOrder.dateChange = function(inputField) { //inputField = #Order_Received_dt 29882 var jtbl = $('#inventory-table'); 29883 var orderId = $('#inventory-order-header #Order_id').val(); 29884 29885 if (UTIL.isDate(inputField.value)) { 29886 //$('#inventory-order-disclaimer, #inventory-order-dates-buttons').addClass('hide'); 29887 //$('#inventory-restock-edit-buttons').removeClass('hide'); 29888 29889 var jbtns = $('#inventory-order-dates-buttons'); 29890 jbtns.find('.btnSave').addClass('hide'); 29891 jbtns.find('#btn-order-update-stock').removeClass('hide'); 29892 29893 var jStockDate = $('#inventory-order-dates #Stock_dt'); 29894 29895 if (UTIL.isEmpty(jStockDate.text())) { 29896 var dtOR = $(inputField); 29897 29898 if (!UTIL.isEmpty(dtOR.attr('original_value'))) { 29899 var dtStock = dtOR.attr('original_value'); 29900 } else { 29901 var dtStock = new Date(); 29902 dtStock = dtStock.getMonthString(true) + ' ' + dtStock.getDate() + ' @ ' + dtStock.toGloTime(); 29903 } 29904 29905 jStockDate.text(dtStock); 29906 } 29907 29908 $('#inventory-table tbody tr').each(function() { 29909 var me = $(this); 29910 var ocount = me.find('.item-order-count input'); 29911 29912 if (UTIL.isEmpty(ocount.val())) { 29913 ocount.val( me.find('.item-in-stock-edit input').val() ); 29914 } 29915 }); 29916 29917 var orderType = 4; 29918 GLO.Inventory.displayColumns(orderType, jtbl, orderId); 29919 } else { 29920 //$('#inventory-order-disclaimer, #inventory-order-dates-buttons').removeClass('hide'); 29921 //$('#inventory-restock-edit-buttons').addClass('hide'); 29922 29923 var jbtns = $('#inventory-order-dates-buttons'); 29924 jbtns.find('#btn-order-update-stock').addClass('hide'); 29925 jbtns.find('#btn-order-save').removeClass('hide'); 29926 29927 //if (!UTIL.isEmpty(dtOR.attr('original_value'))) { $('#inventory-order-dates #Stock_dt').text(''); } 29928 $('#inventory-order-dates #Stock_dt').text(''); 29929 29930 var orderType = 2; 29931 GLO.Inventory.displayColumns(orderType, jtbl, orderId); 29932 } 29933 29934 GLO.Inventory.setFooter(orderType); 29935 } 29936 29937 _conIOrder.generate = function(isOverride) { 29938 var jHead = $('#inventory-header-action-container'); 29939 var jAutoOrdering = jHead.find('#inventory-order-header'); 29940 var jsdata = {}, useDefault = true, co = jHead.find('#Filter_Company').val(); 29941 var trOrder = $('#inventory-table > tbody > tr:visible'); 29942 29943 if (trOrder.length > 0 && !UTIL.parseBool(isOverride)) { 29944 var msgConfirm = '<p>Remove ' + UTIL.pluralLabel(trOrder.length, 'order row') + ' below and generate new order?<
29944/p>'; 29945 var htmConfirm = '<div id="pop-confirm-generate-order">' + msgConfirm + '</div>'; 29946 var fnConfirm = function() { GLO.Inventory.Order.generate(true); }; 29947 29948 GLO.Popup.Confirm.open(htmConfirm, 'Remove Rows + Generate Order?', fnConfirm); 29949 return; 29950 } 29951 29952 jHead.find('#last_order_date').text(''); 29953 29954 if (!UTIL.isEmpty(co)) { 29955 if (co.substring(0, 1) === 'v') { 29956 jsdata["vendor_id"] = co.substring(1); 29957 } else if (co.substring(0, 1) === 'd') { 29958 jsdata["distributor_id"] = co.substring(1); 29959 } else if (co.substring(0, 1) === 'p') { 29960 jsdata["vendor_id"] = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id'); 29961 29962 jHead.find('#Filter_Company').val('v' + jsdata["vendor_id"]); 29963 GLO.Inventory.filterOnChange(jHead); 29964 } 29965 } 29966 29967 if (jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked')) { 29968 jsdata["Since_Last_Order_fl"] = "1"; 29969 useDefault = false; 29970 } 29971 29972 if (jAutoOrdering.find('#auto_ordering_dates_fl').prop('checked')) { 29973 jsdata["Start_dt"] = jAutoOrdering.find('#auto_start_dt').val(); 29974 jsdata["End_dt"] = jAutoOrdering.find('#auto_end_dt').val(); 29975 useDefault = false; 29976 29977 if (UTIL.isEmpty(jsdata["Start_dt"])) { 29978 var st = new Date(); 29979 st = new Date(st.setDate(st.getDate() - 14)).toGloDate(); 29980 29981 jsdata["Start_dt"] = st; 29982 jAutoOrdering.find('#auto_start_dt').val(st); 29983 } 29984 29985 if (UTIL.isEmpty(jsdata["End_dt"])) { 29986 jsdata["End_dt"] = new Date().toGloDate(); 29987 jAutoOrdering.find('#auto_end_dt').val(jsdata["End_dt"]); 29988 } 29989 } 29990 29991 if (jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked')) { 29992 var minpct = jAutoOrdering.find('#minimum_pct').val(); 29993 29994 jsdata["Minimum_pct"] = UTIL.coalesce(minpct, 100); 29995 useDefault = false; 29996 29997 if (UTIL.isEmpty(minpct)) { jAutoOrdering.find('#minimum_pct').val(100); } 29998 } 29999 30000 if (useDefault) { 30001 jsdata["Since_Last_Order_fl"] = "1"; 30002 jsdata["Minimum_pct"] = 100; 30003 30004 jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked', true); 30005 jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked', true); 30006 jAutoOrdering.find('#minimum_pct').val(100); 30007 } 30008 30009 var btn = jAutoOrdering.find('#inventory-automatic-order-button'); 30010 GLO.UI.Form.beginProcessing(btn); 30011 var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderGenerate'; 30012 30013 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata }) 30014 .success(function(data, textStatus, jqXHR) { 30015 if (UTIL.Validate.hasPermissionError(data)) { return; } 30016 if ($('#inventory-automatic-ordering:visible').length === 0) { return; } 30017 30018 if (data) { 30019 var li, ul = $(data); 30020 30021 if (ul.attr('error_cd')) { 30022 GLO.Popup.Warning(ul); 30023 } else { 30024 $('#inventory-table tbody tr').each(function() { 30025 var me = $(this); 30026 var rowId = me.attr('id'); 30027 li = ul.find('li[inventory_id="' + rowId + '"]'); 30028 30029 if (li.length === 1) { 30030 me.removeClass('hide'); 30031 me.find('.item-in-stock-edit input').val(li.attr('amount_nr')).change(); 30032 } else { 30033 me.addClass('hide'); 30034 } 30035 }); 30036 30037 var lastOrderDt = ul.attr('last_order_dt'); 30038 if (!UTIL.isEmpty(lastOrderDt)) { $('#last_order_date').text(lastOrderDt); } 30039 30040 GLO.Inventory.setFooter(2); 30041 } 30042 } 30043 }) 30044 .error(function(jqXHR, textStatus, errorThrown) { 30045 new GLO.Popup.Error('Unable to generate the order at this time. Please try again later.'); 30046 GLO.UI.Form.resetProcessing(); 30047 }); 30048 30049 } 30050 30051 _conIOrder.remove = function(deleteButton) { 30052 var shipmentId = GLO.Inventory.Restock.getShipmentId(); 30053 var msg = SA.Resource.DeleteOrderConfirm; 30054 deleteButton = $(deleteButton).parent(); 30055 30056 GLO.Popup.Confirm(msg, function() { 30057 GLO.Inventory.Order.removeConfirmed(deleteButton, shipmentId); 30058 }); 30059 } 30060 30061 _conIOrder.removeConfirmed = function(deleteButton, shipmentId) { 30062 var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderDelete'; 30063 GLO.UI.Form.beginProcessing(deleteButton); 30064 30065 if (GLO.Inventory.getOrderType() === 4) { 30066 $('#Order_Received_dt').val('').change(); 30067 GLO.Inventory.Restock.save(false, true, true); 30068 return; 30069 } 30070
30071 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } }) 30072 .success(function(data, textStatus, jqXHR) { 30073 if (UTIL.Validate.hasPermissionError(data)) { return; } 30074 30075 GLO.Inventory.Order.back(); 30076 }) 30077 .error(function(jqXHR, textStatus, errorThrown) { 30078 new GLO.Popup.Error('Unable to delete the order at this time. Please try again later.'); 30079 GLO.UI.Form.resetProcessing(); 30080 }); 30081 } 30082 30083 _conIOrder.email = function(wasSaved) { 30084 if (!wasSaved) { 30085 var saveButton = $('#inventory-header-action-container').find('.btnSave:visible'); 30086 30087 if (saveButton.length === 1 && saveButton.find('a').css("border-color").toLowerCase() === 'rgb(255, 0, 0)') { 30088 GLO.Inventory.Restock.save(false, true, false, true); 30089 return; 30090 } else if (UTIL.isEmpty(GLO.Inventory.Restock.getShipmentId())) { 30091 GLO.Inventory.Restock.save(false, true, false, true); 30092 return; 30093 } 30094 } 30095 30096 var ddStaff = '<option>' + $('.staffDD:first').html() + '</option>'; 30097 30098 var div = $('<div id="email-order-popup">' 30099 + '<h2>' + SA.Resource.EmailOrder + '</h2>' 30100 + '<style id="pop-return-style"> .ui-autocomplete { z-index: 6000 !important; } </style>' 30101 + '<div id="email-order-popup-container">' 30102 + '<div id="email-order-row1">' 30103 + '<label id="email-order-add-client-label" for="email-order-to-client"> <b>' + SA.Resource.SendTo + '</b> <span>( ' + SA.Resource.enter_client_name + ' )</span> </label>' 30104 + '<input id="email-order-to-client" type="text" maxlength="100"/>' 30105 + '<span id="email-order-add-client" style="white-space: nowrap;">( <a onclick="UserPortal.Create.addClientLink()" title="' + SA.Resource.AddNewClient + '">' + SA.Resource.AddClient.toLowerCase() + '</a> )</span>' 30106 + '</div>' 30107 + '<div id="email-order-row2">' 30108 + '<label for="email-order-copy-staff"> <b>' + SA.Resource.CopyStaff + '</b> <span>( cc staff )</span></label>' 30109 + '<select id="email-order-copy-staff" type="text">' + ddStaff + '</select>' 30110 + '</div>' 30111 + '<div id="email-order-row3a">' 30112 + '<label for="email-order-include-note">' + SA.Resource.IncludeNoteInEmail + '</label>' 30113 + '</div>' 30114 + '<div id="email-order-row3b">' 30115 + '<textarea id="email-order-include-note" style="width: 96%;"></textarea>' 30116 + '</div>' 30117 + '</div>' 30118 + '</div>'); 30119 30120 var oj = GLO.Popup.Custom(div, GLO.Inventory.Order.emailConfirmed); 30121 var jpop = oj.getPopup(); 30122 30123 jpop.addClass('no-persist'); 30124 jpop.find('h2').css({ "letter-spacing": "2px" }); 30125 30126 jpop.find('.pop-buttons').css({ "width": "300px", "margin": "auto", "margin-bottom": "8px" }); 30127 jpop.find('.btnSave a').text('Send'); 30128 //jpop.find('.btnCancel a').text(SA.Resource.Close); 30129 30130 jpop.find('#email-order-to-client').autocomplete({ 30131 minLength: 2, source: GLO.Link.Object.Provider.UserSearch + '?isorder=1', 30132 select: function(event, ui) { 30133 this.value = ui.item.value 30134 $('#email-order-popup').attr('client_id', ui.item.id); 30135 } 30136 }); 30137 30138 jpop.find('#email-order-copy-staff').val(GLO.Info.StaffId); 30139 30140 var note = UTIL.coalesce($('#Shipment_Note_vc:visible').val(), $('#shipment-detail-header-note').text()); 30141 jpop.find('#email-order-include-note').val(note); 30142 } 30143 30144 _conIOrder.emailConfirmed = function(clientId) { 30145 var shipmentId = $('#shipment-detail-header').attr('shipment_id'); 30146 if (UTIL.isEmpty(shipmentId)) { shipmentId = GLO.Inventory.Restock.getShipmentId(); } 30147 30148 var jpop = $('#email-order-popup'); 30149 var cid = jpop.attr('client_id'); 30150 var cname = jpop.find('#email-order-to-client').val(); 30151 var sid = jpop.find('#email-order-copy-staff').val(); 30152 var note = UTIL.replaceAll(UTIL.replaceAll(jpop.find('#email-order-include-note').val(), '<', ''), '>', ''); 30153 30154 if (UTIL.isEmpty(cid)) { 30155 GLO.Popup.Warning(SA.Resource.PleaseEnterClientName, function() { $('#email-order-popup').find('#email-order-to-client').focus(); }); 30156 return; 30157 } 30158 30159 var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderEmail'; 30160 var emailBtn = $('#shipment-detail-header-buttons #btnEmail'); 30161 30162 GLO.UI.Form.beginProcessing(jpop.closest('.glopop').find('.btnSave')); 30163
30164 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "shipment_id": shipmentId, "to_client_id": cid, "cc_staff_id": sid, "note_vc": note } }) 30165 .success(function(data, textStatus, jqXHR) { 30166 if (UTIL.Validate.hasPermissionError(data)) { return; } 30167 30168 data = $(data); 30169 30170 if (data.attr('error_cd') == '100') { 30171 ClientProfile.goto(cid , 1, cname); 30172 30173 var msg = cname + ' ' + SA.Resource.EmailMissingWarning + ' ' + cname + '.'; 30174 GLO.Popup.Warning(msg, function() { $('#simplemodal-container').css({ "z-index": 9999 }); }); 30175 } else { 30176 var dt = new Date().toGloDate(); 30177 var j = $('#inventory-order-dates').find('#Order_dt'); 30178 30179 if (UTIL.isEmpty(j.val())) { j.val(dt); } 30180 30181 GLO.UI.Form.resetProcessing(); 30182 GLO.Popup.close(); 30183 GLO.Popup.Success(SA.Resource.OrderEmailed); 30184 } 30185 }) 30186 .error(function(jqXHR, textStatus, errorThrown) { 30187 var htm = '<p>There is a problem sending this order as an email</p> <p>Please wait a few minutes before sending this email</p>'; 30188 GLO.Popup.Error.open(htm, 'Order Email Not Sent'); 30189 GLO.UI.Form.resetProcessing(); 30190 }); 30191 } 30192 30193 _conIOrder.printView = function() { 30194 var shipmentId = $('#shipment-detail-header').attr('shipment_id'); 30195 _savePrintDate(shipmentId); 30196 30197 UI.Print.printOnDevice(); 30198 } 30199 30200 _conIOrder.print = function() { 30201 var dt = new Date(); 30202 var sdt = dt.toGloDateString(true, true, true, true) + ' @ ' + dt.toGloTime(); 30203 30204 var jPrint = $('#print-order-only').addClass('print-only').removeClass('print-order-only'); 30205 jPrint.find('#print-only-date-header').text(sdt); 30206 30207 setTimeout(GLO.Inventory.Order.afterPrint, 450); 30208 UI.Print.printOnDevice(); 30209 30210 var shipmentId = GLO.Inventory.Restock.getShipmentId(); 30211 30212 var jOrderDate = $('#inventory-order-dates').find('#Order_dt'); 30213 if (!UTIL.isEmpty(jOrderDate.val())) { jOrderDate.val(dt.toGloDate()); } 30214 30215 if (!UTIL.isEmpty(shipmentId)) { 30216 _savePrintDate(shipmentId); 30217 } else { 30218 GLO.Inventory.Restock.save(true, true); 30219 } 30220 } 30221 30222 _conIOrder.afterPrint = function() { 30223 if (document.readyState == "complete") { 30224 $('#print-order-only').addClass('print-order-only').removeClass('print-only'); 30225 } else { 30226 setTimeout(GLO.Inventory.Order.afterPrint, 150); 30227 } 30228 } 30229 30230 function _savePrintDate(shipmentId) { 30231 var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderPrinted'; 30232 var printBtn = $('#inventory-order-print-button'); 30233 GLO.UI.Form.beginProcessing(printBtn); 30234 30235 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } }) 30236 .success(function(data, textStatus, jqXHR) { 30237 if (UTIL.Validate.hasPermissionError(data)) { return; } 30238 30239 var dt = new Date().toGloDate(); 30240 var j = $('#inventory-order-dates').find('#Order_dt'); 30241 30242 if (UTIL.isEmpty(j.val())) { j.val(dt); } 30243 }) 30244 .error(function(jqXHR, textStatus, errorThrown) { 30245 //new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 30246 GLO.UI.Form.resetProcessing(); 30247 }); 30248 } 30249 30250 _conIOrder.save = function() { 30251 GLO.Inventory.Restock.save(false, true); 30252 } 30253 30254 return _conIOrder; 30255})(); 30256 30257 30258GLO.Inventory.Item = (function() { 30259 function _conIItem() { } 30260 var _lookingUpCostBasis = false; 30261 var _loadingCostPopup = false; 30262 var cropper = null; 30263 30264 _conIItem.openViewPopup = function(id) { 30265 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + id + '&dt=' + UTIL.getDateString(); //var uri = GLO.Link.Page.Provider.Home + 'Inventory#action=view-product&id=' + id; //UI.openChildWindow(uri, '', true);
30266 var throbber = $('<div style="text-align: center;">' + $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}).outerHTML() + '</div>'); 30267 30268 var ojpop = new GLO.Popup.Custom(throbber, UserPortal.Price.productCommissionSet); 30269 jpop = ojpop.getPopup(); //.addClass('no-persist'); 30270 30271 jpop.find('.pop-buttons-parent').remove(); 30272 jpop.css({ "padding-left": "0", "padding-right": "0", "padding-top": "0" }); 30273 30274 var ocss = { "min-height": "100px", "min-width": "550px", "margin-left": "0", "margin-right": "0", "padding-top": "0", "padding-left": "0", "padding-right": "0" }; 30275 30276 if (GLO.Info.isMobile() && !GLO.Info.isLandscape()) { ocss["min-width"] = "320px"; } 30277 30278 jpop.find('.msg').css(ocss).load(uri, function(responseText, textStatus, XMLHttpRequest) { 30279 if (GLO.Log.processesSecurityException(jpop, arguments[0], arguments[1], arguments[2])) { return; } 30280 30281 $('.msg').find('#product-summary-buttons-parent').removeClass('hide'); //.css({ "position": "", "margin-left": "", "margin": "auto", "margin-top": "30px", "width": "300px" }); 30282 30283 ojpop.realign(); 30284 }); 30285 } 30286 30287 _conIItem.back = function() { 30288 GLO.Inventory.updateHash('product-list'); 30289 } 30290 30291 _conIItem.unHide = function() { 30292 if (GLO.Inventory.prevHash.indexOf('-list') !== -1) { 30293 GLO.Inventory.updateHash(GLO.Inventory.prevHash, GLO.Inventory.prevHashId); 30294 } else if (GLO.Inventory.prevIsItem) { 30295 var id = UTIL.coalesce(GLO.Inventory.prevItemId, $('#inventory-item-edit #Inventory_id').val()); 30296 30297 if (!UTIL.isEmpty(id)) { 30298 GLO.Inventory.updateHash('edit-product', id); 30299 } else { 30300 GLO.Inventory.updateHash('new-product', 0); 30301 } 30302 } else if (GLO.Inventory.isProductListView(GLO.Inventory.prevHash)) { 30303 GLO.Inventory.updateHash(GLO.Inventory.prevHash); 30304 } else { 30305 GLO.Inventory.updateHash('product-list'); 30306 } 30307 } 30308 30309 _conIItem.openItem = function(id) { 30310 var jbtn = $(event.currentTarget); 30311 30312 if ($('#manage-inventory').length && GLO.Inventory.isProductList) { 30313 _conIItem.click(event.currentTarget, id); 30314 30315 setTimeout(function() { 30316 if ($('#inventory-item-summary').closest('#simplemodal-container').length) { 30317 $.modal.close(); 30318 } 30319 }, 1100); 30320 } else { 30321 GLO.Uri.gotoUri('provider/inventory#action=view-product&id=' + id); 30322 } 30323 30324 setTimeout(function() { 30325 GLO.UI.Form.beginProcessing(jbtn); 30326 }, 100); 30327 } 30328 30329 _conIItem.click = function(element, id) { 30330 if (UTIL.isEmpty(id)) { id = $(element).closest('tr').attr('id'); } 30331 var action = GLO.Uri.hash('action').toLowerCase(); 30332 30333 if (action === 'order' || action === 'audit' || action === 'restock' || $('#shipment-detail-header:visible').length === 1 || document.location.pathname.substring(0, 9) === '/reports/') { 30334 if (GLO.Info.isMobile(true)) { GLO.UI.animate(10); } 30335 30336 var url = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=edit-product&id=' + id; 30337 var childWindow = UI.openChildWindow(url, '', true, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes,height=800"); 30338 } else if ( $('#inventory-item-form').length === 0) { 30339 GLO.Inventory.updateHash('view-product', id); 30340 } else { 30341 GLO.Inventory.updateHash('edit-product', id); 30342 } 30343 } 30344 30345 _conIItem.openView = function(id) { 30346 var jItem = $("#inventory-item-view"); 30347 var tr = $('#inventory-table tbody tr#' + id); 30348 30349 var type = tr.find('.item-type-category').text() 30350 var category = tr.find('.item-type').text() 30351 30352 if (type && category) { 30353 type = type + " - " + category; 30354 } else if (category) { 30355 type = category; 30356 } 30357 30358 jItem.attr('is_gift_card_fl', tr.attr('is_gift_card_fl')); 30359 30360 jItem.find('#vw-name').text( UTIL.coalesce(tr.find('.item-name').attr('title'), tr.find('.item-name').text()) ); 30361 jItem.find('#vw-vendor').text( tr.find('.item-vendor').text() ); 30362 30363 jItem.find('#vw-sku').text( tr.attr('sku_vc') ); 30364 jItem.find('#vw-upc').text( tr.attr('upc_vc') ); 30365 jItem.find('#vw-shelf').text( tr.find('.item-shelf').text() ); 30366 30367 jItem.find('#vw-type').text(type); 30368 jItem.find('#vw-size').text( tr.find('.item-size').text() ); 30369 30370 var cost = tr.find('.item-cost').text(); 30371 if (!UTIL.isEmpty(cost)) { cost = '$' + cost; } 30372 jItem.find('#vw-cost').text(cost); 30373 30374 var price = tr.find('.item-price').text(); 30375 //if (!UTIL.isEmpty(price)) { price = '$' + price; } 30376 jItem.find('#vw-price').text(price); 30377 30378 var eprice = tr.attr('employee_price_mn'); 30379 if (!UTIL.isEmpty(eprice)) { eprice = '$' + eprice; } 30380 jItem.find('#vw-employee-price').text(eprice); 30381
30382 jItem.find('#vw-in-stock').text(tr.find('.item-in-stock').text()); 30383 jItem.find('#vw-min-stock').text(tr.find('.item-minimum-stock:visible').text()); 30384 30385 var desc = tr.find('.item-desc').text(); 30386 30387 if (!UTIL.isEmpty(desc)) { 30388 jItem.find('#vw-description').text(desc); 30389 jItem.find('.vw-item-description').removeClass('hide'); 30390 } else { 30391 jItem.find('.vw-item-description').addClass('hide'); 30392 } 30393 30394 if (UTIL.parseBool(tr.attr('for_retail_fl'))) { 30395 jItem.find('#vw-is-for-retail').removeClass('hide'); 30396 } else { 30397 jItem.find('#vw-is-for-retail').addClass('hide'); 30398 } 30399 30400 if (UTIL.parseBool(tr.attr('for_internal_fl'))) { 30401 jItem.find('#vw-is-for-internal').removeClass('hide'); 30402 } else { 30403 jItem.find('#vw-is-for-internal').addClass('hide'); 30404 } 30405 30406 tax = tr.attr('tax_rate_pct'); 30407 commission = tr.attr('commission_pct'); 30408 30409 if (!UTIL.isEmpty(tax)) { 30410 jItem.find('#vw-tax-rate').text(tax); 30411 jItem.find('.vw-item-tax-rate').removeClass('hide'); 30412 } else { 30413 jItem.find('.vw-item-tax-rate').addClass('hide'); 30414 } 30415 30416 if (!UTIL.isEmpty(commission)) { 30417 jItem.find('#vw-commission').text(tax); 30418 jItem.find('.vw-item-commission').removeClass('hide'); 30419 } else { 30420 jItem.find('.vw-item-commission').addClass('hide'); 30421 } 30422 30423 jItem.removeClass('hide'); 30424 } 30425 30426 _conIItem.openEdit = function(id) { 30427 GLO.Inventory.Item.costXml = null; 30428 var jItem = $("#inventory-item-form"); 30429 var jOverride = $('#inventory-item-override-row'); 30430 30431 var nm = '', vendor = '', productLine = '', sku = '', upc = '', category = '', typeId = '', size = '', unit = '', shelfDays = ''; 30432 var webCode = null, forRetail = true, forInternal = '', trackStock, cost = '', price = '', inStock = '', minStock = '', employeePrice = '', tax = '', commission = '', desc = ''; //overrideTax = false 30433 var itemImageFilename='', itemImageCount = '', isVariation = 0, hasVariations = 0, parentInventoryId = 0, isCombo = 0, isBundle = 0; 30434 30435 jOverride.find('label').css({ "cursor": "pointer", "text-decoration": "underline" }); 30436 jOverride.find('#inventory-item-override-tax, #inventory-item-override-commission').addClass('hide'); 30437 30438 if (!UTIL.isEmpty(id)) { 30439 if (id == 0) { //= is going back to new product. 30440 jItem.removeClass('hide'); 30441 return; 30442 } 30443 30444 var tr = $('#inventory-table tbody tr#' + id); 30445 30446 nm = UTIL.coalesce(tr.find('.item-name').attr('title'), tr.find('.item-name').text()); 30447 vendor = tr.find('.item-vendor').attr('vendor_id'); 30448 productLine = tr.find('.item-product-line').attr('product_line_id'); 30449 30450 sku = UTIL.coalesce($.trim(tr.find('.item-sku').attr('title')), $.trim(tr.find('.item-sku').text()), tr.attr('sku_vc')); 30451 upc = UTIL.coalesce($.trim(tr.find('.item-upc').attr('title')), $.trim(tr.find('.item-upc').text()), tr.attr('upc_vc')); 30452 shelfDays = UTIL.coalesceInt(tr.find('.item-shelf').attr('order_by'), tr.attr('shelf_days_nr')); 30453 30454 category = tr.find('.item-type-category').attr('type_category_id'); 30455 typeId = tr.find('.item-type').attr('type_id'); 30456 30457 unit = tr.find('.item-size').attr('unit_id'); 30458 var unitAbbreviation = $('select#Unit_id option[value="' + unit + '"]').attr('title'); 30459 size = jQuery.trim(tr.find('.item-size').attr('size_dr')); //.replace(unitAbbreviation, '') 30460 30461 trackStock = UTIL.parseBool(tr.attr('track_stock_fl')) && (GLO.Info.providerPackage != 4); 30462 forRetail = UTIL.parseBool(tr.attr('for_retail_fl')); 30463 forInternal = UTIL.parseBool(tr.attr('for_internal_fl')); 30464 webCode = tr.attr('web_cd'); 30465 30466 cost = tr.find('.item-cost').text(); 30467 30468 if (UTIL.isEmpty(cost)) { 30469 cost = 'set cost'; 30470 } else { 30471 cost = '$' + UTIL.roundMoney(cost.replace('$', '')); 30472 } 30473 30474 inStock = tr.find('.item-in-stock').text(); 30475 if (UTIL.isNumber(inStock)) { inStock = parseInt(inStock); } 30476 30477 minStock = tr.find('.item-minimum-stock').text(); 30478 30479 price = UTIL.cleanString(tr.find('.item-price')).text().replace('$', ''); 30480 employeePrice = UTIL.cleanString(tr.attr('employee_price_mn')).replace('$', ''); //employeePrice = tr.find('.item-employee-price').text(); 30481 30482 tax = tr.attr('tax_rate_pct'); //tax = tr.find('.item-tax').text(); 30483 commission = tr.attr('commission_pct'); 30484 30485 if (!UTIL.isEmpty(tax) || !UTIL.isEmpty(commission)) { 30486 if (!UTIL.isEmpty(tax)) { 30487 jOverride.find('label[for="Tax_Rate_pct"]').css({ "text-decoration": "" }); 30488 jOverride.find('#inventory-item-override-tax').removeClass('hide'); 30489 } 30490 30491 if (!UTIL.isEmpty(commission)) { 30492 jOverride.find('label[for="Commission_pct"]').css({ "text-decoration": "" }); 30493 jOverride.find('#inventory-item-override-commission').removeClass('hide'); 30494 } 30495 } 30496 30497 desc = tr.find('.item-desc').text(); 30498 itemImageFilename = tr.find('.item-image-path').text(); 30499 itemImageCount = tr.find('.item-image-count').text(); 30500 isVariation = (UTIL.parseBool(tr.find('.item-is-variation').text())) ? 1 : 0; 30501 hasVariations = (UTIL.parseBool(tr.find('.item-has-variations').text())) ? 1 : 0; 30502 parentInventoryId = tr.find('.item-parent-inventory-id').text(); 30503 isCombo = (UTIL.parseBool(tr.find('.item-is-combo').text())) ? 1 : 0; 30504 isBundle = (UTIL.parseBool(tr.find('.item-is-bundle').text())) ? 1 : 0; 30505 jItem.find('#inventory-item-override-row') 30506 30507 if (isBundle) { 30508 GLO.Inventory.Item.getBundleProducts(id); 30509 } else { 30510 resetChildProductsGrid(); 30511 $('#Price_mn').removeAttr('disabled'); 30512 $('#Employee_Price_mn').removeAttr('disabled'); 30513 $('#Avg_Cost_mn').attr("onclick","GLO.Inventory.Item.openCostPopup()"); 30514 } 30515 30516 /* for now only lookup this information when click to open the cost basis popup 30517 if (!UTIL.isEmpty(tr.find('.item-cost-parent').attr('last_cost_mn'))) { 30518 _lookupCostBasis(id); 30519 } 30520 */ 30521 30522 jItem.find('#In_Stock_link').removeClass('hide').text(inStock); 30523 jItem.find('#Avg_Cost_mn').removeClass('hide').text(cost); 30524 jItem.find('#In_Stock_dr').addClass('hide'); 30525 30526 var jHead = $('.inventory-header'); 30527 jHead.find('#inventory-header-options-link, #inventory-header-reports-link').addClass('hide');
30528 jHead.find('.btnBuyNow, .btnReturnProduct').removeClass('hide'); 30529 30530 if (trackStock) { jItem.find('#In_Stock_dr, #Cost_mn, #Cost_mn_dollar').addClass('hide'); } 30531 } else { 30532 var jvendorDD = jItem.find('#Vendor_id'); //if (jvendorDD.find('option').length === 2) { vendor = jvendorDD.find('option').eq(1).attr('value'); } 30533 var tr = null; 30534 30535 jItem.find('#In_Stock_dr, #Cost_mn_dollar, #Cost_mn').removeClass('hide'); 30536 jItem.find('#In_Stock_link, #Avg_Cost_mn').addClass('hide'); 30537 30538 trackStock = UTIL.parseBool($('#inventory-options').attr('track_stock_fl')); 30539 30540 if (UTIL.parseBool(GLO.Uri.hash('internal-use'))) { 30541 forRetail = 0; 30542 forInternal = 1; 30543 price = employeePrice = tax = commission = 0; 30544 30545 $('#inventory-item-override-commission').toggleClass('hide'); 30546 $('#inventory-item-override-tax').toggleClass('hide'); 30547 } 30548 } 30549 30550 jItem.find('#Inventory_id').val(UTIL.cleanString(id)); 30551 jItem.find('#Name_vc').val(nm).focus(); 30552 jItem.find('#Vendor_id').val(vendor).change(); 30553 jItem.find('#Product_Line_id').val(productLine); 30554 jItem.find('#Unit_id').val(unit); 30555 30556 jItem.find('#SKU_vc').val(sku); 30557 jItem.find('#UPC_vc').val(upc); 30558 _setShelfLife(jItem, shelfDays); 30559 30560 if (!UTIL.isEmpty(category) && UTIL.isEmpty(typeId)) { 30561 var jtype = jItem.find('#Inventory_Type_id'); 30562 30563 if (jtype.find('option[value="c' + category + '"]').length === 0) { 30564 var catName = $('#Type_Category_id').find('option[value="' + category + '"]').text(); 30565 jtype.find('option:first').after('<option value="c' + category + '">' + catName + '</option>'); 30566 } 30567 30568 jtype.val('c' + category); 30569 } else { 30570 jItem.find('#Inventory_Type_id').val(typeId); 30571 } 30572 30573 jItem.find('#Size_dr').val(size); 30574 jItem.find('#Web_cd').val(webCode); 30575 jItem.find('#For_Retail_fl').prop('checked', forRetail); 30576 jItem.find('#For_Internal_fl').prop('checked', forInternal); 30577 jItem.find('#Track_Stock_fl').prop('checked', trackStock); 30578 30579 jItem.find('#Cost_mn').val(cost.replace('$', '')); 30580 jItem.find('#Price_mn').val(price); 30581 30582 jItem.find('#In_Stock_dr').val(inStock); 30583 jItem.find('#Minimum_Stock_dr').val(minStock); 30584 jItem.find('#Employee_Price_mn').val(employeePrice); 30585 30586 jItem.find('#Tax_Rate_pct').val(tax); //jItem.find('#Override_Tax_Rate_fl').prop('checked', overrideTax); 30587 jItem.find('#Commission_pct').val(commission); 30588 30589 jItem.find('#Description_vc').val(desc); 30590 30591 if (id !== '') { 30592 //item has been saved 30593 //TODO: DISPLAY ITEM IMAGE COUNT 30594 } 30595 else { 30596 30597 //TODO: CHANGE MANAGE IMAGES TO ADD IMAGES 30598 } 30599 30600 if (false && $('#Vendor_id option').length === 1) { //= brand is optional so do NOT require creating brand first. 30601 GLO.Inventory.Vendor.openEdit(); 30602 } else { 30603 jItem.removeClass('hide'); 30604 } 30605 30606 _setGiftCard(tr, jItem); 30607 _conIItem.setMarkup(); 30608 30609 jItem.find('#Track_Stock_fl').change(); 30610 jItem.find('.btnSave a').css({ "border": "3px solid transparent" }); 30611 jItem.find('input:first').focus(); 30612 30613 if (isVariation == 1) { 30614 //hide buttons, manage options link 30615 $(jItem.find('#inventory-item-image-row')[0]).addClass('hide'); 30616 $(jItem.find('#inventory-item-buttons')[0]).find('#ba-Save').addClass('hide'); 30617 $(jItem.find('#inventory-item-buttons')[0]).find('.btnDelete').addClass('hide'); 30618 $(jItem.find('#inventory-item-is-variant-row')[0]).removeClass('hide'); 30619 if (parentInventoryId > 0) { 30620 var masterProductLinkEl = $(jItem.find('#inventory-item-is-variant-row')[0]).find('#link-to-master-product'); 30621 var masterProductPageUrl = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=edit-product&id=' + parentInventoryId; 30622 $(masterProductLinkEl).attr('href',masterProductPageUrl); 30623 } 30624 } 30625 else { 30626 $(jItem.find('#inventory-item-image-row')[0]).removeClass('hide'); 30627 $(jItem.find('#inventory-item-buttons')[0]).find('#ba-Save').removeClass('hide'); 30628 $(jItem.find('#inventory-item-buttons')[0]).find('.btnDelete').removeClass('hide'); 30629 $(jItem.find('#inventory-item-is-variant-row')[0]).addClass('hide'); 30630 var masterProductLinkEl = $(jItem.find('#inventory-item-is-variant-row')[0]).find('#link-to-master-product'); 30631 var masterProductPageUrl = '#'; 30632 $(masterProductLinkEl).attr('href',masterProductPageUrl); 30633 } 30634 30635 if (hasVariations == 1) { 30636 30637 } 30638 } 30639 function _setGiftCard(tr, jitem) { 30640 var isGiftCard = ((tr && UTIL.parseBool(tr.attr('is_gift_card_fl'))) || (tr === null && GLO.Uri.hash('and') == 'gift-card')) ? 1 : 0; 30641 30642 jitem.find('#Is_Gift_Card_fl').val(isGiftCard); 30643 30644 if (isGiftCard) { 30645 var isGiftVoucher = (jitem.find('#Inventory_Type_id option:selected').attr('default_t
30645ype_id') == 116); 30646 jitem.addClass('is-gift-card'); 30647 jitem.find('#Enable_Gift_Voucher_fl').prop('checked', isGiftVoucher).change(); 30648 30649 _populateReferrerVoucherList(jitem, tr); 30650 30651 if (tr) { 30652 jitem.find('#Expire_Days_sr').val(tr.attr('expire_days_sr')); 30653 jitem.find('#Min_Purchase_mn').val(tr.attr('min_purchase_mn')); 30654 jitem.find('#Referrer_Amount_mn').val(tr.attr('referrer_amount_mn')); 30655 30656 jitem.find('#Gift_Only_fl').prop('checked', UTIL.parseBool(tr.attr('gift_only_fl'))); 30657 jitem.find('#New_Client_Only_fl').prop('checked', UTIL.parseBool(tr.attr('new_client_only_fl'))); 30658 return; 30659 } else { 30660 jitem.find('#inventory-item-override-tax').removeClass('hide'); 30661 jitem.find('#inventory-item-override-commission').removeClass('hide'); 30662 30663 //GLO.Uri.removeHashKey('and'); //= do NOT call because re-triggers hashChange 30664 var typeId = GLO.Inventory.Type.getGiftCardSubCategory(); 30665 jitem.find('#Inventory_Type_id').val(typeId); 30666 30667 jitem.find('#Tax_Rate_pct').val('0'); 30668 jitem.find('#Commission_pct').val('0'); 30669 jitem.find('#For_Retail_fl').prop('checked', true); 30670 } 30671 30672 _autoAddGiftCardTypeIfMissingCheck(); 30673 } else { 30674 jitem.removeClass('is-gift-card'); 30675 } 30676 30677 jitem.find('#Expire_Days_sr, #Min_Purchase_mn, #Referrer_Amount_mn').val(''); 30678 jitem.find('#Gift_Only_fl, #New_Client_Only_fl').prop('checked', false); 30679 } 30680 function _autoAddGiftCardTypeIfMissingCheck() { 30681 if ($('select#Inventory_Type_id option[default_type_id = 115]').length === 0) { 30682 _autoAddGiftCardTypeIfMissing(); 30683 } else if ($('select#Inventory_Type_id option[default_type_id = 116]').length === 0) { 30684 _autoAddGiftCardTypeIfMissing(); 30685 } else if ($('select#Type_Category_id option[default_type_category_id = 41]').length === 0) { 30686 _autoAddGiftCardTypeIfMissing(); 30687 } 30688 } 30689 function _autoAddGiftCardTypeIfMissing() { 30690 var uri = GLO.Link.Page.Provider.Home + 'Inventory/CreateGiftType'; 30691 var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false }) 30692 .success(function(data, textStatus, jqXHR) { 30693 if (UTIL.coalesceInt($(data).attr('change_count_sr')) > 0) { 30694 var msg = '<p>Loading missing gift card/voucher category and sub-category...</p>'; 30695 GLO.Popup.Processing.open('<div id="pop-processing-gift-type-created">' + msg + '</div>', 'Loading Gift Data...'); 30696 30697 setTimeout(function() { 30698 location.reload(); 30699 }, 900); 30700 } 30701 }); 30702 //.error(function(jqXHR, textStatus, errorThrown) { }); 30703 } 30704 30705 function _populateReferrerVoucherList(jitem, tr) { 30706 var voucherTypeId = $('select#Inventory_Type_id option[default_type_id = 116]').val(); 30707 var jvoucher = $('#inventory-table').find('tbody td.item-type[type_id = ' + voucherTypeId + ']'); 30708 var referrerInventoryId = null, optionList = '<option value=""></option>'; 30709 30710 if (jvoucher.length > 1 || (jvoucher.length == 1 && jvoucher.closest('tr').attr('id') != tr.attr('id'))) { //= more than 1 voucher or this is not the voucher 30711 if (tr) { 30712 referrerInventoryId = tr.attr('referrer_inventory_id'); 30713 } 30714 30715 for (var i=0; i < jvoucher.length; i++) { 30716 var selectedAttribute = '', jtr = jvoucher.eq(i).parent('tr'); 30717 var inventoryId = jtr.attr('id'); 30718 var name = jtr.find('.item-name').text(); 30719 30720 if (referrerInventoryId == inventoryId) { 30721 selectedAttribute = ' selected="selected"'; 30722 } 30723 30724 optionList += '<option value="' + inventoryId + '"' + selectedAttribute + '>' + name + '</option>'; 30725 } 30726 30727 jitem.find('#Referrer_Inventory_id').html(optionList).removeClass('hide'); 30728 jitem.find('label[for="Referrer_Inventory_id"]').removeClass('hide'); 30729 } else { 30730 jitem.find('label[for="Referrer_Inventory_id"], #Referrer_Inventory_id').addClass('hide'); 30731 } 30732 } 30733 function _setShelfLife(jitem, shelfDays) { 30734 if (shelfDays > 0) { 30735 if (shelfDays % 365 == 0) { 30736 var days = parseInt(shelfDays/365), period = '365'; 30737 } else if (shelfDays % 30 == 0) { 30738 var days = parseInt(shelfDays/30), period = '30'; 30739 } else if (shelfDays % 7 == 0) { 30740 var days = parseInt(shelfDays/7), period = '7'; 30741 } else { 30742 var days = parseInt(shelfDays), period = '1'; 30743 } 30744 } else { 30745 var days = '', period = ''; 30746 } 30747 30748 jitem.find('#Shelf_Life_nr').val(days);
30749 jitem.find('#Shelf_Life_Period_nr').val(period); 30750 } 30751 function _saveShelf(frm, jsonItem) { 30752 var nr = frm.find('#Shelf_Life_nr').val(); 30753 var period = frm.find('#Shelf_Life_Period_nr').val(); 30754 30755 if (nr > 0) { 30756 jsonItem.Shelf_Life_Days_nr = parseInt(parseInt(nr) * parseInt(period)); 30757 } 30758 } 30759 30760 _conIItem.changeType = function() { 30761 var jitem = $("#inventory-item-form"); 30762 var isVoucher = (jitem.find('#Inventory_Type_id option:selected').attr('default_type_id') == 116); 30763 var jenable = jitem.find('#Enable_Gift_Voucher_fl'); 30764 30765 if (!isVoucher && jenable.prop('checked')) { 30766 jenable.prop('checked', false).change(); 30767 } else if (isVoucher && !jenable.prop('checked')) { 30768 jenable.prop('checked', true).change(); 30769 } 30770 } 30771 _conIItem.changeEnableVoucher = function() { 30772 var jitem = $("#inventory-item-form"); 30773 var isEnabled = jitem.find('#Enable_Gift_Voucher_fl').prop('checked'); 30774 30775 if (isEnabled) { 30776 jitem.addClass('is-gift-voucher-enabled'); 30777 30778 var jtype = jitem.find('#Inventory_Type_id'); 30779 30780 if (jtype.find('option:selected').attr('default_type_id') != 116) { 30781 jtype.find('option[default_type_id=116]').prop('selected', true); 30782 } 30783 } else { 30784 jitem.removeClass('is-gift-voucher-enabled'); 30785 } 30786 } 30787 _conIItem.changeTrackStock = function(element) { 30788 var j = $('#inventory-item-edit:visible'); 30789 var iid = j.find('#Inventory_id').val(); 30790 30791 if (j.length === 0) { return; } 30792 30793 if (element.checked) { 30794 j.find('.track-stock-level').css({ "background-color": "#C1FFC1" }); 30795 j.find('label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"]').css({ "text-decoration": "" }); 30796 30797 j.find('#Minimum_Stock_dr').removeClass('hide'); 30798 30799 if (!UTIL.isEmpty(iid)) { 30800 j.find('#In_Stock_link, #Avg_Cost_mn').removeClass('hide'); 30801 j.find('#Cost_mn').addClass('hide'); 30802 30803 if (!UTIL.isNumber(j.find('#Avg_Cost_mn').text(), true)) { 30804 j.find('#Avg_Cost_mn').text('set cost'); 30805 } 30806 } else { 30807 j.find('#In_Stock_dr, #Cost_mn').addClass('hide'); 30808 } 30809 } else { 30810 j.find('.track-stock-level').css({ "background-color": "#ddd" }); 30811 j.find('label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"]').css({ "text-decoration": "line-through" }); 30812 30813 j.find('#Avg_Cost_mn, #In_Stock_dr, #In_Stock_link, #Minimum_Stock_dr').addClass('hide'); 30814 j.find('#Cost_mn').removeClass('hide'); 30815 30816 if (!UTIL.isNumber(j.find('#Cost_mn').val(), true)) { j.find('#Cost_mn').val(''); } 30817 } 30818 } 30819 30820 _conIItem.clickCommission = function(element) { 30821 $('#inventory-item-override-commission').toggleClass('hide'); 30822 } 30823 30824 _conIItem.clickTax = function(element) { 30825 $('#inventory-item-override-tax').toggleClass('hide'); 30826 } 30827 30828 _conIItem.setMarkup = function() { 30829 var jItem = $("#inventory-item-form"); 30830 var jpm = jItem.find('#Price_Markup_pct'); 30831 30832 var cost = UTIL.coalesceMoney(UTIL.cleanString(UTIL.coalesce(jItem.find('#Cost_mn:visible').val(), jItem.find('#Avg_Cost_mn:visible').text())).replace('$', '')); 30833 var price = UTIL.coalesceMoney(jItem.find('#Price_mn').val()); 30834 30835 if (cost > 0 && price > 0 && UTIL.isNumber(cost, true) && UTIL.isNumber(price, true) && cost > 0) { 30836 var pm = ( ( ( parseFloat(price) - parseFloat(cost) ) / parseFloat(cost) ) * 100).toFixed(0); 30837 jpm.text(pm + '%'); 30838 jpm.parent().find('small').removeClass('hide'); 30839 } else { 30840 jpm.text(''); 30841 jpm.parent().find('small').addClass('hide'); 30842 } 30843 } 30844 30845 _conIItem.vendorChanged = function(vendorDD) { 30846 var vid = $(vendorDD).val(); 30847 if (UTIL.isEmpty(vid)) { vid = ''; } 30848 30849 var options = $('#inventory-item-form').find('#Product_Line_id option'); 30850 30851 for (var i=1; i < options.length; i++) { 30852 if (vid === '') { 30853 options.eq(i).removeClass('hide'); 30854 } else if (vid == options.eq(i).attr('vendor_id')) { 30855 options.eq(i).removeClass('hide'); 30856 } else { 30857 options.eq(i).addClass('hide'); 30858 } 30859 } 30860 } 30861 30862 _conIItem.productLineChanged = function(plDD) { 30863 var vendorDD = $('#inventory-item-form').find('#Vendor_id'); 30864 30865 if (vendorDD.val() == '') { 30866 var vid = $(plDD).find('option:selected').attr('vendor_id'); 30867 vendorDD.val(vid); 30868 } 30869 } 30870 30871 _conIItem.populateCostBasis = function() { 30872 var jModal = $('#simplemodal-container');
30873 var jfrm = $('#inventory-item-form'); 30874 var ul = $(GLO.Inventory.Item.costXml); 30875 30876 if (jfrm.find('#Inventory_id').val() == ul.attr('inventory_id')) { 30877 var lis = ul.find('li'); 30878 var dt; 30879 var len = lis.length; 30880 if (len > 10) { len = 11; } 30881 30882 for (var i=0; i < len; i++) { 30883 dt = lis.eq(i).attr('create_dt'); 30884 30885 _conIItem.addCostRow(lis.eq(i).attr('cost_mn'), lis.eq(i).attr('count_dr'), i, lis.eq(i).attr('stock_id'), dt); 30886 } 30887 30888 var acost = UTIL.roundMoney(ul.attr('avg_cost_mn')); 30889 var tcount = UTIL.roundMoney(ul.attr('total_count_dr')); 30890 30891 jfrm.find('#Avg_Cost_mn').text('$' + acost); 30892 jfrm.find('#In_Stock_link').text(tcount); 30893 } 30894 30895 _conIItem.editCostBasis(); 30896 } 30897 30898 _conIItem.openCostPopup = function() { 30899 _loadingCostPopup = true; 30900 30901 $('#inventory-item-edit-cost').modal(); 30902 var jModal = $('#simplemodal-container').css({ "padding": "0" }).draggable({ "handle": "h2" }); 30903 30904 jModal.find('.btnSave a').css({ "border": "3px solid transparent" }); 30905 var frm = $("#inventory-item-form"); 30906 var trs = frm.find('.edit-cost-row'); 30907 30908 for (var i=1; i < trs.length; ++i) { 30909 trs.eq(i).remove(); 30910 } 30911 30912 if (jModal.height() < 10) { 30913 jModal.height(235); 30914 } 30915 30916 if (innerWidth >= 840) { 30917 jModal.width(800); 30918 jModal.css({ "font-size": "131%" }); 30919 jModal.find(':text').css({ "width": "100px", "letter-spacing": "1px" }); 30920 jModal.find('.btnAddProduct > a').css({ "padding-left": "10px", "padding-right": "10px", "letter-spacing": "1px", "font-weight": "bold" }); 30921 } else if (innerWidth >= 700) { 30922 jModal.width(640); 30923 jModal.css({ "font-size": "108%" }); 30924 jModal.find(':text').css({ "width": "80px", "letter-spacing": "1px" }); 30925 } else if (innerWidth >= 500) { 30926 jModal.width(500); 30927 } else { 30928 jModal.find('.item-edit-created').css({ "white-space": "normal" }); 30929 jModal.find('th.edit-cost-item-column').text('#'); 30930 jModal.find('input.item-edit-count').css({ "width": "40px" }); 30931
30932 if (jModal.width() < 300 || innerWidth < 400) { 30933 jModal.width(310).css({ "position": "relative", "left": "", "margin": "auto" }); 30934 } 30935 } 30936 30937 var iid = frm.find('#Inventory_id').val(); 30938 30939 if (!UTIL.isEmpty(iid)) { 30940 _lookupCostBasis(iid); 30941 } 30942 30943 if (_lookingUpCostBasis) { 30944 var throbber = $('<div style="text-align: center; min-width: 60px; min-height: 60px;">' + $('.loadingDiv').clone().find('img').css({ "margin": "50px auto", "min-width": "50px" }).outerHTML() + '</div>'); 30945 30946 jModal.find('#inventory-item-edit-cost-throbber').removeClass('hide').html(throbber); 30947 jModal.find('#inventory-item-edit-cost-table, #inventory-item-edit-cost-buttons').addClass('hide'); 30948 } else { 30949 _conIItem.openCostPopup2(); 30950 } 30951 30952 var h = jModal.find('#inventory-item-edit-cost').height(); 30953 var w = jModal.find('#inventory-item-edit-cost').width(); 30954 30955 $.modal.update(h,w); 30956 $(window).resize(); //= re-center simpleModal. 30957 _loadingCostPopup = false; 30958 } 30959 30960 _conIItem.openCostPopup2 = function(frm) { 30961 var jModal = $('#simplemodal-container #inventory-item-edit-cost'); 30962 jModal.find('#inventory-item-edit-cost-throbber').addClass('hide'); 30963 jModal.find('#inventory-item-edit-cost-table, #inventory-item-edit-cost-buttons').removeClass('hide'); 30964 30965 if (GLO.Inventory.Item.costXml) { 30966 GLO.Inventory.Item.populateCostBasis(); 30967 30968 var ul = $(GLO.Inventory.Item.costXml); 30969 var iid = ul.attr('inventory_id'); 30970 var cost = ul.attr('avg_cost_mn'); 30971 var cnt = ul.attr('total_count_dr'); 30972 30973 _updateCostBasis_ProductListRow(iid, cost, cnt); 30974 } else { 30975 var frm = $("#inventory-item-form"); 30976 var iid = frm.find('#Inventory_id').val(); 30977 30978 var cost = UTIL.coalesce(frm.find('#Avg_Cost_mn:visible').text().replace('$', ''), frm.find('#Cost_mn:visible').val()); 30979 30980 if (!UTIL.isNumber(cost, true)) { 30981 cost = ''; 30982 } else { 30983 cost = UTIL.roundMoney(cost); 30984 } 30985 30986 if (!UTIL.isEmpty(iid)) { 30987 var dt = $('#inventory-table tbody').find('tr#' + iid).attr('last_update_dt'); 30988 30989 if (UTIL.isDate(dt)) { 30990 dt = new Date(dt); 30991 dt = dt.toGloDate() + ' ' + dt.toGloTime(); 30992 jModal.find('.item-edit-created').text(dt).attr('create_dt', dt); 30993 } 30994 } 30995 30996 var cnt = UTIL.coalesce(frm.find('#In_Stock_dr:visible').val(), frm.find('#In_Stock_link:visible').text()); 30997 30998 if (UTIL.isNumber(cnt)) { cnt = UTIL.roundMoney(cnt); } 30999 31000 jModal.find('.item-edit-cost').val(cost); 31001 jModal.find('.item-edit-count').val(cnt); 31002 31003 _updateCostBasis_ProductListRow(iid, cost, cnt); 31004 } 31005 31006 _conIItem.editCostBasis(); 31007 } 31008 31009 function _updateCostBasis_ProductListRow(iid, cost, cnt) { 31010 var jtr = $('#inventory-table').find('tr#' + iid); 31011 31012 jtr.find('.item-cost').text(cost); 31013 jtr.find('.item-cost-edit input').val(cost); 31014 31015 //jtr.find('.new-in-stock-total').text(cnt); 31016 jtr.find('.current-in-stock').text(cnt); 31017 jtr.find('.item-in-stock').text(cnt); 31018 } 31019 31020 _conIItem.addCostRow = function(cost, count, row, stockId, createDate) { 31021 var pop = $('#simplemodal-container'); 31022 var tbl = pop.find('#inventory-item-edit-cost-table'); 31023 31024 var jrow = tbl.find('.edit-cost-row:last'); 31025 if (UTIL.isEmpty(row)) { row = tbl.find('.edit-cost-row').length; } 31026 31027 if (UTIL.isNumber(cost, true)) { 31028 cost = UTIL.roundMoney(cost); 31029 } else { 31030 cost = ''; 31031 } 31032 31033 if (UTIL.isNumber(count)) { 31034 count = UTIL.roundMoney(count); 31035 } else { 31036 count = ''; 31037 } 31038 31039 if (row === 0) { 31040 jrow.attr('stock_id', stockId); 31041 jrow.find('.item-edit-created').text(createDate).attr('create_dt', undefined); 31042 jrow.find('.item-edit-cost').val(cost); 31043 jrow.find('.item-edit-count').val(count); 31044 } else if (row > 9) { 31045 GLO.Popup.Warning('You have reached the limit of 10 cost-basis rows'); 31046 return false; 31047 } else {
31048 var newRow = jrow.clone(); 31049 var popHeight = pop.height(); 31050 31051 newRow.attr('stock_id', UTIL.cleanString(stockId)); 31052 newRow.find('.item-edit-created').text( UTIL.cleanString(createDate) ).attr('create_dt', undefined); 31053 newRow.find('.item-edit-cost').val(cost); 31054 newRow.find('.item-edit-count').val(count); 31055 31056 jrow.after(newRow); 31057 31058 if (popHeight === pop.height()) { 31059 $.modal.update(popHeight + 38); 31060 //tbl.height(tbl.height() + 38); 31061 } 31062 } 31063 31064 return true; 31065 } 31066 31067 _conIItem.removeCostRow = function(ev, icon) { 31068 var tr = $(icon).closest('tr'); 31069 31070 if (tr.closest('tbody').find('tr').length === 1) { 31071 tr.find('input').val(''); 31072 tr.find('.total-row-cost').text(''); 31073 } else { 31074 var pop = $('#simplemodal-container'); 31075 var popHeight = pop.height(); 31076 31077 tr.remove(); 31078 31079 if (popHeight === pop.height()) { $.modal.update(popHeight - 38); } 31080 } 31081 31082 _conIItem.editCostBasis(ev); 31083 } 31084 31085 _conIItem.closeCostBasis = function() { 31086 _lookingUpCostBasis = false; 31087 $.modal.close(); 31088 } 31089 31090 _lookupCostBasis = function(id) { 31091 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemCost?id=' + id; 31092 _lookingUpCostBasis = true; 31093 31094 var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false }) 31095 .success(function(data, textStatus, jqXHR) { 31096 _lookingUpCostBasis = false; 31097 31098 if ($(data).find('li').length > 0) { 31099 GLO.Inventory.Item.costXml = data; 31100 } 31101 31102 if ($('#inventory-item-edit-cost-throbber:visible').length === 1) { 31103 GLO.Inventory.Item.openCostPopup2(); 31104 } 31105 31106 var h = $('#inventory-item-edit-cost').height(); 31107 var w = $('#inventory-item-edit-cost').width(); 31108 $.modal.update(h,w); 31109 }) 31110 .error(function(jqXHR, textStatus, errorThrown) { 31111 _lookingUpCostBasis = false; 31112 }); 31113 } 31114 31115 _conIItem.editCostBasis = function(ev) { 31116 if (ev) { 31117 $('#inventory-item-edit-cost').find('.btnSave a').css({ "border": "3px solid Red" }); 31118 } 31119 31120 var tbl = $('#inventory-item-edit-cost-table'); 31121 var trs = tbl.find('tbody tr'); 31122 var cost, cnt, rowTotal, totalAvgCost = '', totalCost = 0, totalCount = 0, isValid = true; 31123 31124 for (var i=0; i < trs.length; i++) { 31125 cost = trs.eq(i).find('.item-edit-cost').val(); 31126 cnt = trs.eq(i).find('.item-edit-count').val(); 31127 31128 if (UTIL.isNumber(cost, true) && UTIL.isNumber(cnt)) { 31129 cost = parseFloat(cost); 31130 cnt = parseFloat(cnt); 31131 31132 totalCost += cost * cnt; 31133 totalCount += cnt; 31134 31135 rowTotal = UTIL.displayMoney(cost * cnt, false, false, true); 31136 trs.eq(i).find('.total-row-cost').text(rowTotal); 31137 } else { 31138 trs.eq(i).find('.total-row-cost').text(''); 31139 } 31140 } 31141 31142 if (isValid) { 31143 if (totalCount !== 0) { totalAvgCost = UTIL.displayMoney(totalCost/totalCount, false, false, true); } 31144 31145 totalCost = UTIL.displayMoney(totalCost, false, false, true); 31146 31147 if (totalCount % 1 === 0) { totalCount = parseInt(totalCount); } 31148 } else { 31149 totalAvgCost = totalCost = totalCount = ''; 31150 } 31151 31152 var tfoot = tbl.find('tfoot'); 31153 tfoot.find('#item-edit-avg-cost').text(totalAvgCost); 31154 tfoot.find('#item-edit-count-total').text(totalCount); 31155 tfoot.find('#item-edit-cost-total').text(totalCost); 31156 $(window).resize(); //= re-center simpleModal. 31157 } 31158 31159 _conIItem.saveCostBasis = function() { 31160 var pop = $('#inventory-item-edit-cost'); 31161 var trs = pop.find('.edit-cost-row'); 31162 var jBtn = pop.find('.btnSave'); 31163 var createDate, cost, count, xmlCost = ''; 31164 31165 for (var i=0; i < trs.length; i++) { 31166 cost = UTIL.cleanString(trs.eq(i).find('.item-edit-cost').val()); 31167 count = UTIL.cleanString(trs.eq(i).find('.item-edit-count').val()); 31168 31169 if (!UTIL.isNumber(cost, true) && cost !== '') { 31170 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + cost + '</b> ' + SA.Resource.IsNotValidCost + '</div>', function() { 31171 trs.eq(i).find('.item-edit-cost').focus(); 31172 }); 31173 return; 31174 } else if (!UTIL.isNumber(count) && count !== '') { 31175 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + count + '</b> ' + SA.Resource.IsNotValidCount + '. ' + SA.Resource.ItemMustBeNumberWarning + '.</div>', function() { 31176 trs.eq(i).find('.item-edit-count').focus(); 31177 }); 31178 return; 31179 /* 31180 } else if (cost === '' && count === '') { 31181 var htm = '<div style="padding: 10px; font-size: larger; font-weight: bold;">Count and cost are both empty</div>'; 31182 31183 GLO.Popup.Warning.open(htm, 'Empty Warning', function() { 31184 trs.eq(i).find('.item-edit-count').focus(); 31185 }); 31186 return; 31187 */ 31188 } 31189 31190 if (i === 0) { 31191 createDate = trs.eq(i).find('.item-edit-created').attr('create_dt'); 31192 31193 if (UTIL.isDate(createDate)) { 31194 createDate = " create_dt='" + createDate + "'"; 31195 } else { 31196 createDate = ''; 31197 } 31198 } else { 31199 createDate = ''; 31200 } 31201 31202 xmlCost += "<tr stock_id='" + UTIL.cleanString(trs.eq(i).attr('stock_id')) + "' cost_mn='" + cost + "' count_dr='" + count + "'" + createDate + "/>"; 31203 } 31204 31205 xmlCost = UTIL.htmlEncode(xmlCost); 31206 var inventoryId = $('#inventory-item-form #Inventory_id').val(); 31207 31208 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemCost'; 31209 GLO.UI.Form.beginProcessing(jBtn); 31210 31211 var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false, "data": { "cost_basis_xml": xmlCost, "inventory_id": inventoryId } }) 31212 .success(function(data, textStatus, jqXHR) { 31213 if (UTIL.Validate.hasPermissionError(data)) { return; } 31214 31215 GLO.Inventory.Item.updateItemRow(data, inventoryId); 31216
31217 var jItem = $('#inventory-item-form'); 31218 31219 if (data && inventoryId == jItem.find('#Inventory_id').val()) { 31220 $.modal.close(); //GLO.Popup.close(); 31221 31222 var tr = $(data); 31223 jItem.find('#Avg_Cost_mn').text( tr.find('.item-cost').text() ); 31224 31225 var inStock = tr.find('.item-in-stock').text(); 31226 jItem.find('#In_Stock_link').text(inStock); 31227 jItem.find('#In_Stock_dr').val(inStock); 31228 31229 if (tr.find('.inventory-item-cost-xml li').length > 0) { 31230 GLO.Inventory.Item.costXml = tr.find('.inventory-item-cost-xml').html(); 31231 } else { 31232 GLO.Inventory.Item.costXml = null; 31233 } 31234 31235 _conIItem.setMarkup(); 31236 } 31237 }) 31238 .error(function(jqXHR, textStatus, errorThrown) { 31239 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 31240 GLO.UI.Form.resetProcessing(); 31241 }); 31242 } 31243 31244 _conIItem.save = function() { 31245 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Item'; 31246 var frm = $('#inventory-item-form'); 31247 31248 if (UTIL.isEmpty(frm.find('#Name_vc').val())) { 31249 GLO.Popup.Warning(SA.Resource.PleaseEnterProductName, function() { $('#inventory-item-form #Name_vc').focus(); }); 31250 return; 31251 //} else if (UTIL.isEmpty(frm.find('#Vendor_id').val())) { 31252 // GLO.Popup.Warning('Please enter a brand name', function() { $('#inventory-item-form #Inventory_Vendor_id').focus(); }); 31253 // return; 31254 } 31255 31256 var iid = frm.find('#Inventory_id').val(); 31257 var inm = frm.find('#Name_vc').val(); 31258 var vid = frm.find('#Vendor_id').val(); 31259 var plineid = frm.find('#Product_Line_id').val(); 31260 31261 var sku = frm.find('#SKU_vc').val(); 31262 var upc = frm.find('#UPC_vc').val(); 31263 var itype = frm.find('#Inventory_Type_id').val(); 31264 31265 var unit = frm.find('#Unit_id').val(); 31266 var size = frm.find('#Size_dr').val(); 31267 31268 var webCode = frm.find('#Web_cd').val(); 31269 var rfl = frm.find('#For_Retail_fl').prop('checked'); 31270 var ifl = frm.find('#For_Internal_fl').prop('checked'); 31271 31272 var noTrackStock = !_isTrackStock(iid); 31273 var cost = frm.find('#Cost_mn:visible, #Avg_Cost_mn:visible').val(); 31274 31275 var price = UTIL.cleanString(frm.find('#Price_mn').val()); 31276 var eprice = UTIL.cleanString(frm.find('#Employee_Price_mn').val()); 31277 var instock = UTIL.coalesce(frm.find('#In_Stock_dr:visible').val(), frm.find('#In_Stock_link:visible').text()); 31278 var minstock = UTIL.cleanString(frm.find('#Minimum_Stock_dr').val()); 31279 31280 var tax = frm.find('#Tax_Rate_pct:visible').val(); 31281 var commission = frm.find('#Commission_pct:visible').val(); 31282 var desc = frm.find('#Description_vc').val(); 31283 // var itemImageFilename = $('#item-image-path').val(); 31284 // , "Item_Image_path_vc": itemImageFilename 31285 31286 if (!UTIL.isNumber(price, true) && price !== '') { 31287 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + price + '</b> ' + SA.Resource.IsNotValidPrice + '. ' + SA.Resource.PleaseEnterNumber + '.</div>', function() { 31288 $('#inventory-item-form').find('#Price_mn').focus(); 31289 }); 31290 31291 return; 31292 } else if (!UTIL.isNumber(eprice, true) && eprice !== '') { 31293 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + eprice + '</b> ' + SA.Resource.IsNotValidStaffPrice + '. ' + SA.Resource.PleaseEnterNumber + '.</div>', function() { 31294 $('#inventory-item-form').find('#Employee_Price_mn').focus(); 31295 }); 31296 31297 return; 31298 } else if (!UTIL.isNumber(minstock) && minstock !== '') { 31299 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + minstock + '</b> ' + SA.Resource.IsNotValidDesiredStockAmount + '. ' + SA.Resource.PleaseEnterNumber + '.</div>', function() { 31300 $('#inventory-item-form').find('#Minimum_Stock_dr').focus(); 31301 }); 31302 31303 return; 31304// } else if (!UTIL.isNumber(instock) && instock !== '' && UTIL.isEmpty(iid)) { 31305// GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + UTIL.cleanString(instock) + '</b> is not a valid in stock amount. Please enter a number.</div>', function() { 31306// $('#inventory-item-form').find('#In_Stock_dr').focus(); 31307// }); 31308// 31309// return; 31310 } else if (!UTIL.isNumber(cost, true) && cost !== '' && UTIL.isEmpty(iid)) { 31311 GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + UTIL.cleanString(cost) + '</b> ' + SA.Resource.IsNotValidCost + '. ' + SA.Resource.PleaseEnterNumber + '.</div>', function() { 31312 $('#inventory-item-form').find('#Cost_mn').focus(); 31313 }); 31314 31315 return; 31316 } 31317 31318 var jsonItem = { 31319 "Inventory_id": iid, "Name_vc": inm, "Vendor_id": vid, "Product_Line_id": plineid 31320 , "SKU_vc": sku, "UPC_vc": upc, "Inventory_Type_id": itype, "Unit_id": unit, "Size_dr": size 31321 , "Web_cd": webCode, "For_Retail_fl": rfl, "For_Internal_fl": ifl, "Do_Not_Track_Stock_fl": noTrackStock 31322 , "Cost_mn": cost, "Price_mn": price, "Employee_Price_mn": eprice 31323 , "Minimum_Stock_dr": minstock, "In_Stock_dr": instock, "Tax_Rate_pct": tax 31324 , "Commission_pct": commission, "Description_vc": desc 31325 }; 31326 31327 if (!UTIL.isEmpty(itype) && itype.substring(0, 1) === 'c') { 31328 jsonItem.Inventory_Type_id = ''; 31329 jsonItem.Category_id = itype.substring(1); 31330 } 31331 31332 _saveGiftCard(frm, jsonItem); 31333 _saveShelf(frm, jsonItem); 31334 31335 GLO.UI.Form.beginProcessing(frm.find('.btnSave')); 31336 31337 var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false, "data": jsonItem }) 31338 .success(function(data, textStatus, jqXHR) { 31339 if (UTIL.Validate.hasPermissionError(data)) { return; } 31340 31341 frm.find('.btnSave a').css({ "border": "3px solid transparent" }); 31342 31343 GLO.Inventory.Item.updateItemRow(data, iid); 31344 GLO.Inventory.setMaximumProductListRows(false); 31345 31346 if (!UTIL.isEmpty(jsonItem.Category_id) && UTIL.isEmpty(jsonItem.Inventory_Type_id)) { 31347 frm.find('#Inventory_Type_id').find('option[value="c' + jsonItem.Category_id + '"]').remove(); 31348 } 31349 31350 var isNewProduct = UTIL.isEmpty(iid); 31351 _setProductListFilterOnSave(data, isNewProduct); 31352 GLO.Inventory.updateHash('product-list'); 31353 }) 31354 .error(function(jqXHR, textStatus, errorThrown) { 31355 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 31356 GLO.UI.Form.resetProcessing(); 31357 }); 31358 } 31359 31360 function _saveGiftCard(jitem, jsonItem) { 31361 //= check if user just changed category (did not go to menu item: Create -> Gift Card, instead just went to Create -> Product or changing existing normal product) 31362 var jtype = jitem.find('#Inventory_Type_id option:selected');
31363 var defaultType = jtype.attr('default_type_id'), defaultCategory = jtype.attr('default_type_category_id'); 31364 31365 if (defaultType == 115 || defaultType == 116 || defaultCategory == 41) { 31366 jsonItem.Is_Gift_Card_fl = 1; 31367 } else { 31368 jsonItem.Is_Gift_Card_fl = 0; 31369 } 31370 31371 if (UTIL.parseBool(jsonItem.Is_Gift_Card_fl) && jitem.hasClass('is-gift-card')) { 31372 jsonItem.expire_days_sr = UTIL.coalesceInt(jitem.find('#Expire_Days_sr').val()); 31373 jsonItem.min_purchase_mn = UTIL.coalesceMoney(jitem.find('#Min_Purchase_mn').val()); 31374 31375 jsonItem.referrer_amount_mn = UTIL.coalesceMoney(jitem.find('#Referrer_Amount_mn').val()); 31376 var referrerInventoryId = jitem.find('#Referrer_Inventory_id').val(); 31377 31378 if (referrerInventoryId > 0) { 31379 jsonItem.referrer_inventory_id = referrerInventoryId; 31380 } 31381 31382 jsonItem.gift_only_fl = jitem.find('#Gift_Only_fl').prop('checked') 31383 jsonItem.new_client_only_fl = jitem.find('#New_Client_Only_fl').prop('checked'); 31384 } 31385 } 31386 31387 function _setProductListFilterOnSave(data, isNewProduct) { 31388 var jtbl = $('#inventory-table').find('tbody'); 31389 var productCount = jtbl.find('tr').length; 31390 31391 if (productCount < 20) { 31392 GLO.Inventory.filterClear(); 31393 return; 31394 } 31395 31396 //Step I: filter product list by new/updated item's brand so updated row + all other rows for this brand are displayed. 31397 var jfilter = $('#inventory-header-filter'); 31398 var coFilter = '', jd = $(data); 31399 31400 var pbrand = UTIL.cleanString(jd.find('.item-vendor').attr('vendor_id')); 31401 var pline = UTIL.cleanString(jd.find('.item-product-line').attr('product_line_id')); 31402 31403 if (pline !== '' && jtbl.find('.item-product-line[product_line_id="' + pline + '"]').length > 4) { 31404 coFilter = 'p' + pline; 31405 } else if (pbrand !== '') { 31406 coFilter = 'v' + pbrand; 31407 } 31408 31409 jfilter.find('#Filter_Company').find('option[value="' + coFilter + '"]').attr('selected', 'selected'); 31410 31411 //Step II: Filter Product List by Category/Type 31412 //Step II-A: Lookup 31413 var pcatetory = UTIL.cleanString(jd.find('.item-type-category').attr('type_category_id')); 31414 var psubcatetory = UTIL.cleanString(jd.find('.item-type').attr('type_id')); 31415 31416 var jfcategory = jfilter.find('#Filter_Category'); 31417 var fcategory = jfcategory.val(); 31418 31419 //Step II-B: if (category filter already exists) or (on saved product brand is empty but category exists) 31420 if (!UTIL.isEmpty(fcategory) || (UTIL.isEmpty(pbrand) && (pcatetory !== 'c' || psubcatetory !== 't'))) { 31421 var categoryProductCount = jtbl.find('.item-type-category[type_category_id="' + pcatetory + '"]').length; 31422 var subCategoryProductCount = jtbl.find('.item-type[type_id="' + psubcatetory + '"]').length; 31423 var categoryFilter = ''; 31424 31425 if (subCategoryProductCount > 9 || (subCategoryProductCount > 4 && categoryProductCount > 49) ) { 31426 categoryFilter = 't' + psubcatetory; 31427 } else if (categoryProductCount > 0) { 31428 categoryFilter = 'c' + pcatetory; 31429 } 31430 31431 jfcategory.find('option[value="' + categoryFilter + '"]').attr('selected', 'selected'); 31432 } 31433 31434 31435 //Step III: Filter Product List by Stock Level (gold package only): if has stock level filter + saved product does NOT match filter -> clear stock-level filter 31436 if (GLO.Info.providerPackage !== 4) { 31437 var jfStockLevel = jfilter.find('#Filter_Stock_Level'); 31438 var fStockLevel = jfStockLevel.val(); 31439 31440 if (!UTIL.isEmpty(fStockLevel)) { 31441 var amount = UTIL.coalesceFloat(jd.find('.item-in-stock').text()); 31442 var desired = UTIL.coalesceFloat(jd.find('.item-minimum-stock').text()); 31443 31444 if (!_isInStockLevel(fStockLevel, amount, desired)) { 31445 jfStockLevel.val(''); 31446 } 31447 } 31448 } 31449 31450 //Step IV: Wrap Up 31451 GLO.Inventory.filterOnChange(jfilter); 31452 } 31453 31454 function _isInStockLevel(filter, amount, desired) { 31455 if (filter === 'in' && amount > 0) { 31456 return true; 31457 } else if (filter === 'out' && amount <= 0) { 31458 return true; 31459 } else if (UTIL.isNumber(desired)) { 31460 desired = parseFloat(desired); 31461 31462 if (filter === 'low' && desired > amount) { 31463 return true; 31464 } else if (filter === 'high' && amount > desired) { 31465 return true; 31466 } 31467 } 31468 31469 return false; 31470 } 31471 31472 function _isTrackStock(inventoryId) { 31473 if (!UTIL.isEmpty(inventoryId)) { 31474 var tr = $('#inventory-table tbody tr#' + inventoryId); 31475 31476 if (GLO.Info.providerPackage === 4) { 31477 if (UTIL.isEmpty(inventoryId)) { 31478 return !GLO.Inventory.doNotTrackStock; 31479 } 31480 31481 if (tr.legth === 0) { 31482 return !GLO.Inventory.doNotTrackStock; 31483 } else { 31484 return UTIL.parseBool(tr.attr('track_stock_fl')); 31485 } 31486 } else if (tr.find('#Track_Stock_fl').prop('checked') || tr.find('#Track_Stock_fl:visible').length === 0) { 31487 return true; 31488 } 31489 } else { 31490 if (!GLO.Inventory.doNotTrackStock || GLO.Info.providerPackage == 2) { 31491 return true; 31492 } 31493 } 31494 31495 return false; 31496 } 31497 31498 _conIItem.updateItemRow = function(tr, inventoryId) { 31499 if (tr) {
31500 var tbl = $('#inventory-table tbody'); 31501 tr = $(tr); 31502 31503 //$.tablesorter.clearTableBody(tbl[0]); //requires latest version of tablesorter 31504 31505 if (!UTIL.isEmpty(inventoryId)) { 31506 tr.css({ "background-color": "rgba(255,255,0,.4)" }).attr('title', SA.Resource.ProductRecentlyUpdated); 31507 31508 var oldtr = tbl.find('tr#' + inventoryId).attr('id', 'UPDATED'); 31509 oldtr.after(tr); 31510 oldtr.addClass('hideXX').remove(); //~ the 'hide' is there so the row isn't re-displayed by the tablesorter plugin when a sort is performed after an update. 31511 } else { 31512 tr.css({ "background-color": "Pink" }).attr('title', SA.Resource.ProductRecentlyAdded); 31513 31514 tbl.find('.no-items').remove(); 31515 tbl.prepend(tr); 31516 } 31517 31518 //var isDoResort = true; //requires latest version of tablesorter 31519 //tbl.trigger('update', isDoResort); 31520 //tbl.trigger('updateAll', isDoResort); 31521 } 31522 } 31523 31524 _conIItem.openHelp_NotForSale = function(thisElement) { 31525 var ojInfo = GLO.UI.openHelp(thisElement); 31526 var jpop = ojInfo.getPopup(); 31527 31528 jpop.css({ "background-color": "#275264" }); 31529 jpop.find('h2').css({ "color": "#4F81BD", "background-color": "#222", "border-radius": "8px", "padding": "9px", "margin-top": "-20px", "margin-bottom": "15px", "margin-left": "-25px" }); 31530 31531 jpop.find('.msg p').remove(); 31532 window.setTimeout(function() { ojInfo.realign(); }, 100); 31533 } 31534 31535 _conIItem.remove = function() { 31536 var trs = $('#inventory-table').find('tbody .item-row-box input:checked').closest('tr:visible'); 31537 31538 if (trs.length == 0) { 31539 GLO.Popup.Warning(SA.Resource.PleaseCheckBox); 31540 } else { 31541 var h2 = 'Delete Product', msg = '', jnm, tr, ids = ''; 31542 if (trs.length > 1) { h2 += 's'; } 31543 31544 for (var i=0; i < trs.length; i++) { 31545 ids += trs.eq(i).attr('id') + ','; 31546 jnm = trs.eq(i).find('.item-name'); 31547 31548 msg += '<li style="float: none; line-height: 180%;">' + UTIL.coalesce(jnm.attr('title'), jnm.text()) + '</li>'; 31549 } 31550 31551 ids = ids.substring(0, ids.length-1); 31552 msg = '<div> <h2>' + h2 + '?</h2> <ul style="text-align: center; margin-left: 0; margin-top: 10px; font-weight: bold; font-size: large;">' + msg + '</ul> </div>'; 31553 31554 var ojpop = new GLO.Popup.Confirm(msg, function() { 31555 GLO.Inventory.Item.removeConfirmed(ids); 31556 }); 31557 31558 var jpop = ojpop.getPopup(); 31559 31560 if (jpop.height() > innerHeight * .9) { 31561 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 31562 ojpop.realign(); 31563 } 31564 } 31565 } 31566 31567 _conIItem.removeProduct = function() { 31568 var j = $('#inventory-item-form'); 31569 var id = j.find('#Inventory_id').val(); 31570 var nm = j.find('#Name_vc').val() 31571 31572 if (GLO.Info.isMobile()) { 31573 var msg = 'Delete the product?'; 31574 } else { 31575 var msg = 'Are you sure you want to delete the product?'; 31576 } 31577 31578 msg = '<div class="friendly-msg2">' + msg + '<br/> <b style="color: #4F81BD;">' + nm + '</b></div>'; 31579 msg = '<div> <h2 class="friendly-msg2">' + SA.Resource.Delete + ' ' + SA.Resource.Product + '?</h2>' + msg + '</div>'; 31580 31581 var btn = j.find('.btnDelete'); 31582 GLO.UI.Form.beginProcessing(btn); 31583 31584 var fnYes = function() { GLO.Inventory.Item.removeConfirmed(id); }; 31585 var fnNo = function() { GLO.UI.Form.resetProcessing(btn); } 31586 31587 var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup(); 31588 31589 if (jpop.height() > innerHeight * .9) { 31590 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 31591 } 31592 } 31593 31594 _conIItem.removeConfirmed = function(ids) { 31595 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemDelete'; 31596 //if (UTIL.isEmpty(ids)) { ids = $('#inventory-item-edit #Inventory_id').val(); } 31597 GLO.UI.Form.beginProcessing( $('#inventory-item-edit .btnDelete, #inventory-product-list-buttons .btnDelete') ); 31598
31599 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "ids": ids } }) 31600 .success(function(data, textStatus, jqXHR) { 31601 if (UTIL.Validate.hasPermissionError(data)) { return; } 31602 31603 var arr = ids.split(','); 31604 var tbody = $('#inventory-table tbody'); 31605 31606 for (var i = 0; i < arr.length; i++) { 31607 tbody.find('tr#' + arr[i]).attr('id', 'REMOVED').addClass('hideXX').remove(); //~ the 'hide' is there so the row isn't re-displayed by the tablesorter plugin when a sort is performed after an update. 31608 } 31609 31610 GLO.Inventory.setMaximumProductListRows(false); 31611 GLO.Inventory.setFooter(0); 31612 GLO.Inventory.updateHash('product-list'); 31613 }) 31614 .error(function(jqXHR, textStatus, errorThrown) { 31615 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 31616 GLO.UI.Form.resetProcessing(); 31617 }); 31618 } 31619 31620 _conIItem.selectAll = function(checkbox) { 31621 var jcheckbox = $(checkbox); 31622 var isChecked = jcheckbox.prop('checked'); 31623 var tbl = jcheckbox.closest('table'); 31624 31625 tbl.find('.item-row-box:visible input:checkbox').each(function() { 31626 $(this).prop('checked', isChecked); 31627 }); 31628 } 31629 31630 _conIItem.viewHistory = function(event) { 31631 var uri = GLO.Link.Page.Provider.Home + 'reports/inventory/#tab=product-history&id=' + GLO.Uri.hash('id'); 31632 31633 if (event.ctrlKey) { 31634 var childWindow = UI.openChildWindow(uri, '', true); 31635 } else { 31636 document.location = uri; 31637 } 31638 } 31639 31640 _conIItem.addItemImage = function() { 31641 var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemImage'; 31642 // GLO.UI.Form.beginProcessing(); 31643 var frm = $('#inventory-item-form'); 31644 var iid = frm.find('#Inventory_id').val(); 31645 var itemImageFilename = $('#item-image-path').val(); 31646 31647 var jsonData = { 31648 "Inventory_id": iid, "Item_Image_path_vc": itemImageFilename 31649 }; 31650 31651 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData}) 31652 .success(function(data, textStatus, jqXHR) { 31653 if (UTIL.Validate.hasPermissionError(data)) { return; } 31654 GLO.Inventory.Item.getItemImages(iid); 31655 31656 }) 31657 .error(function(jqXHR, textStatus, errorThrown) { 31658 new GLO.Popup.Error('Unable to save image at this time. Please try again later.'); 31659 GLO.UI.Form.resetProcessing(); 31660 }); 31661 } 31662 31663 _conIItem.removeItemImage = function(itemImageId) { 31664 var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveItemImage'; 31665 // GLO.UI.Form.beginProcessing(); 31666 31667 var frm = $('#inventory-item-form'); 31668 var iid = frm.find('#Inventory_id').val(); 31669 31670 var jsonData = { 31671 "Inventory_id": iid, 31672 "Inventory_Image_id": itemImageId 31673 }; 31674 31675 31676 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData}) 31677 .success(function(data, textStatus, jqXHR) { 31678 if (UTIL.Validate.hasPermissionError(data)) { return; } 31679 GLO.Inventory.Item.getItemImages(iid); 31680 31681 }) 31682 .error(function(jqXHR, textStatus, errorThrown) { 31683 new GLO.Popup.Error('Unable to remove image at this time. Please try again later.'); 31684 GLO.UI.Form.resetProcessing(); 31685 }); 31686 } 31687 31688 _conIItem.setPrimaryItemImage = function(itemImageId) { 31689 var uri = GLO.Link.Page.Provider.Home + 'Inventory/SetPrimaryItemImage'; 31690 // GLO.UI.Form.beginProcessing(); 31691 31692 var frm = $('#inventory-item-form'); 31693 var iid = frm.find('#Inventory_id').val(); 31694 31695 var jsonData = { 31696 "Inventory_id": iid, 31697 "Inventory_Image_id": itemImageId 31698 }; 31699 31700 31701 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData}) 31702 .success(function(data, textStatus, jqXHR) { 31703 if (UTIL.Validate.hasPermissionError(data)) { return; } 31704 GLO.Inventory.Item.getItemImages(iid); 31705 31706 }) 31707 .error(function(jqXHR, textStatus, errorThrown) { 31708 new GLO.Popup.Error('Unable to set main image at this time. Please try again later.'); 31709 GLO.UI.Form.resetProcessing(); 31710 }); 31711 } 31712 31713 _conIItem.launchImageUpload = function(event) { 31714 $('#inventory-edit-image-upload-container').modal(); 31715 var jModal = $('#simplemodal-container #inventory-edit-image-upload-container');
31716 var h = jModal.find('#inventory-edit-image-upload-container').height(); 31717 var w = jModal.find('#inventory-edit-image-upload-container').width(); 31718 31719 $.modal.update(h,w); 31720 $(window).resize(); 31721 31722 if (GLO.Info.isMobile()) { 31723 $('#simplemodal-container').draggable({disable:true}); 31724 } 31725 } 31726 31727 _conIItem.launchManageImages= function(event) { 31728 31729 GLO.UI.loadBulkitCss(); 31730 31731 $('#inventory-manage-images-container').modal(); 31732 var jModal = $('#simplemodal-container #inventory-manage-images-container'); 31733 var h = $(window).height() * 0.8; 31734 var w = $(window).width() * 0.8; 31735 31736 $.modal.update(h,w); 31737 $(window).resize(); 31738 $('.modalCloseImg').css("margin-top","20px"); 31739 $('.modalCloseImg').css("margin-right","20px"); 31740 $('.modalCloseImg').on("click",function() { GLO.Inventory.Item.closeManageImages(); }); 31741 31742 if (GLO.Info.isMobile()) { 31743 $('#simplemodal-container').draggable({disable:true}); 31744 } 31745 $('#simplemodal-container').css("overflow-y","auto"); 31746 31747 var frm = $('#inventory-item-form'); 31748 var iid = frm.find('#Inventory_id').val(); 31749 31750 GLO.Inventory.Item.getItemImages(iid); 31751 } 31752 31753 _conIItem.closeManageImages = function() { 31754 31755 $('.modalCloseImg').off("click"); 31756 GLO.UI.removeBulkitCss(); 31757 } 31758 31759 31760 _conIItem.uploadImageAndResize = function () { 31761 //define the width to resize e.g 800px 31762 var resize_width = 800;//without px 31763 31764 //get the image selected 31765 var item = document.querySelector('#uploader').files[0]; 31766 31767 //create a FileReader 31768 var reader = new FileReader(); 31769 31770 //image turned to base64-encoded Data URI. 31771 reader.readAsDataURL(item); 31772 reader.name = item.name;//get the image's name 31773 reader.size = item.size; //get the image's size 31774 reader.onload = function(event) { 31775 var img = new Image();//create a image 31776 img.src = event.target.result;//result is base64-encoded Data URI 31777 img.name = event.target.name;//set name (optional) 31778 img.size = event.target.size;//set size (optional) 31779 img.onload = function(el) { 31780 var elem = document.createElement('canvas');//create a canvas 31781 31782 //scale the image to 800 (width) and keep aspect ratio 31783 var scaleFactor = resize_width / el.target.width; 31784 elem.width = resize_width; 31785 elem.height = el.target.height * scaleFactor; 31786 31787 //draw in canvas 31788 var ctx = elem.getContext('2d'); 31789 ctx.drawImage(el.target, 0, 0, elem.width, elem.height); 31790 31791 //get the base64-encoded Data URI from the resize image 31792 var srcEncoded = ctx.canvas.toDataURL('image/png', 1); 31793 31794 //assign it to thumb src 31795 document.querySelector('#item-image').src = srcEncoded; 31796 31797 //image modal 31798 $.modal.update(1000,1000); 31799 $(window).resize(); 31800 $('#simplemodal-container').css("overflow-y","auto"); 31801 $('#simplemodal-container').draggable(); 31802 $('.modalCloseImg').css("margin-top","20px"); 31803 $('.modalCloseImg').css("margin-right","20px"); 31804 31805 //hide upload button and show crop button 31806 // $('#uploaderLabel').addClass('hide'); 31807 // $('#uploader').addClass('is-hidden'); 31808 // $('#btnUploadResize').addClass('is-hidden'); 31809 $('#btnCrop').removeClass('is-hidden'); 31810 // $('#previewLabel').removeClass('hide'); 31811 // $('.image-preview').removeClass('hide'); 31812 31813 //init cropper js 31814 var $image = $('#item-image'); 31815 31816 $image.cropper({ 31817 aspectRatio: 1 / 1, 31818 preview:'.image-preview', 31819 crop: function(event) { 31820 // console.log(event.detail.x); 31821 // console.log(event.detail.y); 31822 // console.log(event.detail.width); 31823 // console.log(event.detail.height); 31824 // console.log(event.detail.rotate); 31825 // console.log(event.detail.scaleX); 31826 // console.log(event.detail.scaleY); 31827 } 31828 }); 31829 31830 $image.on({ 31831 ready: function (e) { 31832 console.log(e.type); 31833 var cropBoxData = $image.cropper('getCropBoxData'); 31834 cropBoxData.width = 800; 31835 cropBoxData.height = 800; 31836 $image.cropper('setCropBoxData', cropBoxData); 31837 }, 31838 cropstart: function (e) { 31839 console.log(e.type, e.detail.action); 31840 }, 31841 cropmove: function (e) { 31842 console.log(e.type, e.detail.action); 31843 }, 31844 cropend: function (e) { 31845 console.log(e.type, e.detail.action); 31846 }, 31847 crop: function (e) { 31848 console.log(e.type); 31849 }, 31850 zoom: function (e) { 31851 console.log(e.type, e.detail.ratio); 31852 } 31853 }); 31854 31855 31856 /*Now you can send "srcEncoded" to the server and 31857 convert it to a png o jpg. Also can send 31858 "el.target.name" that is the file's name.*/ 31859 31860 /*Also if you want to download tha image use this*/ 31861 /* 31862 var a = document.createElement("a"); //Create <a> 31863 a.href = srcEncoded; //set srcEncoded as src 31864 a.download = "myimage.png"; //set a name for the file 31865 a.click(); 31866 31867 */ 31868 } 31869 } 31870 } 31871
31872 _conIItem.cropImage = function() { 31873 31874 var $image = $('#item-image'); 31875 31876 // Get the Cropper.js instance after initialized 31877 var cropper = $image.data('cropper'); 31878 var cropperData = cropper.getData(); 31879 var srcCroppedEncoded = cropper.getCroppedCanvas().toDataURL('image/png', 1); 31880 $image.cropper('destroy'); 31881 31882 document.querySelector('#item-image').src = srcCroppedEncoded; 31883 31884 //hide crop button and show save button 31885 $('#btnCrop').addClass('is-hidden'); 31886 $('#btnSaveItemImage').removeClass('is-hidden'); 31887 $('#btnSaveItemImage').on("click",function() { GLO.Inventory.Item.saveImage(srcCroppedEncoded,cropperData.width); }); 31888 31889 } 31890 31891 //used by product page to upload product image for store 31892 _conIItem.saveImage = function(data,width) { 31893 31894 //remove the attached handler 31895 $('#btnSaveItemImage').off("click"); 31896 31897 var jcontainer = $('#uploader'); 31898 31899 //reset error 31900 $('#itemImageUploadErrorMessage').addClass('is-hidden'); 31901 31902 var fnCallback = function(jcontainer, fileName, imgId, imgSize) { 31903 if (fileName!=null && fileName.length > 0) { 31904 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName; 31905 // console.log(img_path); 31906 31907 //clear the image display 31908 document.querySelector('#item-image').src =''; 31909 $('#btnSaveItemImage').addClass('is-hidden'); 31910 // $('#btnCloseModal').addClass('is-hidden'); 31911 31912 //set hidden field value 31913 $('#item-image-path').val(fileName); 31914 //close the modal 31915 // $('.simplemodal-close').click(); 31916 31917 //display the image preview 31918 // $('.item-existing-image-preview-container').removeClass('hide'); 31919 // $('.item-existing-image-preview').attr("src",img_path); 31920 // $('.item-image-fullsize-link').attr("href",img_path); 31921 31922 GLO.Inventory.Item.addItemImage(); 31923 } 31924 else { 31925 //display error 31926 $('#itemImageUploadErrorMessage').removeClass('is-hidden'); 31927 } 31928 } 31929 31930 if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) { 31931 return true; 31932 } 31933 } 31934 31935 _conIItem.removeImageAskConfirmation= function(itemImageId) { 31936 31937 if (GLO.Info.isMobile()) { 31938 var msg = 'Remove the image?'; 31939 } else { 31940 var msg = 'Are you sure you want to remove the image?'; 31941 } 31942 31943 msg = '<div class="friendly-msg2">' + msg + '</div>'; 31944 msg = '<div> <h2 class="friendly-msg2">Remove Image?</h2>' + msg + '</div>'; 31945 31946 var fnYes = function() { GLO.Inventory.Item.removeImage(itemImageId); }; 31947 var fnNo = function() { GLO.UI.Form.resetProcessing(); } 31948 31949 var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup(); 31950 31951 if (jpop.height() > innerHeight * .9) { 31952 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 31953 } 31954 } 31955 31956 _conIItem.mainImageAskConfirmation= function(itemImageId) { 31957 31958 if (GLO.Info.isMobile()) { 31959 var msg = 'Change the main image?'; 31960 } else { 31961 var msg = 'Are you sure you want to change the main image?'; 31962 } 31963 31964 msg = '<div class="friendly-msg2">' + msg + '</div>'; 31965 msg = '<div> <h2 class="friendly-msg2">Change Main Product Image?</h2>' + msg + '</div>'; 31966 31967 var fnYes = function() { GLO.Inventory.Item.setPrimaryItemImage(itemImageId); }; 31968 var fnNo = function() { GLO.UI.Form.resetProcessing(); } 31969 31970 var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup(); 31971 31972 if (jpop.height() > innerHeight * .9) { 31973 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 31974 } 31975 } 31976 31977 _conIItem.removeImage = function(itemImageId) { 31978 31979 GLO.Inventory.Item.removeItemImage(itemImageId); 31980 } 31981 31982 _conIItem.getItemImages = function(inventoryId) { 31983 var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemImages?id=' + inventoryId; 31984 31985 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 31986 .done(function(data, textStatus, jqXHR) { 31987 window.onbeforeunload = null; 31988 if(data!=null && data!== '') { 31989 var itemImages = data; 31990 if (itemImages.length > 0) {
31991 generateItemImagesGrid(itemImages); 31992 } 31993 else { 31994 //display blank state 31995 generateItemImagesGridBlankState(); 31996 } 31997 } else { 31998 new GLO.Popup.Error('Could not get the product images'); 31999 } 32000 }) 32001 .fail(function(jqXHR, textStatus, errorThrown) { 32002 GLO.UI.Form.resetProcessing(); 32003 new GLO.Popup.Error('Could not get the product images'); 32004 }); 32005 } 32006 32007 //render the item images grid 32008 var generateItemImagesGrid = function(itemImages) { 32009 var itemImagesGrid = $('#item-images-grid'); 32010 var productPlaceholderImage = 'product-image-placeholder.png'; 32011 itemImagesGrid.html(""); 32012 32013 itemImages.forEach(function(itemImage) { 32014 32015 var productDescPreview = ''; 32016 var img_path=GLO.Data.cdnDirectory + 'upload-folder/' + productPlaceholderImage; 32017 32018 if (itemImage.ImagePath.length > 0) { 32019 img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImage.ImagePath; 32020 } 32021 32022 var imageCardEl = document.createElement("div"); 32023 imageCardEl.className = "column is-one-fifth-desktop is-one-quarter-tablet"; 32024 imageCardEl.innerHTML = (`<div class="card" data-id="${itemImage.ItemImageId}"> 32025 <div class="card-image"> 32026 <figure class="image is-square"> 32027 <img src="${img_path}" alt=""> 32028 </figure> 32029 <div class="card-content is-overlay is-clipped is-pulled-right is-pulled-top ${itemImage.IsPrimary ? '':'is-hidden'}"> 32030 <span class="tag is-info"> 32031 Main Image 32032 </span> 32033 </div> 32034 </div> 32035 <footer class="card-footer"> 32036 <a class="card-footer-item"> 32037 <a href="#" class="card-footer-item is-size-7 ${itemImage.IsPrimary ? 'is-hidden':''}" onclick="GLO.Inventory.Item.mainImageAskConfirmation(${itemImage.ItemImageId})">Set as Main</a> 32038 <a href="#" class="card-footer-item has-text-danger is-size-7" onclick="GLO.Inventory.Item.removeImageAskConfirmation(${itemImage.ItemImageId})">Remove</a> 32039 </a> 32040 </footer> 32041 </div>`); 32042 32043 itemImagesGrid.append(imageCardEl); 32044 }); 32045 } 32046 32047 var generateItemImagesGridBlankState = function() { 32048 32049 var itemImagesGrid = $('#item-images-grid'); 32050 itemImagesGrid.html(""); 32051 var imageCardEl = document.createElement("div"); 32052 imageCardEl.className = "column"; 32053 imageCardEl.innerHTML = (`<span id="item-images-grid-blank-state" class="is-size-3 has-text-grey">Click Upload an image to add a new product image</span>`); 32054 itemImagesGrid.append(imageCardEl); 32055 } 32056 32057 _conIItem.Options = (function() { 32058 function _conIItemOptions() { } 32059 const _MAX_ITEM_OPTIONS = 3; 32060 var _itemId; 32061 var _itemOptionTypesArray = [{"attribute_id":"1","attribute_type_vc":"Choose One - Text"},{"attribute_id":"2","attribute_type_vc":"Choose One - Color"}]; 32062 var _itemOptionsArray = []; 32063 var _itemVariantsArray = []; 32064 var _itemSelectedItemOptionColorSwatch; 32065 var _itemSelectedVariant; 32066 32067 var _tagsInputOptions = { 32068 allowDuplicates: false, 32069 caseSensitive: false, 32070 clearSelectionOnTyping: false, 32071 closeDropdownOnItemSelect: true, 32072 delimiter: ',', 32073 freeInput: true, 32074 highlightDuplicate: true, 32075 highlightMatchesString: true, 32076 itemValue: undefined, 32077 itemText: undefined, 32078 maxTags: 20, 32079 maxChars: 99, 32080 minChars: 1, 32081 noResultsLabel: 'No results found', 32082 placeholder: '', 32083 removable: true, 32084 searchMinChars: 1, 32085 searchOn: 'text', 32086 selectable: true, 32087 source: undefined, 32088 tagClass: 'is-link', 32089 trim: true 32090 }; 32091 32092 var getItemOptionCsv = function(itemOption) { 32093 var valueArray = []; 32094 itemOption.ItemAttributeValues.forEach(iov => { 32095 valueArray.push(iov.Value); 32096 }); 32097 var csv = ''; 32098 csv = valueArray.join(','); 32099 return csv; 32100 } 32101 32102 //render the item images grid 32103 var generateItemImagePickerGrid = function(itemImages) { 32104 var itemImagesGrid = $('#item-variation-image-choices'); 32105 var productPlaceholderImage = 'product-image-placeholder.png'; 32106 itemImagesGrid.html(""); 32107 32108 itemImages.forEach(function(itemImage) { 32109 32110 var productDescPreview = ''; 32111 var img_path=GLO.Data.cdnDirectory + 'upload-folder/' + productPlaceholderImage; 32112 32113 if (itemImage.ImagePath.length > 0) { 32114 img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImage.ImagePath; 32115 } 32116 32117 var imageCardEl = document.createElement("div"); 32118 imageCardEl.className = "column is-one-fifth-desktop is-one-quarter-tablet"; 32119 imageCardEl.innerHTML = (`<div class="card" data-id="${itemImage.ItemImageId}"> 32120 <div class="card-image"> 32121 <figure class="image is-square"> 32122 <img src="${img_path}" alt=""> 32123 </figure> 32124 <div class="card-content is-overlay is-clipped is-pulled-right is-pulled-top ${itemImage.IsPrimary ? '':'is-hidden'}"> 32125 <span class="tag is-info"> 32126 Main Image 32127 </span> 32128 </div> 32129 </div> 32130 <footer class="card-footer"> 32131 <a class="card-footer-item"> 32132 <a href="#" class="card-footer-item has-text-danger is-size-7" onclick="GLO.Inventory.Item.Options.setImageForVariation(${itemImage.ItemImageId},'${itemImage.ImagePath}')">Select</a> 32133 </a> 32134 </footer> 32135 </div>`); 32136
32137 itemImagesGrid.append(imageCardEl); 32138 }); 32139 } 32140 32141 var generateItemImagePickerGridBlankState = function() { 32142 32143 var itemImagesGrid = $('#item-variation-image-choices'); 32144 itemImagesGrid.html(""); 32145 var imageCardEl = document.createElement("div"); 32146 imageCardEl.className = "column"; 32147 imageCardEl.innerHTML = (`<span id="item-images-grid-blank-state" class="is-size-3 has-text-grey">Please go to product details and upload images for product</span>`); 32148 itemImagesGrid.append(imageCardEl); 32149 } 32150 32151 var attachBulmaTagsInput = function(elem) { 32152 if (typeof elem.BulmaTagsInput == 'undefined') { 32153 32154 new BulmaTagsInput(elem,_tagsInputOptions); 32155 32156 //attach handlers 32157 elem.BulmaTagsInput().on('before.remove', function(data) { 32158 console.log(data); 32159 return true; 32160 }); 32161 elem.BulmaTagsInput().on('after.add', function(data) { 32162 console.log(data); 32163 return true; 32164 }); 32165 } 32166 } 32167 32168 var generateItemVariationsBlankState = function() { 32169 32170 var itemVariationsList = $('#variations-list'); 32171 32172 var itemVariationsInner = itemVariationsList.find('.item-variations-inner'); 32173 itemVariationsInner.html("<p>Product variations will be auto-generated based on the product options added.</p>"); 32174 32175 } 32176 32177 var doVariationsHaveInventoryIds = function() { 32178 32179 var retVal = false; 32180 32181 if (_itemVariantsArray == null || typeof _itemVariantsArray == 'undefined' || _itemVariantsArray.length == 0) { 32182 return false; 32183 } 32184 var variantsWithInventoryIds = _itemVariantsArray.filter(iv=> iv.VariantInventoryId > 0); 32185 if (variantsWithInventoryIds.length > 0) { 32186 retVal = true; 32187 } 32188 32189 return retVal; 32190 } 32191 32192 _conIItemOptions.init = function(itemId) { 32193 _itemId = itemId; 32194 GLO.Inventory.Item.Options.getItemOptions(_itemId); 32195 GLO.Inventory.Item.Options.getItemVariations(_itemId); 32196 } 32197 32198 _conIItemOptions.getOptionType = function(optionTypeName) { 32199 var selectedOptionType; 32200 for (var i = 0; i < _itemOptionTypesArray.length; i++) { 32201 if (_itemOptionTypesArray[i].attribute_type_vc == optionTypeName || _itemOptionTypesArray[i].attribute_id == optionTypeName){ 32202 selectedOptionType = _itemOptionTypesArray[i]; 32203 break; 32204 } 32205 } 32206 32207 return selectedOptionType; 32208 } 32209 32210 _conIItemOptions.generateNewOption = function(elem) { 32211 32212 var itemOptionsList = $('#options-list'); 32213 32214 var newOptionEl = document.createElement("div"); 32215 newOptionEl.className = "box m-3 item-option"; 32216 newOptionEl.innerHTML = (`<div class="option-edit"> 32217 <div class="columns"> 32218 <div class="column is-half"> 32219 <div class="field"> 32220 <label class="label is-pulled-left">Name</label> 32221 <div class="control required option-name"> 32222 <input class="input item-option-name" placeholder="Option name for store display e.g. Size"> 32223 </div> 32224 </div> 32225 </div> 32226 <div class="column is-half"> 32227 <div class="field"> 32228 <label class="label is-pulled-left">Type</label> 32229 <div class="control required option-type"> 32230 <div class="select is-fullwidth"> 32231 <select class="select-option-type" onchange="GLO.Inventory.Item.Options.changeOptionType(this)"> 32232 <option value="1">Choose One - Text</option> 32233 <option value="2">Choose One - Color</option> 32234 </select> 32235 </div> 32236 </div> 32237 </div> 32238 </div> 32239 </div> 32240 <div class="columns"> 32241 <div class="column"> 32242 <div class="field"> 32243 <label class="label is-pulled-left">Values</label> 32244 </div> 32245 </div> 32246 </div> 32247 <div class="option-edit-fields"> 32248 <div class="columns"> 32249 <div class="column"> 32250 <div class="field"> 32251 <div class="control required text-option-value"> 32252 <div class="bulma-tags"> 32253 <input class="input item-option-value" type="tags" placeholder="Add values e.g. Small, Medium, Large"> 32254 </div> 32255 </div> 32256 </div> 32257 </div> 32258 </div> 32259 </div> 32260 </div>
32261 <div class="option-preview is-hidden"> 32262 <!-- this is the preview of the option --> 32263 </div> 32264 <div class="columns option-actions"> 32265 <div class="column is-one-fifth"> 32266 <div class="buttons is-justify-content-left"> 32267 <button class="button is-danger has-text-weight-normal is-light" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button> 32268 </div> 32269 </div> 32270 <div class="column"> 32271 32272 </div> 32273 <div class="column is-one-third"> 32274 <div class="buttons is-justify-content-right"> 32275 <button class="button has-text-weight-normal" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button> 32276 <button class="button is-info has-text-weight-normal" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button> 32277 <button class="button is-info has-text-weight-normal is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Edit</button> 32278 </div> 32279 </div> 32280 </div>`); 32281 32282 $(newOptionEl).insertBefore($('.create-new-option')); 32283 32284 GLO.Inventory.Item.Options.checkOptionThreshold(); 32285 32286 //attach tags input 32287 var tagEl = $(newOptionEl).find('input[type="tags"]')[0]; 32288 attachBulmaTagsInput(tagEl); 32289 32290 } 32291 32292 _conIItemOptions.checkOptionThreshold = function() { 32293 32294 var itemOptionsAdded = $('#options-list').find('.item-option').length; 32295 if (itemOptionsAdded < _MAX_ITEM_OPTIONS) { 32296 $('.create-new-option').removeClass("is-hidden"); 32297 } 32298 else { 32299 $('.create-new-option').addClass("is-hidden"); 32300 } 32301 } 32302 32303 _conIItemOptions.getItemOptions = function(inventoryId) { 32304 var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemAttributes?id=' + inventoryId; 32305 32306 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 32307 .done(function(data, textStatus, jqXHR) { 32308 window.onbeforeunload = null; 32309 if(data!=null && data!== '') { 32310 var _itemOptionsArray = JSON.parse(data.data); 32311 if (_itemOptionsArray.length > 0) { 32312 GLO.Inventory.Item.Options.generateItemOptionsList(_itemOptionsArray); 32313 } 32314 else { 32315 //display blank state 32316 //which it does by default 32317 } 32318 } else { 32319 new GLO.Popup.Error('Could not get the product options. Please refresh page and try again.'); 32320 } 32321 }) 32322 .fail(function(jqXHR, textStatus, errorThrown) { 32323 GLO.UI.Form.resetProcessing(); 32324 new GLO.Popup.Error('Could not get the product options. Please refresh page and try again.'); 32325 }); 32326 } 32327 32328 _conIItemOptions.getItemVariations = function(inventoryId) { 32329 var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemVariations?id=' + inventoryId; 32330 32331 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 32332 .done(function(data, textStatus, jqXHR) { 32333 window.onbeforeunload = null; 32334 if(data!=null && data!== '') { 32335 _itemVariantsArray = JSON.parse(data.data); 32336 if (_itemVariantsArray.length > 0) { 32337 GLO.Inventory.Item.Options.generateItemVariationsList(_itemVariantsArray); 32338 } 32339 else { 32340 //display blank state 32341 generateItemVariationsBlankState(); 32342 } 32343 } else { 32344 new GLO.Popup.Error('Could not get the product variants. Please refresh page and try again.'); 32345 } 32346 }) 32347 .fail(function(jqXHR, textStatus, errorThrown) { 32348 GLO.UI.Form.resetProcessing(); 32349 new GLO.Popup.Error('Could not get the product variants. Please refresh page and try again.'); 32350 }); 32351 } 32352 32353 var resetItemOptionsList = function() { 32354 32355 var itemOptionsList = $('#options-list'); 32356 itemOptionsList.html(""); 32357 32358 var addNewOptionEl = document.createElement("div"); 32359 addNewOptionEl.className="box m-3 create-new-option"; 32360 addNewOptionEl.innerHTML=(` 32361 <div class="buttons is-justify-content-center"> 32362 <button class="button is-light" onclick="GLO.Inventory.Item.Options.addNewOptionAskConfirmation(this)">Add New option</button> 32363 </div>`); 32364 32365 itemOptionsList.append(addNewOptionEl); 32366 } 32367 32368 32369 _conIItemOptions.generateItemOptionsList = function(itemOptions) { 32370 32371 resetItemOptionsList(); 32372 32373 itemOptions.forEach(itemOption => { 32374 if (itemOption.AttributeTypeCode == 1) { 32375 GLO.Inventory.Item.Options.generateTextOption(itemOption); 32376 } 32377 if (itemOption.AttributeTypeCode == 2) { 32378 GLO.Inventory.Item.Options.generateColorOption(itemOption); 32379 } 32380 }); 32381 32382 GLO.Inventory.Item.Options.checkOptionThreshold(); 32383 } 32384 32385 32386 _conIItemOptions.generateItemVariationsList = function(itemVariations) { 32387 32388 console.log('generate variations grid'); 32389 32390 var itemVariationsList = $('#variations-list'); 32391 32392 var itemVariationsInner = itemVariationsList.find('.item-variations-inner'); 32393 itemVariationsInner.html(""); 32394 32395 var variationsListHeaderEl = document.createElement("div"); 32396 variationsListHeaderEl.className = "columns is-mobile item-variations"; 32397 32398 var variationsListFooterEl = document.createElement("div"); 32399 variationsListFooterEl.className = "columns is-mobile pt-1"; 32400 32401 //generateVariationEditFields 32402 variationsListHeaderEl.innerHTML = (`<div class="column is-one-fifth"> 32403 <div class="field"> 32404 <div class="control"> 32405 <span class="has-text-weight-bold">Variation</span> 32406 </div> 32407 </div> 32408 </div> 32409 <div class="column is-2"> 32410 <div class="field"> 32411 <div class="control"> 32412 <span class="has-text-weight-bold">Price</span> 32413 </div> 32414 </div> 32415 </div> 32416 <div class="column is-2"> 32417 <div class="field"> 32418 <div class="control"> 32419 <span class="has-text-weight-bold">In Stock</span> 32420 </div> 32421 </div> 32422 </div> 32423 <div class="column is-one-fifth"> 32424 <div class="field"> 32425 <div class="control"> 32426 <span class="has-text-weight-bold">SKU</span> 32427 </div> 32428 </div> 32429 </div> 32430 <div class="column is-1"> 32431 <div class="field"> 32432 <div class="control"> 32433 <span class="has-text-weight-bold">Image</span> 32434 </div> 32435 </div> 32436 </div>`); 32437 32438 //column header for active switch 32439 // <div class="column is-1"> 32440 // <div class="field"> 32441 // <div class="control">
32442 // <span class="has-text-weight-bold">Active</span> 32443 // </div> 32444 // </div> 32445 // </div> 32446 32447 itemVariationsInner.append(variationsListHeaderEl); 32448 32449 //generate variations rows 32450 itemVariations.forEach(itemVariation => { 32451 32452 var variationFieldsEl = document.createElement("div"); 32453 variationFieldsEl.className = "columns is-mobile item-variation"; 32454 32455 //generateVariationEditFields 32456 variationFieldsEl.innerHTML = (`<div class="column is-one-fifth"> 32457 <div class="field"> 32458 <div class="control variation-name"> 32459 <span>${itemVariation.Name}</span> 32460 <span class="is-hidden">${itemVariation.ItemVariationId}</span> 32461 </div> 32462 </div> 32463 </div> 32464 <div class="column is-2"> 32465 <div class="field"> 32466 <div class="control required variation-price"> 32467 <input class="input" placeholder="Price" min="0" value="${itemVariation.Price}" onChange="GLO.Inventory.Item.Options.validateVariationPrice(this)"> 32468 </div> 32469 </div> 32470 </div> 32471 <div class="column is-2"> 32472 <div class="field"> 32473 <div class="control required variation-quantity"> 32474 <input class="input" type="number" placeholder="Qty" value="${itemVariation.Quantity}"> 32475 </div> 32476 </div> 32477 </div> 32478 <div class="column is-one-fifth"> 32479 <div class="field"> 32480 <div class="control required variation-sku"> 32481 <input class="input" placeholder="SKU" value="${itemVariation.Sku}"> 32482 </div> 32483 </div> 32484 </div> 32485 <div class="column is-1"> 32486 <div class="field"> 32487 <div class="control variation-image"> 32488 <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchVariantImagePicker(this)"> 32489 <span class="icon is-small"> 32490 <i class="fas fa-bold fa-plus-circle ${ (itemVariation.Image !== null) ? 'is-hidden': ''}"></i> 32491 <figure class="image is-24x24 ${ (itemVariation.Image !== null) ? '': 'is-hidden'}"> 32492 <img src="${ (itemVariation.Image !== null) ? (GLO.Data.cdnDirectory + 'upload-folder/' + itemVariation.Image.ImagePath):''}"> 32493 </figure> 32494 <input type="hidden" id="item-image-id" name="item-image-id" value="${ (itemVariation.Image !== null) ? itemVariation.Image.ItemImageId:''}"/> 32495 </span> 32496 </button> 32497 </div> 32498 </div> 32499 </div>`); 32500 32501 //field for active switch 32502 // <div class="column is-1"> 32503 // <div class="field"> 32504 // <div class="control variation-active"> 32505 // <input id="${itemVariation.Name}" type="checkbox" name="${itemVariation.Name}" class="switch is-small is-outlined is-info" onclick="GLO.Inventory.Item.Options.enableVariation(this)" checked> 32506 // <label for="${itemVariation.Name}"></label> 32507 // </div> 32508 // </div> 32509 // </div> 32510 32511 itemVariationsInner.append(variationFieldsEl); 32512 32513 }); 32514 32515 variationsListFooterEl.innerHTML = (`<div class="column is-two-thirds"> 32516 32517 </div> 32518 <div class="column"> 32519 <div class="buttons is-justify-content-left"> 32520 <button class="button has-text-weight-normal" onclick="GLO.Inventory.Item.Options.cancelVariationEdit(this)">Cancel</button> 32521 <button class="button is-info has-text-weight-normal" onclick="GLO.Inventory.Item.Options.saveVariations(this)">Save</button> 32522 </div> 32523 </div>`); 32524 32525 itemVariationsInner.append(variationsListFooterEl); 32526 } 32527 32528 32529 _conIItemOptions.generateTextOption = function(itemOption) { 32530 32531 //generate option container with buttons 32532 var itemOptionsList = $('#options-list'); 32533 var itemOptionCsv = getItemOptionCsv(itemOption); 32534 var newOptionEl = document.createElement("div"); 32535 newOptionEl.className = "box m-3 item-option"; 32536 newOptionEl.setAttribute("data-id",itemOption.ItemAttributeId); 32537 newOptionEl.innerHTML = (`<div class="option-edit"> 32538 <div class="columns"> 32539 <div class="column is-half"> 32540 <div class="field"> 32541 <label class="label is-pulled-left">Name</label> 32542 <div class="control required option-name"> 32543 <input class="input item-option-name" placeholder="Option name for store display e.g. Size" value="${itemOption.Name}"> 32544 </div> 32545 </div> 32546 </div> 32547 <div class="column is-half"> 32548 <div class="field"> 32549 <label class="label is-pulled-left">Type</label> 32550 <div class="control required option-type"> 32551 <div class="select is-fullwidth"> 32552 <select class="select-option-type is-disabled"> 32553 <option>Choose One - Text</option> 32554 <option>Choose One - Color</option> 32555 </select> 32556 </div> 32557 </div> 32558 </div> 32559 </div> 32560 </div> 32561 <div class="columns"> 32562 <div class="column"> 32563 <div class="field"> 32564 <label class="label is-pulled-left">Values</label> 32565 </div> 32566 </div> 32567 </div> 32568 <div class="option-edit-fields"> 32569 <div class="columns"> 32570 <div class="column"> 32571 <div class="field"> 32572 <div class="control required text-option-value"> 32573 <input class="input item-option-value" type="tags" placeholder="Add comma-separated values e.g. Small, Medium, Large" value="${itemOptionCsv}"> 32574 </div> 32575 </div> 32576 </div> 32577 </div> 32578 </div> 32579 </div>
32580 <div class="option-preview is-hidden"> 32581 <!-- this is the preview of the option --> 32582 </div> 32583 <div class="columns option-actions"> 32584 <div class="column is-one-fifth"> 32585 <div class="buttons is-justify-content-left"> 32586 <button class="button is-danger has-text-weight-normal is-light btn-remove" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button> 32587 </div> 32588 </div> 32589 <div class="column"> 32590 32591 </div> 32592 <div class="column is-one-third"> 32593 <div class="buttons is-justify-content-right"> 32594 <button class="button has-text-weight-normal btn-cancel is-hidden" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button> 32595 <button class="button is-info has-text-weight-normal btn-save is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button> 32596 <button class="button is-info has-text-weight-normal btn-edit" onclick="GLO.Inventory.Item.Options.editOption(this)">Edit</button> 32597 </div> 32598 </div> 32599 </div>`); 32600 32601 $(newOptionEl).insertBefore($('.create-new-option')); 32602 // itemOptionsList.append(newOptionEl); 32603 32604 GLO.Inventory.Item.Options.generateTextOptionPreview(itemOption,newOptionEl); 32605 32606 } 32607 32608 _conIItemOptions.generateTextOptionPreview = function(itemOption,optionEl) { 32609 32610 var itemOptionPreviewEl = $(optionEl).find('.option-preview'); 32611 32612 var optionPreviewInnerEl = document.createElement("div"); 32613 optionPreviewInnerEl.className = "container has-background-light p-3 m-3"; 32614 optionPreviewInnerEl.innerHTML=(`<span class="pull-left">Preview</span><span>${itemOption.Name}</span><span class="is-hidden">${itemOption.Id}</span>`); 32615 32616 itemOptionPreviewEl.append(optionPreviewInnerEl); 32617 32618 var optionValuesEl = document.createElement("div"); 32619 optionValuesEl.className="buttons is-justify-content-center mt-1"; 32620 32621 itemOption.ItemAttributeValues.forEach(function(itemOptionValue) { 32622 var optionValueEl = document.createElement("button"); 32623 optionValueEl.className="button"; 32624 optionValueEl.innerHTML=(`${itemOptionValue.Value}`); 32625 optionValuesEl.append(optionValueEl); 32626 }); 32627 32628 optionPreviewInnerEl.append(optionValuesEl); 32629 32630 32631 $(optionEl).find('.option-edit').addClass('is-hidden'); 32632 itemOptionPreviewEl.removeClass('is-hidden'); 32633 } 32634 32635 _conIItemOptions.generateColorOption = function(itemOption) { 32636 32637 //generate option container with buttons 32638 var itemOptionsList = $('#options-list'); 32639 // var itemOptionCsv = getItemOptionCsv(itemOption); 32640 var newOptionEl = document.createElement("div"); 32641 newOptionEl.className = "box m-3 item-option"; 32642 newOptionEl.setAttribute("data-id",itemOption.ItemAttributeId); 32643 newOptionEl.innerHTML = (`<div class="option-edit"> 32644 <div class="columns"> 32645 <div class="column is-half"> 32646 <div class="field"> 32647 <label class="label is-pulled-left">Name</label> 32648 <div class="control required option-name"> 32649 <input class="input item-option-name" placeholder="Option name for store display e.g. Color" value="${itemOption.Name}"> 32650 </div> 32651 </div> 32652 </div> 32653 <div class="column is-half"> 32654 <div class="field"> 32655 <label class="label is-pulled-left">Type</label> 32656 <div class="control required option-type"> 32657 <div class="select is-fullwidth"> 32658 <select class="select-option-type is-disabled"> 32659 <option>Choose One - Text</option> 32660 <option selected>Choose One - Color</option> 32661 </select> 32662 </div> 32663 </div> 32664 </div> 32665 </div> 32666 </div> 32667 <div class="columns"> 32668 <div class="column"> 32669 <div class="field"> 32670 <label class="label is-pulled-left">Values</label> 32671 </div> 32672 </div> 32673 </div> 32674 <div class="option-edit-fields"> 32675 <!-- color swatches go here --> 32676 </div> 32677 </div> 32678 <div class="option-preview is-hidden"> 32679 <!-- this is the preview of the option --> 32680 </div>
32681 <div class="columns option-actions"> 32682 <div class="column is-one-fifth"> 32683 <div class="buttons is-justify-content-left"> 32684 <button class="button is-danger has-text-weight-normal is-light btn-remove" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button> 32685 </div> 32686 </div> 32687 <div class="column"> 32688 32689 </div> 32690 <div class="column is-one-third"> 32691 <div class="buttons is-justify-content-right"> 32692 <button class="button has-text-weight-normal btn-cancel is-hidden" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button> 32693 <button class="button is-info has-text-weight-normal btn-save is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button> 32694 <button class="button is-info has-text-weight-normal btn-edit" onclick="GLO.Inventory.Item.Options.editOption(this)">Edit</button> 32695 </div> 32696 </div> 32697 </div>`); 32698 32699 $(newOptionEl).insertBefore($('.create-new-option')); 32700 32701 GLO.Inventory.Item.Options.generateColorSwatchEditFields(itemOption,newOptionEl); 32702 GLO.Inventory.Item.Options.generateColorOptionPreview(itemOption,newOptionEl); 32703 32704 } 32705 32706 _conIItemOptions.generateColorSwatchEditFields = function(itemOption,optionEl) { 32707 32708 var itemOptionPreviewEl = $(optionEl).find('.option-preview'); 32709 var optionEditFieldsEl = $(optionEl).find('.option-edit-fields'); 32710 optionEditFieldsEl.html(""); 32711 32712 var addNewColorSwatchEl = document.createElement("div"); 32713 addNewColorSwatchEl.className = "columns is-mobile create-new-color-swatch"; 32714 32715 itemOption.ItemAttributeValues.forEach(function(itemOptionValue) { 32716 32717 var optionFieldsEl = document.createElement("div"); 32718 optionFieldsEl.className = "columns is-mobile item-option-color-value"; 32719 32720 if (itemOptionValue.IsImage) { 32721 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemOptionValue.Value; 32722 32723 optionFieldsEl.innerHTML = (`<div class="column is-one-fifth"> 32724 <div class="field"> 32725 <div class="control required color-swatch-value"> 32726 <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)"> 32727 <span class="icon is-small"> 32728 <i class="fas fa-bold fa-plus-circle is-hidden"></i> 32729 <figure class="image is-24x24"> 32730 <img class="is-rounded" src="${img_path}"> 32731 </figure> 32732 <input type="hidden" id="item-image-path" name="item-image-path" value="${itemOptionValue.Value}" /> 32733 <input type="hidden" id="item-attribute-value-id" name="item-attribute-value-id" value="${itemOptionValue.ItemAttributeValueId}" /> 32734 </span> 32735 </button> 32736 </div> 32737 </div> 32738 </div> 32739 <div class="column"> 32740 <div class="field"> 32741 <div class="control required color-swatch-name"> 32742 <input class="input" placeholder="Add value e.g. Blue" value="${itemOptionValue.Name}"> 32743 </div> 32744 </div> 32745 </div> 32746 <div class="column is-one-fifth"> 32747 <div class="field"> 32748 <div class="control"> 32749 <button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)" data-id="${itemOptionValue.ItemAttributeValueId}"> 32750 <span class="icon is-small"> 32751 <i class="fas fa-bold fa-times"></i> 32752 </span> 32753 </button> 32754 </div> 32755 </div> 32756 </div>`); 32757 32758 } 32759 else { 32760 optionFieldsEl.innerHTML = (`<div class="column is-one-fifth"> 32761 <div class="field"> 32762 <div class="control required color-swatch-value"> 32763 <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)"> 32764 <span class="icon is-small" style="background-color:${itemOptionValue.Value}"> 32765 <i class="fas fa-bold fa-plus-circle is-hidden"></i> 32766 <figure class="image is-24x24 is-hidden"> 32767 <img class="is-rounded" src=""> 32768 </figure> 32769 <input type="hidden" id="item-image-path" name="item-image-path" value="${itemOptionValue.Value}" /> 32770 <input type="hidden" id="item-attribute-value-id" name="item-attribute-value-id" value="${itemOptionValue.ItemAttributeValueId}" /> 32771 </span> 32772 </button> 32773 </div> 32774 </div> 32775 </div> 32776 <div class="column"> 32777 <div class="field"> 32778 <div class="control required color-swatch-name"> 32779 <input class="input" placeholder="Add value e.g. Blue" value="${itemOptionValue.Name}"> 32780 </div> 32781 </div> 32782 </div> 32783 <div class="column is-one-fifth"> 32784 <div class="field"> 32785 <div class="control"> 32786 <button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)" data-id="${itemOptionValue.ItemAttributeValueId}"> 32787 <span class="icon is-small"> 32788 <i class="fas fa-bold fa-times"></i> 32789 </span> 32790 </button> 32791 </div> 32792 </div> 32793 </div>`); 32794 } 32795 32796 optionEditFieldsEl.append(optionFieldsEl); 32797 }); 32798 32799 addNewColorSwatchEl.innerHTML = (`<div class="column"> 32800 <div class="field"> 32801 <div class="control"> 32802 <button class="button is-link is-inverted" onclick="GLO.Inventory.Item.Options.addBlankColorSwatchOptionValue(this)">Add Color 32803 </button> 32804 </div> 32805 </div> 32806 </div> 32807 </div>`); 32808 32809 optionEditFieldsEl.append(addNewColorSwatchEl); 32810 32811 } 32812 32813 _conIItemOptions.generateColorOptionPreview = function(itemOption,optionEl) { 32814 32815 var itemOptionPreviewEl = $(optionEl).find('.option-preview'); 32816 32817 var optionPreviewInnerEl = document.createElement("div"); 32818 optionPreviewInnerEl.className = "container has-background-light p-3 m-3"; 32819 optionPreviewInnerEl.innerHTML=(`<span class="pull-left">Preview</span><span>${itemOption.Name}</span><span class="is-hidden">${itemOption.Id}</span>`); 32820 32821 itemOptionPreviewEl.append(optionPreviewInnerEl); 32822
32823 var productColorsEl = document.createElement("div"); 32824 productColorsEl.className="product-colors"; 32825 32826 var colorSelectorEl = document.createElement("div"); 32827 colorSelectorEl.className="color-selector"; 32828 32829 itemOption.ItemAttributeValues.forEach(function(itemOptionValue) { 32830 var optionValueEl = document.createElement("div"); 32831 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemOptionValue.Value; 32832 if (itemOptionValue.IsImage) { 32833 // 32834 optionValueEl.innerHTML=(`<input type="radio" id="${itemOptionValue.ItemAttributeValueId}" name="color" value="" class="active"></input> 32835 <label for="${itemOptionValue.ItemAttributeValueId}"> 32836 <span class="indicator"> 32837 <i data-feather="check"></i> 32838 </span> 32839 <span> 32840 <img class="is-rounded image is-36x36" src="${img_path}"> 32841 </span> 32842 </label>`); 32843 32844 } 32845 else { 32846 optionValueEl.innerHTML=(`<input type="radio" id="${itemOptionValue.ItemAttributeValueId}" name="color" value="" class="active"></input> 32847 <label for="${itemOptionValue.ItemAttributeValueId}"> 32848 <span class="indicator"> 32849 <i data-feather="check"></i> 32850 </span> 32851 <span style="background-color:${itemOptionValue.Value}"></span> 32852 </label>`); 32853 } 32854 32855 colorSelectorEl.append(optionValueEl); 32856 }); 32857
32858 productColorsEl.append(colorSelectorEl); 32859 optionPreviewInnerEl.append(productColorsEl); 32860 32861 $(optionEl).find('.option-edit').addClass('is-hidden'); 32862 itemOptionPreviewEl.removeClass('is-hidden'); 32863 32864 } 32865 32866 _conIItemOptions.changeOptionType = function(elem) { 32867 32868 console.log('Change Option Type'); 32869 32870 var newOptionType = elem.value; 32871 var itemOptionsList = $('#options-list'); 32872 var optionEditFieldsEl = $(itemOptionsList).find('.option-edit-fields'); 32873 optionEditFieldsEl.html(""); 32874 32875 var optionFieldsEl = document.createElement("div"); 32876 optionFieldsEl.className = "columns is-mobile item-option-color-value"; 32877 32878 var addNewColorSwatchEl = document.createElement("div"); 32879 addNewColorSwatchEl.className = "columns is-mobile create-new-color-swatch"; 32880 32881 //text option 32882 if (newOptionType == 1) { 32883 //generateTextOptionFields 32884 optionFieldsEl.innerHTML = (`<div class="column"> 32885 <div class="field"> 32886 <div class="control"> 32887 <input class="input" placeholder="Add comma-separated values e.g. Small, Medium, Large"> 32888 </div> 32889 </div> 32890 </div>`); 32891 } 32892 32893 //color option 32894 if (newOptionType == 2) { 32895 //generateColorOptionFields 32896 optionFieldsEl.innerHTML = (`<div class="column is-one-fifth"> 32897 <div class="field"> 32898 <div class="control required color-swatch-value"> 32899 <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)"> 32900 <span class="icon is-small"> 32901 <i class="fas fa-bold fa-plus-circle"></i> 32902 <figure class="image is-24x24 is-hidden"> 32903 <img class="is-rounded" src="https://bulma.io/images/placeholders/24x24.png"> 32904 </figure> 32905 <input type="hidden" id="item-image-path" name="item-image-path" /> 32906 </span> 32907 </button> 32908 </div> 32909 </div> 32910 </div> 32911 <div class="column"> 32912 <div class="field"> 32913 <div class="control required color-swatch-name"> 32914 <input class="input" placeholder="Add value e.g. Blue"> 32915 </div> 32916 </div> 32917 </div> 32918 <div class="column is-one-fifth"> 32919 <div class="field"> 32920 <div class="control"> 32921 <button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)"> 32922 <span class="icon is-small"> 32923 <i class="fas fa-bold fa-times"></i> 32924 </span> 32925 </button> 32926 </div> 32927 </div> 32928 </div>`); 32929 } 32930 32931 optionEditFieldsEl.append(optionFieldsEl); 32932 32933 addNewColorSwatchEl.innerHTML = (`<div class="column"> 32934 <div class="field"> 32935 <div class="control"> 32936 <button class="button is-link is-inverted" onclick="GLO.Inventory.Item.Options.addBlankColorSwatchOptionValue(this)">Add Color 32937 </button> 32938 </div> 32939 </div> 32940 </div> 32941 </div>`); 32942 32943 optionEditFieldsEl.append(addNewColorSwatchEl); 32944 32945 } 32946 32947 _conIItemOptions.addBlankColorSwatchOptionValue = function(elem) { 32948 32949 var optionFieldsEl = document.createElement("div"); 32950 optionFieldsEl.className = "columns is-mobile item-option-color-value"; 32951 32952 optionFieldsEl.innerHTML = (`<div class="column is-one-fifth"> 32953 <div class="field"> 32954 <div class="control required color-swatch-value"> 32955 <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)"> 32956 <span class="icon is-small"> 32957 <i class="fas fa-bold fa-plus-circle"></i> 32958 <figure class="image is-24x24 is-hidden"> 32959 <img class="is-rounded" src="https://bulma.io/images/placeholders/24x24.png"> 32960 </figure> 32961 <input type="hidden" id="item-image-path" name="item-image-path" /> 32962 </span> 32963 </button> 32964 </div> 32965 </div> 32966 </div> 32967 <div class="column"> 32968 <div class="field"> 32969 <div class="control required color-swatch-name"> 32970 <input class="input" placeholder="Add value e.g. Black"> 32971 </div> 32972 </div> 32973 </div> 32974 <div class="column is-one-fifth"> 32975 <div class="field"> 32976 <div class="control"> 32977 <button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)">
32978 <span class="icon is-small"> 32979 <i class="fas fa-bold fa-times"></i> 32980 </span> 32981 </button> 32982 </div> 32983 </div> 32984 </div>`); 32985 32986 var createNewColorSwatchEl = $(elem).closest('.create-new-color-swatch'); 32987 $(optionFieldsEl).insertBefore(createNewColorSwatchEl); 32988 } 32989 32990 _conIItemOptions.launchItemOptionUploadColorSwatch = function(elem) { 32991 32992 _itemSelectedItemOptionColorSwatch = elem; 32993 32994 $('#item-option-color-swatches-container').modal(); 32995 var jModal = $('#simplemodal-container #item-option-color-swatches-container'); 32996 var h = $(window).height() * 0.2; 32997 var w = $(window).width() * 0.3; 32998 32999 $.modal.update(h,w); 33000 $(window).resize(); 33001 $('.modalCloseImg').css("margin-top","20px"); 33002 $('.modalCloseImg').css("margin-right","20px"); 33003 $('.modalCloseImg').on("click",function() { GLO.Inventory.Item.Options.closeItemOptionUploadColorSwatch(); }); 33004 33005 if (GLO.Info.isMobile()) { 33006 $('#simplemodal-container').draggable({disable:true}); 33007 } 33008 $('#simplemodal-container').css("overflow-y","auto"); 33009 33010 } 33011 33012 _conIItemOptions.closeItemOptionUploadColorSwatch = function() { 33013 33014 $('.modalCloseImg').off("click"); 33015 } 33016 33017 _conIItemOptions.selectedColorSwatchImage = function(elem) { 33018 console.log('Chose image upload for color swatch'); 33019 33020 $('#item-option-color-choices').addClass('is-hidden'); 33021 $('#item-option-image-uploader').removeClass('is-hidden'); 33022 33023 } 33024 33025 _conIItemOptions.changeOptionColor = function(elem) { 33026 console.log('Change Option Color Value'); 33027 } 33028 33029 _conIItemOptions.addNewOptionAskConfirmation= function(elem) { 33030 33031 var variationsHaveInventoryIds = doVariationsHaveInventoryIds(); 33032 33033 if (variationsHaveInventoryIds) { 33034 33035 if (GLO.Info.isMobile()) { 33036 var msg = 'Add new product option?'; 33037 } else { 33038 var msg = 'Are you sure you want to add a new product option?'; 33039 } 33040 33041 msg = msg + ' Upon saving the new option, products generated for the variations will be deleted and variations will be regenerated.'; 33042 33043 msg = '<div class="friendly-msg2">' + msg + '</div>'; 33044 msg = '<div> <h2 class="friendly-msg2">Add Product Option?</h2>' + msg + '</div>'; 33045 33046 33047 var fnYes = function() { GLO.Inventory.Item.Options.generateNewOption(elem); }; 33048 var fnNo = function() { GLO.UI.Form.resetProcessing(); } 33049 33050 var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup(); 33051 33052 if (jpop.height() > innerHeight * .9) { 33053 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 33054 } 33055 } 33056 else { 33057 GLO.Inventory.Item.Options.generateNewOption(elem); 33058 } 33059 33060 33061 } 33062 33063 _conIItemOptions.removeOptionAskConfirmation= function(elem) { 33064 33065 var variationsHaveInventoryIds = false; 33066 33067 //check if option has an id 33068 var itemAttributeId = $(elem).closest('.item-option').attr('data-id'); 33069 //check for variant inventory ids only if option was saved previously 33070 if (itemAttributeId !== undefined && itemAttributeId > 0) { 33071 variationsHaveInventoryIds = doVariationsHaveInventoryIds(); 33072 } 33073 33074 if (GLO.Info.isMobile()) { 33075 var msg = 'Remove the product option?'; 33076 } else { 33077 var msg = 'Are you sure you want to remove the product option?'; 33078 } 33079 33080 if (variationsHaveInventoryIds) { 33081 33082 msg = msg + ' Products generated for the variations will be deleted and variations will be regenerated.'; 33083 } 33084 33085 msg = '<div class="friendly-msg2">' + msg + '</div>'; 33086 msg = '<div> <h2 class="friendly-msg2">Remove Product Option?</h2>' + msg + '</div>'; 33087 33088 33089 var fnYes = function() { GLO.Inventory.Item.Options.removeOption(elem); }; 33090 var fnNo = function() { GLO.UI.Form.resetProcessing(); } 33091 33092 var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup(); 33093 33094 if (jpop.height() > innerHeight * .9) { 33095 jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) }); 33096 } 33097 } 33098 33099 _conIItemOptions.removeOptionValue = function(elem) { 33100 console.log('Remove Option Color Value'); 33101 33102 var optionColorValueX = elem; 33103 var optionDiv = optionColorValueX.closest(".item-option"); 33104 var itemOptionsColorValues = $(optionDiv).find('.item-option-color-value').length; 33105 33106 33107 if (itemOptionsColorValues == 1) { 33108 // GLO.Inventory.Item.Options.removeOption(optionDiv); 33109 GLO.Inventory.Item.Options.removeOptionAskConfirmation(optionDiv); 33110 } 33111 else { 33112 optionColorValueX.closest(".item-option-color-value").remove(); 33113 } 33114 } 33115 33116 _conIItemOptions.cancelOptionEdit = function(elem) { 33117 33118 console.log('Cancel Edit - Option Preview or Remove'); 33119 33120 var itemOptionEl = $(elem).closest('.item-option'); 33121 if (itemOptionEl.attr('data-id') !== undefined && itemOptionEl.attr('data-id') !== false) { 33122 $(elem).parents('.item-option').find('.option-edit').addClass('is-hidden'); 33123 $(elem).parents('.item-option').find('.btn-cancel').addClass('is-hidden'); 33124 $(elem).parents('.item-option').find('.btn-save').addClass('is-hidden'); 33125 33126 $(elem).parents('.item-option').find('.option-preview').removeClass('is-hidden'); 33127 $(elem).parents('.item-option').find('.btn-edit').removeClass('is-hidden'); 33128 } 33129 else { 33130 //remove empty option 33131 GLO.Inventory.Item.Options.removeOption(elem); 33132 } 33133 33134 } 33135 33136 _conIItemOptions.editOption = function(elem) { 33137 console.log('Option Edit Mode'); 33138 33139 $(elem).parents('.item-option').find('.option-preview').addClass('is-hidden'); 33140 $(elem).parents('.item-option').find('.btn-edit').addClass('is-hidden'); 33141 33142 $(elem).parents('.item-option').find('.option-edit').removeClass('is-hidden'); 33143 $(elem).parents('.item-option').find('.btn-cancel').removeClass('is-hidden'); 33144 $(elem).parents('.item-option').find('.btn-save').removeClass('is-hidden'); 33145 33146 //attach tags input 33147 var tagEl = $(elem).parents('.item-option').find('input[type="tags"]')[0]; 33148 if (tagEl) { 33149 attachBulmaTagsInput(tagEl); 33150 } 33151 33152 } 33153
33154 var validateOption = function(itemOptionEl) { 33155 33156 //foreach variation check if price, qty and sku are valid 33157 //if any row is invalid mark the row or field with css class 33158 //return true if everything looks good 33159 var optionFieldsCompleted = true; 33160 33161 var optionNameField = $(itemOptionEl).find('.control.required.option-name'); 33162 var optionNameValue = $(itemOptionEl).find('.item-option-name').val(); 33163 33164 if (optionNameValue == '' || typeof optionNameValue == 'undefined') { 33165 $(optionNameField).addClass('has-error'); 33166 optionFieldsCompleted = false; 33167 } 33168 else { 33169 $(optionNameField).removeClass('has-error'); 33170 } 33171 33172 33173 var attributeTypeName = $(itemOptionEl).find('.select-option-type').val(); 33174 var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName); 33175 33176 //text option 33177 if (itemAttributeType.attribute_id == 1) { 33178 var optionTagsField = $(itemOptionEl).find('.control.required.text-option-value'); 33179 var csvValue = $(itemOptionEl).find('input[type="tags"]')[0].value; 33180 if (csvValue == '' || typeof csvValue == 'undefined') { 33181 $(optionTagsField).addClass('has-error'); 33182 optionFieldsCompleted = false; 33183 } 33184 else { 33185 $(optionTagsField).removeClass('has-error'); 33186 } 33187 } 33188 33189 //color option 33190 if (itemAttributeType.attribute_id == 2) { 33191 var optionColorSwatchList = $(itemOptionEl).find('.option-edit-fields'); 33192 var optionColorSwatchCount = optionColorSwatchList.find('.item-option-color-value').length; 33193 33194 for (var i=0; i < optionColorSwatchCount; i++) { 33195 var colorSwatchRow = $(optionColorSwatchList).find('.item-option-color-value')[i]; 33196 var colorSwatchValueEl = $(colorSwatchRow).find('.control.required.color-swatch-value'); 33197 var colorSwatchImageButton = $(colorSwatchValueEl).find('.button'); 33198 var colorSwatchImageValue = $(colorSwatchValueEl).find('#item-image-path').val(); 33199 33200 var colorSwatchNameEl = $(colorSwatchRow).find('.control.required.color-swatch-name'); 33201 var colorSwatchNameValue = $(colorSwatchNameEl).find('.input').val(); 33202 33203 if (colorSwatchImageValue == '' || typeof colorSwatchImageValue == 'undefined') { 33204 // $(colorSwatchValueEl).addClass('has-error'); 33205 $(colorSwatchImageButton).removeClass('is-info').addClass('is-danger'); 33206 optionFieldsCompleted = false; 33207 } 33208 else { 33209 // $(colorSwatchValueEl).removeClass('has-error'); 33210 $(colorSwatchImageButton).removeClass('is-danger').addClass('is-info'); 33211 } 33212 33213 if (colorSwatchNameValue == '' || typeof colorSwatchNameValue == 'undefined') { 33214 $(colorSwatchNameEl).addClass('has-error'); 33215 optionFieldsCompleted = false; 33216 } 33217 else { 33218 $(colorSwatchNameEl).removeClass('has-error'); 33219 } 33220 } 33221 } 33222 33223 return optionFieldsCompleted; 33224 33225 } 33226 33227 _conIItemOptions.saveOption = function(elem) { 33228 console.log('Option Save'); 33229 var itemOptionEl = $(elem).closest('.item-option'); 33230 33231 var validatOptionResult = validateOption(itemOptionEl); 33232 33233 if (validatOptionResult) { 33234 33235 var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemAttribute'; 33236 33237 //check for data-id 33238 var itemAttributeId = itemOptionEl.attr('data-id'); 33239 33240 if (itemAttributeId == undefined) { 33241 itemAttributeId = 0;//for new options 33242 } 33243 33244 var itemOption = new Object(); 33245 itemOption.ProviderId = GLO.Data.provider.id; 33246 itemOption.Name = $(elem).closest('.item-option').find('.item-option-name').val(); 33247 itemOption.InventoryId = _itemId; 33248 itemOption.ItemAttributeId = itemAttributeId; 33249 33250 var attributeTypeName = $(elem).closest('.item-option').find('.select-option-type').val(); 33251 var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName); 33252 itemOption.AttributeTypeCode = itemAttributeType.attribute_id; 33253 33254 itemOption.ItemAttributeValues = []; 33255 33256 if (itemOption.AttributeTypeCode == 1) { 33257 //text option 33258 var csvValue = $(elem).closest('.item-option').find('input[type="tags"]')[0].value; 33259 var csvArray = csvValue.split(','); 33260 csvArray.forEach(function(optionVal) { 33261 var itemAttributeValue = { 33262 ItemAttributeId: itemAttributeId, 33263 Name: optionVal, 33264 Value: optionVal, 33265 IsImage: false}; 33266 33267 itemOption.ItemAttributeValues.push(itemAttributeValue); 33268 });
33269 } 33270 else if (itemOption.AttributeTypeCode == 2) { 33271 //color option 33272 var colorValueElArray = itemOptionEl.find('.item-option-color-value'); 33273 for (var i = 0; i < colorValueElArray.length; i++) { 33274 var colorSwatchImagePath = $(colorValueElArray[i]).find('#item-image-path').val(); 33275 var colorSwatchName = $(colorValueElArray[i]).find('.input').val(); 33276 33277 var itemAttributeValue = { 33278 ItemAttributeId: itemAttributeId, 33279 Name: colorSwatchName, 33280 Value: colorSwatchImagePath, 33281 IsImage: true 33282 }; 33283 33284 itemOption.ItemAttributeValues.push(itemAttributeValue); 33285 } 33286 } 33287 else { 33288 //nothing to do 33289 console.log('Invalid item option type'); 33290 return; 33291 } 33292 33293 var jsonString= JSON.stringify(itemOption); 33294 33295 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: itemOption}) 33296 .success(function(data, textStatus, jqXHR) { 33297 if (UTIL.Validate.hasPermissionError(data)) { return; } 33298 GLO.Popup.Success.open('Product Option updated.'); 33299 GLO.Inventory.Item.Options.getItemOptions(_itemId); 33300 GLO.Inventory.Item.Options.getItemVariations(_itemId); 33301 33302 }) 33303 .error(function(jqXHR, textStatus, errorThrown) { 33304 new GLO.Popup.Error('Unable to save product option at this time. Please try again later.'); 33305 GLO.UI.Form.resetProcessing(); 33306 }); 33307 33308 } 33309 33310 } 33311 33312 _conIItemOptions.removeOption = function(elem) { 33313 console.log('Option Remove'); 33314 var itemOptionEl = $(elem).closest('.item-option'); 33315 33316 //check for data-id 33317 var itemAttributeId = itemOptionEl.attr('data-id'); 33318 33319 if (itemAttributeId > 0) { 33320 var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveItemAttribute'; 33321 33322 var itemOption = new Object(); 33323 itemOption.ProviderId = GLO.Data.provider.id; 33324 itemOption.Name = $(elem).closest('.item-option').find('.item-option-name').val(); 33325 itemOption.InventoryId = _itemId; 33326 itemOption.itemAttributeId = itemAttributeId; 33327 33328 var attributeTypeName = $(elem).closest('.item-option').find('.select-option-type').val(); 33329 var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName); 33330 itemOption.AttributeTypeCode = itemAttributeType.attribute_id; 33331 33332 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: itemOption}) 33333 .success(function(data, textStatus, jqXHR) { 33334 if (UTIL.Validate.hasPermissionError(data)) { return; } 33335 var optionDiv = elem; 33336 optionDiv.closest(".item-option").remove(); 33337 GLO.Inventory.Item.Options.checkOptionThreshold(); 33338 GLO.Inventory.Item.Options.getItemOptions(_itemId); 33339 GLO.Inventory.Item.Options.getItemVariations(_itemId); 33340 33341 }) 33342 .error(function(jqXHR, textStatus, errorThrown) { 33343 new GLO.Popup.Error('Unable to remove product option at this time. Please try again later.'); 33344 GLO.UI.Form.resetProcessing(); 33345 }); 33346 } 33347 else { 33348 //option not saved yet 33349 var optionDiv = elem; 33350 optionDiv.closest(".item-option").remove(); 33351 GLO.Inventory.Item.Options.checkOptionThreshold(); 33352 } 33353 } 33354 33355 _conIItemOptions.uploadImageAndResize = function () { 33356 //define the width to resize e.g 180px 33357 var resize_width = 500;//without px 33358 33359 //get the image selected 33360 var item = document.querySelector('#uploader').files[0]; 33361 33362 //create a FileReader 33363 var reader = new FileReader(); 33364 33365 //image turned to base64-encoded Data URI. 33366 reader.readAsDataURL(item); 33367 reader.name = item.name;//get the image's name 33368 reader.size = item.size; //get the image's size 33369 reader.onload = function(event) { 33370 var img = new Image();//create a image 33371 img.src = event.target.result;//result is base64-encoded Data URI 33372 img.name = event.target.name;//set name (optional) 33373 img.size = event.target.size;//set size (optional) 33374 img.onload = function(el) { 33375 var elem = document.createElement('canvas');//create a canvas 33376 33377 //scale the image to 600 (width) and keep aspect ratio 33378 var scaleFactor = resize_width / el.target.width; 33379 elem.width = resize_width; 33380 elem.height = el.target.height * scaleFactor; 33381 33382 //draw in canvas 33383 var ctx = elem.getContext('2d'); 33384 ctx.drawImage(el.target, 0, 0, elem.width, elem.height); 33385 33386 //get the base64-encoded Data URI from the resize image 33387 var srcEncoded = ctx.canvas.toDataURL('image/png', 1); 33388 33389 //assign it to thumb src 33390 // document.querySelector('#item-image').src = srcEncoded; 33391 33392 GLO.Inventory.Item.Options.saveItemOptionImage(srcEncoded,resize_width); 33393 } 33394 } 33395 } 33396 33397 _conIItemOptions.saveItemOptionImage = function(data,width) { 33398 33399 //remove the attached handler 33400 $('#btnSaveItemImage').off("click"); 33401 33402 var jcontainer = $('#uploader'); 33403 33404 //reset error 33405 $('#itemImageUploadErrorMessage').addClass('is-hidden'); 33406 33407 var fnCallback = function(jcontainer, fileName, imgId, imgSize) { 33408 if (fileName!=null && fileName.length > 0) { 33409 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName; 33410 // console.log(img_path); 33411 33412 //clear the image display 33413 document.querySelector('#item-image').src =''; 33414 33415 //set the image on the option 33416 if (_itemSelectedItemOptionColorSwatch) { 33417 33418 //hide the icon 33419 $($(_itemSelectedItemOptionColorSwatch).find('i')[0]).addClass('is-hidden'); 33420 33421 //set the filename 33422 $($(_itemSelectedItemOptionColorSwatch).find('#item-image-path')[0]).val(fileName); 33423 //display the image 33424 $($(_itemSelectedItemOptionColorSwatch).find('img')[0]).attr('src',img_path); 33425 //unhide the image container 33426 $($(_itemSelectedItemOptionColorSwatch).find('figure')[0]).removeClass('is-hidden'); 33427 33428 _itemSelectedItemOptionColorSwatch = null; 33429 } 33430 33431 //close the modal 33432 $('.simplemodal-close').click(); 33433 // closeItemOptionUploadColorSwatch 33434 33435 } 33436 else { 33437 //display error 33438 $('#itemImageUploadErrorMessage').removeClass('is-hidden'); 33439 } 33440 } 33441 33442 if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) { 33443 return true; 33444 } 33445 } 33446 33447 //launchVariantImagePicker 33448 _conIItemOptions.getItemImages = function(inventoryId) { 33449 var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemImages?id=' + inventoryId; 33450
33451 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 33452 .done(function(data, textStatus, jqXHR) { 33453 window.onbeforeunload = null; 33454 if(data!=null && data!== '') { 33455 var itemImages = data; 33456 if (itemImages.length > 0) { 33457 generateItemImagePickerGrid(itemImages); 33458 } 33459 else { 33460 //display blank state 33461 generateItemImagePickerGridBlankState(); 33462 } 33463 } else { 33464 new GLO.Popup.Error('Could not get the product images'); 33465 } 33466 }) 33467 .fail(function(jqXHR, textStatus, errorThrown) { 33468 GLO.UI.Form.resetProcessing(); 33469 new GLO.Popup.Error('Could not get the product images'); 33470 }); 33471 } 33472 33473 _conIItemOptions.launchVariantImagePicker = function(elem) { 33474 33475 _itemSelectedVariant = elem; 33476 33477 $('#item-variation-image-picker-container').modal(); 33478 var jModal = $('#simplemodal-container #item-variation-image-picker-container'); 33479 var h = $(window).height() * 0.8; 33480 var w = $(window).width() * 0.8; 33481 33482 $.modal.update(h,w); 33483 $(window).resize(); 33484 $('.modalCloseImg').css("margin-top","20px"); 33485 $('.modalCloseImg').css("margin-right","20px"); 33486 $('.modalCloseImg').on("click",function() { GLO.Inventory.Item.Options.closeVariantImagePicker(); }); 33487 33488 if (GLO.Info.isMobile()) { 33489 $('#simplemodal-container').draggable({disable:true}); 33490 } 33491 $('#simplemodal-container').css("overflow-y","auto"); 33492 33493 GLO.Inventory.Item.Options.getItemImages(_itemId); 33494 33495 } 33496 33497 _conIItemOptions.setImageForVariation = function(itemImageId,itemImageFilename) { 33498 33499 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImageFilename; 33500 33501 //set the image on the variation 33502 if (_itemSelectedVariant) { 33503 33504 //hide the icon 33505 $($(_itemSelectedVariant).find('i')[0]).addClass('is-hidden'); 33506 33507 //set the imageId 33508 $($(_itemSelectedVariant).find('#item-image-id')[0]).val(itemImageId); 33509 //display the image 33510 $($(_itemSelectedVariant).find('img')[0]).attr('src',img_path); 33511 //unhide the image container 33512 $($(_itemSelectedVariant).find('figure')[0]).removeClass('is-hidden'); 33513 33514 _itemSelectedVariant = null; 33515 } 33516 33517 //close the modal 33518 $('.simplemodal-close').click(); 33519 33520 } 33521 33522 33523 _conIItemOptions.closeVariantImagePicker = function() { 33524 33525 $('.modalCloseImg').off("click"); 33526 } 33527 33528 _conIItemOptions.validateVariationPrice = function(elem) { 33529 var priceVal = parseFloat(elem.value); 33530 33531 if (isNaN(priceVal)) { 33532 elem.value = ''; 33533 } else { 33534 elem.value = priceVal.toFixed(2); 33535 } 33536 } 33537 33538 var validateVariations = function() { 33539 33540 //foreach variation check if price, qty and sku are valid 33541 //if any row is invalid mark the row or field with css class 33542 //return true if everything looks good 33543 var variationsFieldsCompleted = true; 33544 var itemVariationsList = $('#variations-list'); 33545 var itemVariationsCount = itemVariationsList.find('.item-variations-inner').find('.item-variation').length; 33546 for (var i=0; i < itemVariationsCount; i++) { 33547 var itemVariationRow = itemVariationsList.find('.item-variations-inner').find('.item-variation')[i]; 33548 var itemVariationPriceField = $(itemVariationRow).find('.control.required.variation-price'); 33549 var itemVariationQuantityField = $(itemVariationRow).find('.control.required.variation-quantity'); 33550 var itemVariationSkuField = $(itemVariationRow).find('.control.required.variation-sku'); 33551 33552 var itemVariationPriceValue = $(itemVariationPriceField).find('.input').val(); 33553 if (itemVariationPriceValue == '' || isNaN(itemVariationPriceValue) || itemVariationPriceValue <= 0) { 33554 $(itemVariationPriceField).addClass('has-error'); 33555 variationsFieldsCompleted = false; 33556 } 33557 else { 33558 $(itemVariationPriceField).removeClass('has-error'); 33559 } 33560 33561 var itemVariationQuantityValue = $(itemVariationQuantityField).find('.input').val(); 33562 if (itemVariationQuantityValue == '' || isNaN(itemVariationQuantityValue)) { 33563 $(itemVariationQuantityField).addClass('has-error'); 33564 variationsFieldsCompleted = false; 33565 } 33566 else { 33567 $(itemVariationQuantityField).removeClass('has-error'); 33568 } 33569 33570 33571 var itemVariationSkuValue = $(itemVariationSkuField).find('.input').val(); 33572 if (itemVariationSkuValue == '') { 33573 $(itemVariationSkuField).addClass('has-error'); 33574 variationsFieldsCompleted = false; 33575 } 33576 else { 33577 $(itemVariationSkuField).removeClass('has-error'); 33578 } 33579 33580 } 33581 33582 return variationsFieldsCompleted; 33583 33584 } 33585 33586 _conIItemOptions.saveVariations = function(elem) { 33587 33588 console.log('save variations'); 33589 33590 var itemVariationsArray = []; 33591
33592 var validateVariationResult = validateVariations(); 33593 33594 if (validateVariationResult) { 33595 33596 var itemVariationsList = $('#variations-list'); 33597 var itemVariationsCount = itemVariationsList.find('.item-variations-inner').find('.item-variation').length; 33598 for (var i=0; i < itemVariationsCount; i++) { 33599 var itemVariationRow = itemVariationsList.find('.item-variations-inner').find('.item-variation')[i]; 33600 var itemVariationNameField = $(itemVariationRow).find('.control.variation-name'); 33601 var itemVariationPriceField = $(itemVariationRow).find('.control.required.variation-price'); 33602 var itemVariationQuantityField = $(itemVariationRow).find('.control.required.variation-quantity'); 33603 var itemVariationSkuField = $(itemVariationRow).find('.control.required.variation-sku'); 33604 var itemVariationImageField = $(itemVariationRow).find('.control.variation-image'); 33605 33606 var itemVariationNameValue = $($(itemVariationNameField).find('span')[0]).text(); 33607 var itemVariationIdValue = $($(itemVariationNameField).find('span')[1]).text(); 33608 33609 var itemVariationPriceValue = $(itemVariationPriceField).find('.input').val(); 33610 var itemVariationQuantityValue = $(itemVariationQuantityField).find('.input').val(); 33611 var itemVariationSkuValue = $(itemVariationSkuField).find('.input').val(); 33612 var itemVariationImageId = $(itemVariationImageField).find('#item-image-id').val(); 33613 33614 var itemVariation = new Object(); 33615 itemVariation.ItemVariationId = itemVariationIdValue; 33616 itemVariation.PrimaryInventoryId = _itemId; 33617 itemVariation.ProviderId = GLO.Data.provider.id; 33618 itemVariation.Name = itemVariationNameValue; 33619 itemVariation.Price = itemVariationPriceValue; 33620 itemVariation.Quantity = itemVariationQuantityValue; 33621 itemVariation.Sku = itemVariationSkuValue; 33622 33623 var itemImage = new Object(); 33624 itemImage.ItemImageId = itemVariationImageId; 33625 itemImage.InventoryId = _itemId; 33626 33627 itemVariation.Image = itemImage; 33628 itemVariation.IsAvailableInStore = true; 33629 itemVariation.IsValid = true; 33630 33631 itemVariationsArray.push(itemVariation); 33632 33633 } 33634 33635 var jsonString= JSON.stringify(itemVariationsArray); 33636 33637 var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemVariations'; 33638 33639 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonString, contentType: "application/json"}) 33640 .success(function(data, textStatus, jqXHR) { 33641 if (UTIL.Validate.hasPermissionError(data)) { return; } 33642 // GLO.Inventory.Item.Options.getItemVariations(_itemId); 33643 GLO.Popup.Success.open('Product Variations updated.'); 33644 33645 }) 33646 .error(function(jqXHR, textStatus, errorThrown) { 33647 new GLO.Popup.Error('Unable to save product variations. Please try again.'); 33648 GLO.UI.Form.resetProcessing(); 33649 }); 33650 33651 } 33652 } 33653 33654 _conIItemOptions.cancelVariationEdit = function(elem) { 33655 //reload variations list 33656 GLO.Inventory.Item.Options.getItemVariations(_itemId); 33657 } 33658 33659 return _conIItemOptions; 33660 })(); 33661 33662 _conIItem.launchItemOptions = function(event) { 33663 var uri = GLO.Link.Page.Provider.Home + 'Inventory/itemoptions?id=' + GLO.Uri.hash('id'); 33664 33665 if (event.ctrlKey) { 33666 var childWindow = UI.openChildWindow(uri, '', true); 33667 } else { 33668 document.location = uri; 33669 } 33670 } 33671 33672 _conIItem.lookup = function() { 33673 var htm = $('<div> <h1 class="friendly-msg2" style="padding-top: 6px; font-size: larger;">' + SA.Resource.ProductLookup + '</h1>' 33674 + '<div class="friendly-msg2" style="min-width: 300px;">' 33675 + '<div style="margin-top: 20px; margin-bottom: 12px; padding-left: 20px; padding-right: 20px;">' + SA.Resource.LookupProduct + '</div>' 33676 + '<input type="text" id="inventory-product-lookup-autocomplete" style="padding: 8px; letter-spacing: 1px; font-size: 16px;"/>' 33677 + '</div> </div>'); 33678 33679 var ojpop = new GLO.Popup.Custom(htm); 33680 var jpop = ojpop.getPopup().addClass('no-persist'); 33681 var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" }); //.addClass('pop-buttons2'); 33682 jbtns.find('.btnSave').remove(); 33683 jbtns.find('.btnCancel').css({ "letter-spacing": "1px" }); 33684 33685 var top = UTIL.coalesceInt(jpop.css('top').replace('px', ''), 200); 33686 33687 if (top > 200) { 33688 jpop.css({ "top": "100px" }); 33689 } 33690 33691 var jsearch = jpop.find('#inventory-product-lookup-autocomplete'); 33692 33693 jsearch.autocomplete({ 33694 source: GLO.Link.Object.Provider.Ajax + 'ProductSearch', 33695 minLength: 2, 33696 select: function(event, ui) { 33697 ojpop.close(); 33698 GLO.Inventory.updateHash('edit-product', ui.item.id); 33699 } 33700 }); 33701 33702 jsearch.focus(); 33703 } 33704 33705 _conIItem.openAddBundleChildProduct = function(event) { 33706 //GLO.Mobile.getViewport(); return; //DEBUG ONLY. 33707 if (GLO.Sale.Keypad.mustOpenKeypad()) { return; } 33708 33709 $("#pop-quick-sell").modal(); 33710 33711 var jmodal = $("#simplemodal-container").css({ "top": "4px", "padding": "0", "border-radius": "20px" }); 33712 var jtxt = jmodal.find('#quick-sell-product-name'); 33713 33714 jmodal.find('a.modalCloseImg').css({ "top": "4px", "right": "6px" }); 33715 33716 if (GLO.Info.isMobile()) { 33717 var w = 360; 33718 33719 if (innerWidth < 370) { w = innerWidth * .96; } 33720 33721 var left = parseInt((innerWidth - w)/2) - 4 + 'px'; 33722 33723 $.modal.update(140, w);
33724 jmodal.css({ "top": "4px", "left": left }); 33725 jmodal.find('.modalCloseImg').attr("style", "top: 5px !important;"); 33726 } else { 33727 $.modal.update(150, 450); 33728 jmodal.css({ "top": "100px" }); 33729 jmodal.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" }); 33730 } 33731 33732 jtxt.autocomplete({ 33733 source: GLO.Link.Object.Provider.Ajax + 'ProductSearch', 33734 minLength: 2, 33735 autoFocus: true, 33736 open: function(event, ui) { 33737 $('.ui-autocomplete.auto-select-first-item').find('li:first').click(); 33738 }, 33739 select: function(event, ui) { 33740 var bundleChildProductEl = '<div data-id="' + ui.item.id + '" style="background-color: #ADD8E6;color: #000;border-radius: 5px;padding: 10px;font-size: 100%;">' + ui.item.value + ' - $' + ui.item.price_mn + '</div>' 33741 $('#bundle-product-items').append(bundleChildProductEl); 33742 GLO.Inventory.Item.addProductToBundle(ui.item.id) 33743 GLO.UI.Form.resetProcessing(); 33744 $.modal.close(); 33745 33746 } 33747 }); 33748 33749 jtxt.data("ui-autocomplete")._renderMenu = function(ul, items) { 33750 var that = this; 33751 33752 $.each(items, function(index, item) { 33753 that._renderItemData(ul, item); 33754 }); 33755 33756 $(ul).find("li:odd").addClass("odd"); 33757 33758 if (items.length === 1 && items[0].is_sku_upc_match_fl == 1) { 33759 $(ul).addClass('auto-select-first-item', true); 33760 } 33761 }; 33762 33763 jtxt.focus(); 33764 } 33765 33766 _conIItem.addProductToBundle = function(childInventoryId) { 33767 var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateBom'; 33768 // GLO.UI.Form.beginProcessing(); 33769 33770 var frm = $('#inventory-item-form'); 33771 var iid = frm.find('#Inventory_id').val(); 33772 33773 var jsonData = { 33774 "ParentInventoryId": iid, 33775 "ChildInventoryId": childInventoryId, 33776 "Quantity":1 33777 }; 33778 33779 33780 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData}) 33781 .success(function(data, textStatus, jqXHR) { 33782 if (UTIL.Validate.hasPermissionError(data)) { return; } 33783 // TODO:disable price and calculate total price 33784 $('#Price_mn').attr('disabled','disabled'); 33785 $('#Employee_Price_mn').attr('disabled','disabled') 33786 33787 33788 33789 }) 33790 .error(function(jqXHR, textStatus, errorThrown) { 33791 new GLO.Popup.Error('Unable to add child product at this time. Please try again later.'); 33792 GLO.UI.Form.resetProcessing(); 33793 }); 33794 } 33795 33796 33797 _conIItem.removeProductsFromBundle = function(parentInventoryId) { 33798 var uri = GLO.Link.Page.Provider.Home + 'Inventory/DeleteBom'; 33799 // GLO.UI.Form.beginProcessing(); 33800 33801 var frm = $('#inventory-item-form'); 33802 var iid = frm.find('#Inventory_id').val(); 33803 33804 var jsonData = { 33805 "ParentInventoryId": iid, 33806 "ChildInventoryId": 0, 33807 "Quantity":1 33808 }; 33809 33810 33811 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData}) 33812 .success(function(data, textStatus, jqXHR) { 33813 if (UTIL.Validate.hasPermissionError(data)) { return; } 33814 GLO.Inventory.Item.getBundleProducts(iid); 33815 33816 }) 33817 .error(function(jqXHR, textStatus, errorThrown) { 33818 new GLO.Popup.Error('Unable to delete child products at this time. Please try again later.'); 33819 GLO.UI.Form.resetProcessing(); 33820 }); 33821 } 33822 33823 _conIItem.getBundleProducts = function(inventoryId) { 33824 var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetBom?id=' + inventoryId; 33825 33826 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 33827 .done(function(data, textStatus, jqXHR) { 33828 window.onbeforeunload = null; 33829 if(data!=null && data!== '') { 33830 var childProducts = data; 33831 if (childProducts.length > 0) { 33832 $('#Price_mn').attr('disabled','disabled'); 33833 $('#Employee_Price_mn').attr('disabled','disabled'); 33834 $('#Avg_Cost_mn').attr("onclick",""); 33835 GLO.Inventory.Item.generateBundleProductChildProductsGrid(childProducts); 33836 } 33837 else { 33838 //display blank state 33839 resetChildProductsGrid(); 33840 $('#Price_mn').removeAttr('disabled'); 33841 $('#Employee_Price_mn').removeAttr('disabled'); 33842 $('#Avg_Cost_mn').attr("onclick","GLO.Inventory.Item.openCostPopup()"); 33843 } 33844 } else { 33845 new GLO.Popup.Error('Could not get the child products. Please try again later.'); 33846 } 33847 }) 33848 .fail(function(jqXHR, textStatus, errorThrown) { 33849 GLO.UI.Form.resetProcessing(); 33850 new GLO.Popup.Error('Could not get the product images'); 33851 }); 33852 } 33853 33854 var resetChildProductsGrid = function() { 33855 var childProductsGrid = $('#bundle-product-items'); 33856 childProductsGrid.html(""); 33857 } 33858 33859 _conIItem.generateBundleProductChildProductsGrid = function(childProducts) { 33860 33861 33862 resetChildProductsGrid(); 33863
33864 childProducts.forEach(childProduct => { 33865 var productMeta = ''; 33866 if (childProduct.Size) { 33867 productMeta = childProduct.Size + ' ' + childProduct.UnitofMeasure; 33868 } 33869 if (childProduct.VendorName) { 33870 productMeta = productMeta + ' (' + childProduct.VendorName + ')'; 33871 } 33872 var bundleChildProductEl = '<div data-id="' + childProduct.ChildInventoryId + '" style="background-color: #ADD8E6;color: #000;border-radius: 5px;padding: 10px;font-size: 100%;">' + childProduct.Name + ' ' + productMeta + ' - $' + childProduct.Price + '</div>' 33873 $('#bundle-product-items').append(bundleChildProductEl); 33874 }); 33875 } 33876 33877 return _conIItem; 33878})(); 33879 33880 33881GLO.Inventory.Location = (function() { 33882 function _cILocation() { } 33883 33884 _cILocation.initProductSummary = function(jpop) { 33885 var uls = jpop.find('ul.shipment-location-list'); 33886 33887 for (var i=0; i < uls.length; i++) { 33888 if (uls.eq(i).find('.event-location').length > 1) { 33889 uls.eq(i).sortable({ "update": GLO.Inventory.Location.updateSortOrder }).find('.ui-icon,.btnMove').disableSelection(); 33890 } 33891 } 33892 } 33893 33894 _cILocation.updateSortOrder = function(ev, dropObj) { 33895 //var id = dropObj.item.attr('id'); 33896 //var old_sort_sr = parseInt(dropObj.item.attr('sort_sr')); 33897 33898 var xml = '', ul = dropObj.item.closest('ul.shipment-location-list'); 33899 var list = ul.find('>li'); 33900 var parentEventId = ul.parent().attr('event_id'); 33901 var iid = $('#inventory-item-summary').find('h1').attr('inventory_id'); 33902 33903 for (var i=0; i < list.length; i++) { 33904 var id = list.eq(i).attr('sub_event_id'); 33905 33906 xml += '<li sub_event_id="' + id + '" sort_sr="' + (i + 100) + '"/>'; 33907 } 33908 33909 var uri = GLO.Link.Page.Provider.Home + 'Inventory/SortMoveProduct'; 33910 var ol = UTIL.htmlEncode('<ol>' + xml + '</ol>'); 33911 var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sort_xml": ol } 33912 33913 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 33914 .success(function(data, textStatus, jqXHR) { 33915 //alert("success:" + data + '\n\ndivID = ' + jDiv.html()); 33916 }) 33917 .error(function(jqXHR, textStatus, errorThrown) { 33918 //alert("error: updateSortOrder()\n" + textStatus); 33919 var abc = 123; 33920 }); 33921 } 33922 33923 _cILocation.openMove = function(btn) { 33924 var jPopItem = $('#inventory-item-summary'); 33925 var h1 = jPopItem.find('h1'); 33926 var iid = h1.attr('inventory_id'); 33927 var h1 = UTIL.coalesce($.trim(h1.text()), 'Product') + ' Location'; 33928 33929 var liMoveEvent = $(btn).closest('li.event-move'); 33930 var liOrderEvent = liMoveEvent.closest('li.recent-activity-order'); 33931 33932 var moveCount = UTIL.coalesceInt(liMoveEvent.find('.event-stock-count').text(), 0); 33933 var subEventId = UTIL.cleanString(liMoveEvent.attr('sub_event_id')); 33934 var sort = UTIL.cleanString(liMoveEvent.attr('sort_sr')); 33935 var note = UTIL.cleanString(liMoveEvent.find('.event-note').text()); 33936 var locationId = liMoveEvent.attr('location_id'); //create_dt, update_by_staff_id 33937 var isle = UTIL.cleanString(liMoveEvent.find('.event-isle > i').text()); 33938 var shelf = UTIL.cleanString(liMoveEvent.find('.event-shelf > i').text()); 33939 var rack = UTIL.cleanString(liMoveEvent.find('.event-rack > i').text()); 33940 33941 var orderCount = UTIL.coalesceInt(liOrderEvent.find('.event-count').text(), 0); 33942 var parentEventId = liOrderEvent.attr('event_id'); 33943 33944 var div = '<div id="pop-edit-move-event" inventory_id="' + iid + '" parent_event_id="' + parentEventId + '" sub_event_id="' + subEventId + '" sort_sr="' + sort + '">'; 33945 var htm = div + $('#item-move-location-edit').outerHTML() + '</div>'; 33946 33947 var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Inventory.Location.saveMove); 33948 jpop.find('#Move_Count_sr').val(moveCount).attr('max', orderCount); 33949 jpop.find('#Event_Note_vc').val(note); 33950 33951 jpop.find('#Location_id').val(locationId); 33952 jpop.find('#Isle_vc').val(isle); 33953 jpop.find('#Shelf_vc').val(shelf); 33954 jpop.find('#Rack_vc').val(rack); 33955 } 33956 _cILocation.saveMove = function() { 33957 var uri = GLO.Link.Page.Provider.Home + 'Inventory/MoveProduct'; 33958 var jpop = $('#pop-edit-move-event'); 33959 33960 var iid = jpop.attr('inventory_id'), parentEventId = jpop.attr('parent_event_id'), subEventId = jpop.attr('sub_event_id'), sort = jpop.attr('sort_sr'); 33961 var moveCount = UTIL.coalesceInt(jpop.find('#Move_Count_sr').val(), 0); 33962 33963 var locationId = jpop.find('#Location_id').val(); 33964 var isle = UTIL.htmlEncode(jpop.find('#Isle_vc').val()); 33965 var shelf = UTIL.htmlEncode(jpop.find('#Shelf_vc').val()); 33966 var rack = UTIL.htmlEncode(jpop.find('#Rack_vc').val()); 33967 var note = UTIL.htmlEncode(jpop.find('#Event_Note_vc').val()); 33968 33969 var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sub_event_id": subEventId, "count": moveCount 33970 , "location_id": locationId, "isle": isle, "shelf": shelf, "rack": rack, "note": note }; 33971 33972 jpop = jpop.closest('.glopop'); 33973 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 33974
33975 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 33976 .success(function(data, textStatus, jqXHR) { 33977 if (UTIL.Validate.hasPermissionError(data)) { return; } 33978 33979 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 33980 GLO.Popup.Warning.open(data, 'Move Invalid'); 33981 return; 33982 } 33983 33984 GLO.Popup.close(jpop); 33985 var jPopItem = $('#inventory-item-summary').closest('.simplemodal-container'); 33986 33987 if (jPopItem.length) { 33988 $.modal.close(); 33989 } 33990 33991 GLO.Popup.Success.open('Location Saved'); 33992 //jpop.find('.btnSave a').css({ "border": "3px solid transparent" }); 33993 }) 33994 .error(function(jqXHR, textStatus, errorThrown) { 33995 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 33996 GLO.UI.Form.resetProcessing(); 33997 }); 33998 } 33999 _cILocation.removeMove = function(btn) { 34000 var fnYes = function() { 34001 GLO.Inventory.Location.removeMoveConfirmed(btn); 34002 } 34003 var htm = 'Remove these products from this location?'; 34004 GLO.Popup.Confirm.open(htm, 'Remove From Location?', fnYes); 34005 } 34006 _cILocation.removeMoveConfirmed = function(btn) { 34007 var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveMoveProduct'; 34008 var liMoveEvent = $(btn).closest('li.event-move'); 34009 34010 var iid = $('#inventory-item-summary').closest('.simplemodal-container').find('h1').attr('inventory_id'); 34011 var subEventId = liMoveEvent.attr('sub_event_id'); 34012 var parentEventId = liMoveEvent.closest('li.recent-activity-order').attr('event_id'); 34013 var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sub_event_id": subEventId }; 34014 34015 var jprocessing = GLO.Popup.Processing.open('Remove products...', 'Product Location'); 34016 34017 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 34018 .success(function(data, textStatus, jqXHR) { 34019 if (UTIL.Validate.hasPermissionError(data)) { return; } 34020 34021 if (!UTIL.isEmpty($(data).attr('warning_cd'))) { 34022 GLO.Popup.Warning.open(data, 'Move Invalid'); 34023 return; 34024 } 34025 34026 jprocessing.close(); 34027 var jPopItem = $('#inventory-item-summary').closest('.simplemodal-container'); 34028 34029 if (jPopItem.length) { 34030 $.modal.close(); 34031 } 34032 34033 GLO.Popup.Success.open('Products Removed from Location'); 34034 //jpop.find('.btnSave a').css({ "border": "3px solid transparent" }); 34035 }) 34036 .error(function(jqXHR, textStatus, errorThrown) { 34037 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34038 GLO.UI.Form.resetProcessing(); 34039 }); 34040 } 34041 34042 _cILocation.openBasicHelp = function(id) { 34043 var msg = 'The order location fields (location, isle, shelf, rack) allow you to enter where you stocked this order so you can easily locate it when needed'; 34044 GLO.Popup.Info.open(msg, 'Order Location'); 34045 } 34046 34047 _cILocation.openList = function() { 34048 var list = '', jd = $('#order-editable-fields select#Location_id option'); 34049 34050 if (jd.length > 1) { 34051 for (var i=1; i < jd.length; i++) { 34052 list += '<li location_id="' + jd.eq(i).attr('value') + '">' + jd.eq(i).text() + '</li>'; 34053 } 34054 34055 $('#inventory-location-list').removeClass('hide').find('ul').html(list); 34056 } else { 34057 GLO.Inventory.updateHash('new-location') 34058 } 34059 } 34060 34061 _cILocation.openEdit = function(id, name) { 34062 var j = $('#inventory-location-edit'); 34063 34064 if (!UTIL.isEmpty(id)) { 34065 var h2 = 'Edit Location'; 34066 j.find('.btnDelete').removeClass('hide'); 34067 } else { 34068 var h2 = 'New Location'; 34069 j.find('.btnDelete').addClass('hide');
34070 id = name = ''; 34071 } 34072 34073 j.find('#Location_Name_vc').val(name); 34074 j.attr('location_id', id); 34075 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34076 j.removeClass('hide'); 34077 j.find('input:first').focus(); 34078 } 34079 34080 _cILocation.back = function(isEdit) { 34081 if (isEdit && $('#order-editable-fields select#Location_id option').length > 0) { 34082 GLO.Inventory.updateHash('location-list'); 34083 return; 34084 } else if (!UTIL.isEmpty(GLO.Inventory.prevHash)) { 34085 var prev = GLO.Inventory.prevHash.toLowerCase(); 34086 34087 if (prev.indexOf('new-location') === -1 && prev.indexOf('edit-location') === -1) { 34088 GLO.Inventory.updateHash(GLO.Inventory.prevHash); 34089 return; 34090 } 34091 } 34092 34093 GLO.Inventory.updateHash('order-create'); 34094 } 34095 34096 _cILocation.save = function() { 34097 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Location'; 34098 var j = $('#inventory-location-edit'); 34099 34100 var id = j.attr('location_id'); 34101 var nm = j.find('#Location_Name_vc').val(); 34102 34103 if (UTIL.isEmpty(nm)) { 34104 GLO.Popup.Warning('Please enter a location name', function() { $('#inventory-location-edit #Location_Name_vc').focus(); }); 34105 return; 34106 } 34107 34108 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34109 34110 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id, "name": nm } }) 34111 .success(function(data, textStatus, jqXHR) { 34112 if (UTIL.Validate.hasPermissionError(data)) { return; } 34113 34114 GLO.Popup.Success.open('Location Saved'); 34115 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34116 34117 if (UTIL.isEmpty(id)) { 34118 var newOption = '<option value="' + $(data).attr('location_id') + '">' + nm + '</option>'; 34119 $('select#Location_id').find('option:first').after(newOption); 34120 } else { 34121 $('select#Location_id option[value="' + id + '"]').text(nm); 34122 location.reload(); 34123 } 34124 34125 GLO.Inventory.updateHash('location-list'); 34126 }) 34127 .error(function(jqXHR, textStatus, errorThrown) { 34128 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34129 GLO.UI.Form.resetProcessing(); 34130 }); 34131 } 34132 34133 _cILocation.remove = function() { 34134 var uri = GLO.Link.Page.Provider.Home + 'Inventory/LocationDelete'; 34135 var id = $('#inventory-location-edit').attr('location_id'); 34136 GLO.UI.Form.beginProcessing( $('#inventory-location-edit .btnDelete') ); 34137 34138 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 34139 .success(function(data, textStatus, jqXHR) { 34140 if (UTIL.Validate.hasPermissionError(data)) { return; } 34141 34142 var jdata = $(data); 34143 34144 if (jdata.attr('error_cd')) { 34145 GLO.Popup.Warning.open(jdata, 'Delete Location'); 34146 } else { 34147 GLO.Popup.Success.open('Location Deleted'); 34148 $('select#Location_id option[value="' + id + '"]').remove(); 34149 34150 GLO.Inventory.updateHash('location-list'); 34151 } 34152 }) 34153 .error(function(jqXHR, textStatus, errorThrown) { 34154 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34155 GLO.UI.Form.resetProcessing(); 34156 }); 34157 } 34158 34159 return _cILocation; 34160})(); 34161 34162 34163GLO.Inventory.Vendor = (function() { 34164 function _conVendor() { } 34165 34166 _conVendor.back = function() { 34167 GLO.Inventory.Item.unHide(); 34168 } 34169 34170 _conVendor.openEdit = function(id, name, distributorId, distributorName) { 34171 //$('#inventory-item-form:visible').addClass('hide'); 34172 //$('#inventory-vendor-list:visible').addClass('hide'); 34173 34174 var j = $('#inventory-vendor-edit'); 34175 34176 if (!UTIL.isEmpty(id)) {
34177 var h2 = SA.Resource.EditBrand; 34178 j.find('.btnDelete').removeClass('hide'); 34179 34180 if (!UTIL.isEmpty(distributorId)) { distributorName = ''; } 34181 } else { 34182 var h2 = SA.Resource.NewBrand; 34183 j.find('.btnDelete').addClass('hide'); 34184 34185 id = name = distributorId = distributorName = ''; 34186 } 34187 34188 j.find('#Vendor_Name_vc').val(name); 34189 j.find('#Vendor_id').val(id); 34190 34191 j.find('#Distributor_id').val(distributorId); 34192 j.find('#New_Distributor_vc').val(distributorName); 34193 34194 if (j.find('#Distributor_id option').length > 0) { 34195 j.find('#inventory-distributor-existing').removeClass('hide'); 34196 j.find('#inventory-distributor-or').removeClass('hide'); 34197 } else { 34198 j.find('#inventory-distributor-existing').addClass('hide'); 34199 j.find('#inventory-distributor-or').addClass('hide'); 34200 } 34201 34202 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34203 j.removeClass('hide'); 34204 j.find('input:first').focus(); 34205 } 34206 34207 _conVendor.openList = function() { 34208 var jd = $('select#Vendor_id option'); 34209 34210 if (jd.length > 0) { 34211 var dlist = ''; 34212 34213 for (var i=1; i < jd.length; i++) { 34214 var vid = jd.eq(i).attr('value'); 34215 var did = $.trim(jd.eq(i).attr('distributor_id')); 34216 var liCSS = '', vendorMerchantId = jd.eq(i).attr('vendor_merchant_id'); 34217 var vname = jd.eq(i).text(); 34218 34219 if (vendorMerchantId > 0) { 34220 var merchant = UserPortal.Price.Payment.getMerchant(vendorMerchantId); 34221 34222 if (merchant && merchant.name) { 34223 var merchantName = UTIL.coalesceString(merchant.friendly_name, merchant.name); 34224 liCSS = 'has-custom-product-merchant'; 34225 vname += '<span class="merchant-name-icon"><b>' + merchantName + '</b></span>'; 34226 } 34227 } 34228 34229 dlist += '<li class="' + liCSS + '" vendor_id="' + vid + '" distributor_id="' + did + '">' + vname + '</li>'; 34230 } 34231 34232 $('#inventory-vendor-list').removeClass('hide').find('ul').html(dlist); 34233 } else { 34234 _conVendor.openEdit(); 34235 } 34236 } 34237 34238 _conVendor.openDistributorList = function() { 34239 var jd = $('select#Distributor_id option'); 34240 34241 if (jd.length > 0) { 34242 var dlist = ''; 34243 34244 for (var i=1; i < jd.length; i++) { 34245 dlist += '<li distributor_id="' + jd.eq(i).attr('value') + '">' + jd.eq(i).text() + '</li>'; 34246 } 34247 34248 $('#inventory-distributor-list').removeClass('hide').find('ul').html(dlist); 34249 } else { 34250 _conVendor.openEdit(); 34251 } 34252 } 34253 34254 _conVendor.openDistributorEdit = function(id, nm) { 34255 var j = $('#inventory-distributor-edit'); 34256 34257 if (!UTIL.isEmpty(id)) { 34258 j.find('.btnDelete').removeClass('hide'); 34259 34260 j.find('tr').attr('distributor_id', id); 34261 j.find('#Distributor_Name_vc').val(nm); //$('select#Distributor_id option[value="' + id + '"]').text() 34262 } else { 34263 j.find('.btnDelete').addClass('hide'); 34264 34265 j.find('tr').attr('distributor_id', ''); 34266 j.find('#Distributor_Name_vc').val(''); 34267 } 34268 34269 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34270 j.removeClass('hide'); 34271 j.find('input:first').focus(); 34272 } 34273 34274 _conVendor.backFromDistributor = function() { 34275 GLO.Inventory.Item.unHide(); 34276 } 34277 34278 _conVendor.saveDistributor = function() { 34279 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Distributor'; 34280 var j = $('#inventory-distributor-edit'); 34281 34282 var distributorId = j.find('tr').attr('distributor_id'); 34283 var distributorName = j.find('#Distributor_Name_vc').val(); 34284 34285 if (UTIL.isEmpty(distributorName)) { 34286 GLO.Popup.Warning(SA.Resource.PleaseDistributorName, function() { $('#inventory-distributor-edit #Distributor_Name_vc').focus(); }); 34287 return; 34288 } 34289 34290 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34291
34292 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": distributorId, "name": distributorName } }) 34293 .success(function(data, textStatus, jqXHR) { 34294 if (UTIL.Validate.hasPermissionError(data)) { return; } 34295 34296 new GLO.Popup.Success(SA.Resource.DistributorSaved); 34297 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34298 34299 if (UTIL.isEmpty(distributorId)) { 34300 distributorId = $(data).attr('distributor_id'); 34301 34302 $('#inventory-vendor-edit').find('#Distributor_id').find('option:first').after('<option value="' + distributorId + '">' + distributorName + '</option>'); 34303 $('#Filter_Company').find('option:first').after('<option class="d-option" value="d' + distributorId + '">' + distributorName + '</option>'); 34304 } else { 34305 $('#inventory-vendor-edit').find('#Distributor_id option[value="' + distributorId + '"]').text(distributorName); 34306 $('#Filter_Company').find('option[value="d' + distributorId + '"]').text(distributorName); 34307 } 34308 34309 GLO.Inventory.updateHash('distributor-list'); 34310 }) 34311 .error(function(jqXHR, textStatus, errorThrown) { 34312 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34313 GLO.UI.Form.resetProcessing(); 34314 }); 34315 } 34316 34317 _conVendor.removeDistributor = function() { 34318 var uri = GLO.Link.Page.Provider.Home + 'Inventory/DistributorDelete'; 34319 var j = $('#inventory-distributor-edit'); 34320 34321 var distributorId = j.find('tr').attr('distributor_id'); 34322 var distributorName = j.find('#Distributor_Name_vc'); 34323 GLO.UI.Form.beginProcessing(j.find('.btnDelete')); 34324 34325 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": distributorId } }) 34326 .success(function(data, textStatus, jqXHR) { 34327 if (UTIL.Validate.hasPermissionError(data)) { return; } 34328 34329 var jdata = $(data); 34330 34331 if (jdata.attr('error_cd')) { 34332 var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Distributor'); 34333 ojpop.addScrollBar(); 34334 } else { 34335 new GLO.Popup.Success(SA.Resource.DistributorRemoved); 34336 $('select#Distributor_id option[value="' + distributorId + '"]').remove(); 34337 $('#Filter_Company').find('option[value="d' + distributorId + '"]').remove(); 34338 34339 GLO.Inventory.updateHash('distributor-list'); 34340 } 34341 }) 34342 .error(function(jqXHR, textStatus, errorThrown) { 34343 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34344 GLO.UI.Form.resetProcessing(); 34345 }); 34346 } 34347 34348 _conVendor.save = function() { 34349 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Vendor'; 34350 var j = $('#inventory-vendor-edit'); 34351 34352 var vid = j.find('#Vendor_id').val(); 34353 var vnm = j.find('#Vendor_Name_vc').val(); 34354 34355 var did = j.find('#Distributor_id').val(); 34356 var dnm = j.find('#New_Distributor_vc').val(); 34357 34358 if (UTIL.isEmpty(vnm)) { 34359 GLO.Popup.Warning(SA.Resource.PleaseEnterBrandName, function() { $('#inventory-vendor-edit #Vendor_Name_vc').focus(); }); 34360 return; 34361 } 34362 34363 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34364 34365 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "vid": vid, "vname": vnm, "did": did, "dname": dnm } }) 34366 .success(function(data, textStatus, jqXHR) { 34367 if (UTIL.Validate.hasPermissionError(data)) { return; } 34368 34369 new GLO.Popup.Success(SA.Resource.BrandSaved); 34370 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34371 34372 var jdata = $(data); 34373 34374 if (!UTIL.isEmpty(vid)) { 34375 document.location = GLO.Link.Page.Provider.Home + 'inventory#action=vendor-list'; 34376 new GLO.Popup.Processing('Loading Update...'); 34377 location.reload(); 34378 return; 34379 } else { 34380 var newOption = '<option value="' + jdata.attr('vendor_id') + '" distributor_id="' + jdata.attr('distributor_id') + '">' + vnm + '</option>'; 34381 34382 $('select#Vendor_id').find('option:first').after(newOption); 34383 $('select#Existing_Vendor_id').find('option:first').after(newOption); 34384 34385 var filterOption = '<option class="v-option" value="v' + jdata.attr('vendor_id') + '">' + GLO.Inventory.filterIndent + vnm + '</option>'; 34386 $('select#Filter_Company').find('option:first').after(filterOption); 34387 } 34388 34389 if (UTIL.isEmpty(did) && !UTIL.isEmpty(dnm)) { 34390 $('select#Distributor_id').prepend('<option value="' + jdata.attr('distributor_id') + '">' + dnm + '</option>'); 34391 $('select#Filter_Company').prepend('<option class="d-option" value="d' + jdata.attr('distributor_id') + '">' + dnm + '</option>'); 34392 } 34393 34394 GLO.Inventory.updateHash('vendor-list'); 34395 }) 34396 .error(function(jqXHR, textStatus, errorThrown) { 34397 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34398 GLO.UI.Form.resetProcessing(); 34399 }); 34400 } 34401 34402 _conVendor.remove = function() { 34403 var uri = GLO.Link.Page.Provider.Home + 'Inventory/VendorDelete'; 34404 var j = $('#inventory-vendor-edit'); 34405 var id = j.find('#Vendor_id').val(); 34406 GLO.UI.Form.beginProcessing(j.find('.btnDelete')); 34407
34408 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 34409 .success(function(data, textStatus, jqXHR) { 34410 if (UTIL.Validate.hasPermissionError(data)) { return; } 34411 34412 var jdata = $(data); 34413 34414 if (jdata.attr('error_cd')) { 34415 var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Brand'); 34416 ojpop.addScrollBar(); 34417 } else { 34418 new GLO.Popup.Success(SA.Resource.BrandRemoved); 34419 $('#inventory-item-edit').find('#Vendor_id option[value="' + id + '"]').remove(); 34420 $('#inventory-product-line-edit').find('#Existing_Vendor_id option[value="' + id + '"]').remove(); 34421 $('select#Filter_Company').find('option[value="v' + id + '"]').remove(); 34422 34423 GLO.Inventory.updateHash('vendor-list'); 34424 } 34425 }) 34426 .error(function(jqXHR, textStatus, errorThrown) { 34427 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34428 GLO.UI.Form.resetProcessing(); 34429 }); 34430 } 34431 34432 _conVendor.openProductLineEdit = function(id, name, vendorId, vendorName) { 34433 var j = $('#inventory-product-line-edit'); 34434 34435 if (!UTIL.isEmpty(id)) { 34436 var h2 = SA.Resource.EditProductLine; 34437 j.find('.btnDelete').removeClass('hide'); 34438 34439 if (!UTIL.isEmpty(vendorId)) { 34440 var vname = $('select#Vendor_id option[value="' + vendorId + '"]').text(); 34441 vendorName = ''; 34442 } else { 34443 var vname = vendorName; 34444 } 34445 34446 name = name.replace(vname + ' - ', ''); 34447 } else { 34448 var h2 = SA.Resource.NewProductLine; 34449 j.find('.btnDelete').addClass('hide'); 34450 34451 id = name = vendorId = vendorName = ''; 34452 } 34453 34454 j.find('#Product_Line_Name_vc').val(name); 34455 j.find('#Product_Line_id').val(id); 34456 34457 j.find('#Existing_Vendor_id').val(vendorId); 34458 j.find('#New_PL_Vendor_vc').val(vendorName); 34459 34460 if (j.find('#Existing_Vendor_id option').length > 0) { 34461 j.find('#inventory-vendor-existing').removeClass('hide'); 34462 j.find('#inventory-vendor-or').removeClass('hide'); 34463 } else { 34464 j.find('#inventory-vendor-existing').addClass('hide'); 34465 j.find('#inventory-vendor-or').addClass('hide'); 34466 } 34467 34468 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34469 j.removeClass('hide'); 34470 j.find('input:first').focus(); 34471 } 34472 34473 _conVendor.openProductLineList = function(isBackground) { 34474 var jpl = $('select#Product_Line_id option'); 34475 34476 if (jpl.length > 0) { 34477 var vname, vendorId, pllist = ''; 34478 var jv = $('select#Vendor_id'); 34479 34480 for (var i=1; i < jpl.length; i++) { 34481 vendorId = jpl.eq(i).attr('vendor_id'); 34482 vname = jv.find('option[value="' + vendorId + '"]').text(); 34483 34484 if (!UTIL.isEmpty(vname)) { vname = vname + ' - '; } else { vname = ''; } 34485 34486 pllist += '<li product_line_id="' + jpl.eq(i).attr('value') + '" vendor_id="' + vendorId + '">' + vname + jpl.eq(i).text() + '</li>'; 34487 } 34488 34489 var plines = $('#inventory-product-line-list'); 34490 plines.find('ul').html(pllist); 34491 34492 if (!isBackground) { 34493 plines.removeClass('hide'); 34494 } 34495 } else if (!isBackground) { 34496 _conVendor.openProductLineEdit(); 34497 } 34498 } 34499 34500 _conVendor.removeProductLine = function() { 34501 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ProductLineDelete'; 34502 var j = $('#inventory-product-line-edit'); 34503 var id = j.find('#Product_Line_id').val(); 34504 GLO.UI.Form.beginProcessing(j.find('.btnDelete')); 34505 34506 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 34507 .success(function(data, textStatus, jqXHR) { 34508 if (UTIL.Validate.hasPermissionError(data)) { return; } 34509 34510 var jdata = $(data); 34511 34512 if (jdata.attr('error_cd')) { 34513 var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Product Line'); 34514 ojpop.addScrollBar(); 34515 } else { 34516 new GLO.Popup.Success(SA.Resource.ProductLineRemoved); 34517 $('#inventory-item-edit').find('#Product_Line_id option[value="' + id + '"]').remove(); 34518 $('select#Filter_Company').find('option[value="p' + id + '"]').remove(); 34519 34520 GLO.Inventory.updateHash('product-line-list'); 34521 } 34522 }) 34523 .error(function(jqXHR, textStatus, errorThrown) { 34524 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34525 GLO.UI.Form.resetProcessing(); 34526 }); 34527 } 34528 34529 _conVendor.saveProductLine = function() { 34530 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ProductLine'; 34531 var j = $('#inventory-product-line-edit'); 34532 34533 var plid = j.find('#Product_Line_id').val(); 34534 var plnm = j.find('#Product_Line_Name_vc').val(); 34535 34536 var vid = j.find('#Existing_Vendor_id').val();
34537 var vnm = j.find('#New_PL_Vendor_vc').val(); 34538 34539 if (UTIL.isEmpty(plnm)) { 34540 GLO.Popup.Warning(SA.Resource.PleaseEnterProductLineName, function() { $('#inventory-product-line-edit #Product_Line_Name_vc').focus(); }); 34541 return; 34542 } else if (UTIL.isEmpty(vnm) && UTIL.isEmpty(vid)) { 34543 GLO.Popup.Warning(SA.Resource.PleaseSelectBrand, function() { $('#inventory-product-line-edit #Existing_Vendor_id').focus(); }); 34544 return; 34545 } 34546 34547 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34548 34549 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "plid": plid, "plname": plnm, "vid": vid, "vname": vnm } }) 34550 .success(function(data, textStatus, jqXHR) { 34551 if (UTIL.Validate.hasPermissionError(data)) { return; } 34552 34553 new GLO.Popup.Success(SA.Resource.ProductLineSaved); 34554 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34555 34556 var jdata = $(data); 34557 34558 if (!UTIL.isEmpty(plid)) { 34559 document.location = GLO.Link.Page.Provider.Home + 'inventory#action=product-line-list'; 34560 new GLO.Popup.Processing('Loading Update...'); 34561 location.reload(); 34562 return; 34563 34564 /* 34565 $('select#Product_Line_id option[value="' + plid + '"]').text(plnm).attr('vendor_id', UTIL.cleanString(jdata.attr('vendor_id'))); 34566 $('select#Filter_Company').find('option[value="p' + plid + '"]').text(GLO.Inventory.filterIndent + GLO.Inventory.filterIndent + plnm); 34567 34568 var jtds = $('#inventory-table').find('.item-product-line[product_line_id="' + plid + '"]'); 34569 34570 for (var i=0; i < jtds.length; i++) { 34571 jtds.eq(i).text(plnm).attr('title', ''); 34572 } 34573 */ 34574 } else { 34575 var vid = jdata.attr('vendor_id'); 34576 var plOption = '<option class="pl-option" value="p' + jdata.attr('product_line_id') + '">' + GLO.Inventory.filterIndent + plnm + '</option>'; 34577 34578 $('select#Product_Line_id').find('option:first').after('<option value="' + jdata.attr('product_line_id') + '" vendor_id="' + vid + '">' + plnm + '</option>'); 34579 $('select#Filter_Company').find('option[value="v' + vid + '"]').after(plOption); 34580 } 34581 34582 if (UTIL.isEmpty(vid) && !UTIL.isEmpty(vnm)) { 34583 $('select#Vendor_id').find('option:first').after('<option value="' + jdata.attr('vendor_id') + '">' + vnm + '</option>'); 34584 $('select#Existing_Vendor_id').find('option:first').after('<option value="' + jdata.attr('vendor_id') + '">' + vnm + '</option>'); 34585 34586 $('select#Filter_Company').find('option:first').after('<option class="v-option" value="v' + jdata.attr('vendor_id') + '">' + GLO.Inventory.filterIndent + vnm + '</option>'); 34587 } 34588 34589 GLO.Inventory.updateHash('product-line-list'); 34590 }) 34591 .error(function(jqXHR, textStatus, errorThrown) { 34592 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34593 GLO.UI.Form.resetProcessing(); 34594 }); 34595 } 34596 34597 _conVendor.getSelected = function(jHead) { 34598 var obj = {}, co = jHead.find('#Filter_Company').val(); 34599 34600 if (!UTIL.isEmpty(co)) { 34601 if (co.substring(0, 1) === 'v') { 34602 obj.vendor_id = co.substring(1); 34603 } else if (co.substring(0, 1) === 'd') { 34604 obj.distributor_id = co.substring(1); 34605 } else if (co.substring(0, 1) === 'p') { 34606 obj.vendor_id = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id'); 34607 } 34608 } 34609 34610 return obj; 34611 } 34612 34613 return _conVendor; 34614})(); 34615 34616 34617GLO.Inventory.Type = (function() { 34618 function _conType() { } 34619 34620 _conType.back = function() { 34621 GLO.Inventory.Item.unHide(); 34622 } 34623 34624 _conType.openEdit = function(id, name, categoryId, categoryName) { 34625 var j = $('#inventory-type-edit'); 34626 34627 if (!UTIL.isEmpty(id)) { 34628 j.find('.btnDelete').removeClass('hide'); 34629 34630 if (!UTIL.isEmpty(categoryId)) { categoryName = ''; } 34631 } else { 34632 j.find('.btnDelete').addClass('hide'); 34633
34634 id = name = categoryId = categoryName = ''; 34635 } 34636 34637 j.find('#Type_Category_id').val(categoryId); 34638 j.find('#New_Type_Category_Name_vc').val(categoryName); 34639 34640 if (UTIL.isEmpty(categoryName)) { categoryName = j.find('#Type_Category_id option:selected').text(); } 34641 name = name.replace(categoryName + " - ", "") 34642 34643 j.find('#Type_Name_vc').val(name); 34644 j.find('tr').attr('inventory_type_id', id); 34645 34646 if (j.find('#Type_Category_id option').length > 0) { 34647 j.find('#inventory-type-category-existing').removeClass('hide'); 34648 j.find('#inventory-type-category-or').removeClass('hide'); 34649 } else { 34650 j.find('#inventory-type-category-existing').addClass('hide'); 34651 j.find('#inventory-type-category-or').addClass('hide'); 34652 } 34653 34654 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34655 j.removeClass('hide'); 34656 j.find('input:first').focus(); 34657 } 34658 34659 _conType.openList = function() { 34660 var jd = $('select#Inventory_Type_id option'); 34661 34662 if (jd.length > 0) { 34663 var dlist = ''; 34664 34665 for (var i=1; i < jd.length; i++) { 34666 var otherAttributes = '', defaultTypeId = jd.eq(i).attr('default_type_id'), defaultCategoryId = jd.eq(i).attr('default_type_category_id'); 34667 34668 if (UTIL.isNumber(defaultTypeId)) { 34669 otherAttributes += ' default_type_id="' + defaultTypeId + '"'; 34670 } 34671 if (UTIL.isNumber(defaultCategoryId)) { 34672 otherAttributes += ' default_type_category_id="' + defaultCategoryId + '"'; 34673 } 34674 34675 dlist += '<li inventory_type_id="' + jd.eq(i).attr('value') + '" type_category_id="' + jd.eq(i).attr('type_category_id') + '"' + otherAttributes + '>' + jd.eq(i).text() + '</li>'; 34676 } 34677 34678 $('#inventory-type-list').removeClass('hide').find('ul').html(dlist); 34679 } else { 34680 _conType.openEdit(); 34681 } 34682 } 34683 34684 _conType.openCategoryList = function() { 34685 var jd = $('select#Type_Category_id option'); 34686 34687 if (jd.length > 0) { 34688 var dlist = ''; 34689 34690 for (var i=1; i < jd.length; i++) { 34691 var otherAttributes = '', defaultCategoryId = jd.eq(i).attr('default_type_category_id'); 34692 34693 if (UTIL.isNumber(defaultCategoryId)) { 34694 otherAttributes += ' default_type_category_id="' + defaultCategoryId + '"'; 34695 } 34696 34697 dlist += '<li type_category_id="' + jd.eq(i).attr('value') + '"' + otherAttributes + '>' + jd.eq(i).text() + '</li>'; 34698 } 34699 34700 $('#inventory-type-category-list').removeClass('hide').find('ul').html(dlist); 34701 } else { 34702 _conType.openEdit(); 34703 } 34704 } 34705 34706 _conType.openCategoryEdit = function(id, nm) { 34707 var j = $('#inventory-type-category-edit'); 34708 34709 if (!UTIL.isEmpty(id)) { 34710 j.find('.btnDelete').removeClass('hide'); 34711 34712 j.find('tr').attr('type_category_id', id); 34713 j.find('#Type_Category_Name_vc').val(nm); 34714 } else { 34715 j.find('.btnDelete').addClass('hide'); 34716 34717 j.find('tr').attr('type_category_id', ''); 34718 j.find('#Type_Category_Name_vc').val(''); 34719 } 34720 34721 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34722 j.removeClass('hide'); 34723 j.find('input:first').focus(); 34724 } 34725 34726 _conType.getGiftCardCategory = function() { 34727 var jcat = $('select#Type_Category_id option[default_type_category_id = 41]'); 34728 return jcat.attr('value'); 34729 } 34730 _conType.getGiftCardSubCategory = function(isVoucher) { 34731 if (isVoucher) { 34732 var typeId = 116; 34733 } else { 34734 var typeId = 115; 34735 } 34736 34737 var jtype = $('select#Inventory_Type_id option[default_type_id = ' + typeId + ']'); 34738 return jtype.attr('value'); 34739 } 34740 34741 _conType.saveCategory = function() { 34742 var j = $('#inventory-type-category-edit'); 34743 var id = j.find('tr').attr('type_category_id'); 34744 var nm = j.find('#Type_Category_Name_vc').val(); 34745 34746 if (UTIL.isEmpty(nm)) { 34747 GLO.Popup.Warning(SA.Resource.PleaseEnterCategoryName, function() { $('#inventory-type-category-edit #Type_Category_Name_vc').focus(); }); 34748 return; 34749 } 34750 34751 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34752 _saveCategory(j, nm, id, 'type-category-list'); 34753 } 34754 34755 function _saveCategory(jContainer, categoryName, categoryId, gotoHash) { 34756 var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeCategory'; 34757
34758 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": categoryId, "name": categoryName } }) 34759 .success(function(data, textStatus, jqXHR) { 34760 if (UTIL.Validate.hasPermissionError(data)) { return; } 34761 34762 new GLO.Popup.Success(SA.Resource.CategorySaved); 34763 jContainer.find('.btnSave a').css({ "border": "3px solid transparent" }); 34764 34765 if (UTIL.isEmpty(categoryId)) { 34766 categoryId = $(data).attr('type_category_id'); 34767 $('select#Type_Category_id').find('option:first').after('<option value="' + categoryId + '">' + categoryName + '</option>'); 34768 $('select#Filter_Category').find('option:first').after('<option class="c-option" value="c' + categoryId + '">' + categoryName + '</option>'); 34769 } else { 34770 $('select#Type_Category_id option[value="' + categoryId + '"]').text(categoryName); 34771 $('select#Filter_Category').find('option[value="c' + categoryId + '"]').text(categoryName); 34772 34773 var jtds = $('#inventory-table').find('.item-type-category[type_category_id="' + categoryId + '"]'); 34774 34775 for (var i=0; i < jtds.length; i++) { 34776 jtds.eq(i).text(categoryName).attr('title', ''); 34777 } 34778 } 34779 34780 GLO.Inventory.updateHash(gotoHash); 34781 }) 34782 .error(function(jqXHR, textStatus, errorThrown) { 34783 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34784 GLO.UI.Form.resetProcessing(); 34785 }); 34786 } 34787 34788 _conType.removeCategory = function() { 34789 var j = $('#inventory-type-category-edit tr'); 34790 var id = j.attr('type_category_id'); 34791 var nm = $('#Type_Category_Name_vc').val(); 34792 34793 new GLO.Popup.Confirm(SA.Resource.ConfirmDeleteCategory + ' <b style="color: #4F81BD">' + nm + '</b>', function(){ 34794 GLO.Inventory.Type.removeCategoryConfirmed(id); 34795 }); 34796 } 34797 34798 _conType.removeCategoryConfirmed = function(id) { 34799 var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeCategoryDelete'; 34800 GLO.UI.Form.beginProcessing( $('#inventory-type-category-edit .btnDelete') ); 34801 34802 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 34803 .success(function(data, textStatus, jqXHR) { 34804 if (UTIL.Validate.hasPermissionError(data)) { return; } 34805 34806 var jdata = $(data); 34807 34808 if (jdata.attr('error_cd')) { 34809 new GLO.Popup.Warning(jdata.outerHTML()); 34810 } else { 34811 new GLO.Popup.Success(SA.Resource.CategoryDeleted); 34812 $('select#Type_Category_id option[value="' + id + '"]').remove(); 34813 $('select#Filter_Category').find('option[value="c' + id + '"]').remove(); 34814 34815 GLO.Inventory.updateHash('type-category-list'); 34816 } 34817 }) 34818 .error(function(jqXHR, textStatus, errorThrown) { 34819 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34820 GLO.UI.Form.resetProcessing(); 34821 }); 34822 } 34823 34824 _conType.save = function() { 34825 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Type'; 34826 var j = $('#inventory-type-edit'); 34827 34828 var tid = j.find('tr').attr('inventory_type_id'); 34829 var tnm = j.find('#Type_Name_vc').val(); 34830 34831 var tcid = j.find('#Type_Category_id').val(); 34832 var tcnm = j.find('#New_Type_Category_Name_vc').val(); 34833 34834 if (UTIL.isEmpty(tnm)) { 34835 GLO.Popup.Warning(SA.Resource.PleaseEnterTypeName, function() { $('#inventory-type-edit #Type_Name_vc').focus(); }); 34836 return; 34837 } else if (UTIL.isEmpty(tcid) && UTIL.isEmpty(tcnm)) { 34838 tcnm = tnm; 34839 var label = tcnm + " - " + tnm; 34840 } else if (UTIL.isEmpty(tcnm)) { 34841 var label = j.find('#Type_Category_id option:selected').text() + " - " + tnm; 34842 } else { 34843 var label = tcnm + " - " + tnm; 34844 } 34845 34846 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34847
34848 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "tid": tid, "tname": tnm, "tcid": tcid, "tcname": tcnm } }) 34849 .success(function(data, textStatus, jqXHR) { 34850 if (UTIL.Validate.hasPermissionError(data)) { return; } 34851 34852 new GLO.Popup.Success(SA.Resource.TypeSaved); 34853 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34854 34855 var jdata = $(data); 34856 34857 if (!UTIL.isEmpty(tid)) { 34858 document.location = GLO.Link.Page.Provider.Home + 'inventory#action=type-list'; 34859 new GLO.Popup.Processing('Loading Update...'); 34860 location.reload(); 34861 return; 34862 } else { 34863 var newOption = '<option value="' + jdata.attr('inventory_type_id') + '" type_category_id="' + jdata.attr('type_category_id') + '">' + label + '</option>'; 34864 $('select#Inventory_Type_id').find('option:first').after(newOption); 34865 34866 var filterOption = '<option class="t-option" value="t' + jdata.attr('inventory_type_id') + '">' + GLO.Inventory.filterIndent + label + '</option>'; 34867 $('select#Filter_Category').find('option:first').after(filterOption); 34868 } 34869 34870 if (UTIL.isEmpty(tcid) && !UTIL.isEmpty(tcnm)) { 34871 var newOption = '<option value="' + jdata.attr('type_category_id') + '">' + tcnm + '</option>'; 34872 $('select#Type_Category_id').find('option:first').after(newOption); 34873 34874 var filterOption = '<option class="c-option" value="c' + jdata.attr('type_category_id') + '">' + tcnm + '</option>'; 34875 $('select#Filter_Category').find('option:first').after(filterOption); 34876 } 34877 34878 GLO.Inventory.updateHash('type-list'); 34879 }) 34880 .error(function(jqXHR, textStatus, errorThrown) { 34881 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 34882 GLO.UI.Form.resetProcessing(); 34883 }); 34884 } 34885 34886 _conType.remove = function() { 34887 var id = $('#inventory-type-edit tr').attr('inventory_type_id'); 34888 var nm = $('#inventory-type-edit #Type_Name_vc').val(); 34889 34890 new GLO.Popup.Confirm(SA.Resource.DeleteTypeConfirm + ' <b style="color: #4F81BD">' + nm + '</b>', function(){ 34891 GLO.Inventory.Type.removeConfirmed(id); 34892 }); 34893 } 34894 34895 _conType.removeConfirmed = function(id) { 34896 var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeDelete'; 34897 GLO.UI.Form.beginProcessing($('#inventory-type-edit .btnDelete')); 34898 34899 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 34900 .success(function(data, textStatus, jqXHR) { 34901 if (UTIL.Validate.hasPermissionError(data)) { return; } 34902 34903 var jdata = $(data); 34904 34905 if (jdata.attr('error_cd')) { 34906 new GLO.Popup.Warning(jdata); 34907 } else { 34908 new GLO.Popup.Success(SA.Resource.TypeRemoved); 34909 34910 $('select#Inventory_Type_id option[value="' + id + '"]').remove(); 34911 $('select#Filter_Category option[value="t' + id + '"]').remove(); 34912 34913 GLO.Inventory.updateHash('type-list'); 34914 } 34915 }) 34916 .error(function(jqXHR, textStatus, errorThrown) { 34917 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 34918 GLO.UI.Form.resetProcessing(); 34919 }); 34920 } 34921 34922 return _conType; 34923})(); 34924 34925 34926GLO.Inventory.Unit = (function() { 34927 function _conUnit() {} 34928 34929 _conUnit.openList = function() { 34930 var ju = $('select#Unit_id option'); 34931 34932 if (ju.length > 0) { 34933 var ulist = ''; 34934 34935 for (var i=1; i < ju.length; i++) { 34936 ulist += '<li unit_id="' + ju.eq(i).attr('value') + '" title="' + ju.eq(i).attr('title') + '">' + ju.eq(i).text() + '</li>'; 34937 } 34938 34939 $('#inventory-unit-list').removeClass('hide').find('ul').html(ulist); 34940 } else { 34941 _conUnit.openEdit(); 34942 } 34943 } 34944 34945 _conUnit.openEdit = function(id, nm, ab) { 34946 var j = $('#inventory-unit-edit'); 34947 34948 if (!UTIL.isEmpty(id)) { 34949 j.find('.btnDelete').removeClass('hide'); 34950 34951 j.find('tr').attr('unit_id', id); 34952 j.find('#Unit_Name_vc').val(nm); 34953 j.find('#Unit_Abbreviation_vc').val(ab); 34954 } else { 34955 j.find('tr').attr('unit_id', ''); 34956 34957 j.find('.btnDelete').addClass('hide'); 34958 j.find('#Unit_Name_vc').val(''); 34959 j.find('#Unit_Abbreviation_vc').val(''); 34960 } 34961 34962 //$('#inventory-unit-list, #inventory-item-form:visible').addClass('hide'); 34963 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34964 j.removeClass('hide');
34965 j.find('input:first').focus(); 34966 } 34967 34968 _conUnit.save = function() { 34969 var uri = GLO.Link.Page.Provider.Home + 'Inventory/Unit'; 34970 var j = $('#inventory-unit-edit'); 34971 34972 var id = j.find('tr').attr('unit_id'); 34973 var nm = j.find('#Unit_Name_vc').val(); 34974 var ab = j.find('#Unit_Abbreviation_vc').val(); 34975 34976 if (UTIL.isEmpty(nm)) { 34977 GLO.Popup.Warning(SA.Resource.PleaseEnterUnitName, function() { $('#inventory-unit-edit #Unit_Name_vc').focus(); }); 34978 return; 34979 } 34980 34981 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 34982 34983 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id, "name": nm, "abbreviation": ab } }) 34984 .success(function(data, textStatus, jqXHR) { 34985 if (UTIL.Validate.hasPermissionError(data)) { return; } 34986 34987 new GLO.Popup.Success(SA.Resource.UnitSizeSaved); 34988 j.find('.btnSave a').css({ "border": "3px solid transparent" }); 34989 34990 if (UTIL.isEmpty(id)) { 34991 var newOption = '<option value="' + $(data).attr('unit_id') + '" title="' + ab + '">' + nm + '</option>'; 34992 $('select#Unit_id').find('option:first').after(newOption); 34993 } else { 34994 $('select#Unit_id option[value="' + id + '"]').text(nm).attr('title', ab); 34995 34996 location.reload(); 34997 } 34998 34999 GLO.Inventory.updateHash('unit-list'); 35000 }) 35001 .error(function(jqXHR, textStatus, errorThrown) { 35002 new GLO.Popup.Error('Unable to save at this time. Please try again later.'); 35003 GLO.UI.Form.resetProcessing(); 35004 }); 35005 } 35006 35007 _conUnit.remove = function() { 35008 var uri = GLO.Link.Page.Provider.Home + 'Inventory/UnitDelete'; 35009 var id = $('#inventory-unit-edit tr').attr('unit_id'); 35010 GLO.UI.Form.beginProcessing( $('#inventory-unit-edit .btnDelete') ); 35011 35012 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 35013 .success(function(data, textStatus, jqXHR) { 35014 if (UTIL.Validate.hasPermissionError(data)) { return; } 35015 35016 var jdata = $(data); 35017 35018 if (jdata.attr('error_cd')) { 35019 new GLO.Popup.Warning(jdata); 35020 } else { 35021 new GLO.Popup.Success(SA.Resource.UnitSizeDeleted); 35022 $('select#Unit_id option[value="' + id + '"]').remove(); 35023 35024 GLO.Inventory.updateHash('unit-list'); 35025 } 35026 }) 35027 .error(function(jqXHR, textStatus, errorThrown) { 35028 new GLO.Popup.Error('Unable to delete at this time. Please try again later.'); 35029 GLO.UI.Form.resetProcessing(); 35030 }); 35031 } 35032 35033 _conUnit.back = function() { 35034 GLO.Inventory.Item.unHide(); 35035 } 35036 35037 return _conUnit; 35038})(); 35039 35040 35041GLO.Inventory.Invoice = (function() { 35042 function _conInventoryInvoice() {} 35043 35044 _conInventoryInvoice.createUsageInvoice = function() { 35045 _closeHelp(); 35046 35047 var htm = '<p>Usage Invoice Tickets allow you to mark Internal Use products <small style="letter-spacing: 0;">(products not allowed for retail sale)</small> as used</>'; 35048 var jprocessing = GLO.Popup.Processing.open(htm, 'Creating Usage Invoice Ticket'); 35049 35050 setTimeout(function() { 35051 var jPayInfo = $('<h2 event_cd="800"/>'); 35052 UserPortal.Price.open(false, true, jPayInfo); 35053 35054 jprocessing.close(); 35055 setTimeout(UserPortal.Price.addProductRow, 400); 35056 }, 100); 35057 } 35058 35059 _conInventoryInvoice.recentUsageInvoices = function(count) { 35060 _closeHelp(); 35061 35062 var btn = '<div id="recent-usage-invoice-button"><span class="btnAdd btnCreateUsageInvoice"><a onclick="GLO.Inventory.Invoice.createUsageInvoice()">Create Product Usage Invoice</a></span></div>'; 35063
35064 SA.Menu.recentSales(10, 800, btn); 35065 } 35066 35067 _conInventoryInvoice.createInternalProduct = function() { 35068 _closeHelp(); 35069 GLO.Inventory.gotoHash('new-product&internal-use=1'); 35070 } 35071 35072 function _closeHelp() { 35073 var jpop = $('#pop-inventory-invoice-usage-help').closest('.glopop'); 35074 35075 if (jpop.length) { 35076 GLO.Popup.close(jpop); 35077 } 35078 } 35079 35080 _conInventoryInvoice.openHelp = function() { 35081 var msg1 = 'Do you buy products that you and your staff use, but are not sold to clients?'; 35082 var msg2 = 'Keep track of these products\' cost and count by:'; 35083 var msgcss = 'line-height: 1.4;'; 35084 var msg = '<p style="' + msgcss + '">' + msg1 + '</p> <p style="' + msgcss + 'text-align: left;">' + msg2 + '</p>'; 35085 35086 var l1 = '<a onclick="GLO.Inventory.Invoice.createInternalProduct()">Create Products</a> <b>for Internal Use</b>'; 35087 var l2 = '<a onclick="GLO.Inventory.updateHash(\'order-create\')">Create Order</a> for these products and include the cost'; 35088 var l3 = 'As these products are used <a onclick="GLO.Inventory.Invoice.createUsageInvoice()">Create Product Usage Invoice</a> so you can record the used product cost and count'; 35089 35090 var l3a = 'You might want to create a generic client like "Internal Usage" for these invoices'; 35091 l3 += '<ul> <li>' + l3a + '</li></ul>'; 35092 35093 var ol = '<ol class="reset-list"> <li>' + l1 + '</li> <li>' + l2 + '</li> <li>' + l3 + '</li> </ol>'; 35094 var htm = '<div id="pop-inventory-invoice-usage-help">' + msg + ol + '</div>'; 35095 35096 GLO.Popup.Info.open(htm, 'Product Usage Invoice'); 35097 } 35098 35099 return _conInventoryInvoice; 35100})(); 35101 35102 35103GLO.Inventory.Reports = (function() { 35104 function _conInventoryRpt() {} 35105 35106 _conInventoryRpt.currentTab = 1; 35107 _conInventoryRpt.MAX_TAB = 4; 35108 35109 _conInventoryRpt.init = function() { 35110 var tab = GLO.Report.Template.init(); 35111 var jsonShipmentLookup = _lookupShipmentFromUrl(); 35112 35113 _initReturns(); 35114 _initProductHistory(); 35115 35116 _conInventoryRpt.goToTab(tab, true); 35117 35118 //$('#report-sales-trends').find('#rpt-filter-pay-method').remove(); 35119 $('#report-shipment-history').find('#rpt-filter-pay-method').remove(); 35120 35121 _initAuditHistory(); 35122 _initOrderHistory(); 35123 35124 if (UTIL.isEmpty(GLO.Uri.query('sfilter'))) { 35125 jdd = $('#header-navigation-links #staff-filter').addClass('hide'); 35126 35127 GLO.Info.init(); 35128 var msg = '<span style="padding-right: 10px; color: Black;">' + SA.Resource.Hi + ' ' + UserPortal.lookupStaffName(GLO.Info.StaffId) + '</span>'; 35129 jdd.after(msg); 35130 } 35131 35132 $(window).hashchange(function() { GLO.Inventory.Reports.hashOnChange(); }); 35133 $('#header-navigation-links').find('#hd-report-order-history > a, #hd-report-audit-history > a, #hd-report-product-history > a, #hd-report-return-history > a').addClass('ignore-animate'); 35134 35135 _initInventoryReportUri(jsonShipmentLookup); 35136 GLO.Report.enableFullPageCheck(); 35137 } 35138 function _initInventoryReportUri(jsonShipmentLookup) { 35139 if (!_conInventoryRpt.findShipmentInReportSummary(jsonShipmentLookup.shipment)) { 35140 if (jsonShipmentLookup.hasPendingSearch) { 35141 var jhead = $('#report-main').find('.report-search-header-table:visible'); 35142 var isProductHistory = $('#bd #report-product-history:visible').length; 35143 var isReturnHistory = $('#bd #report-returns-exchanges:visible').length; 35144 35145 /* not necessary, this is now set on server 35146 if (UTIL.isDate(jsonShipmentLookup.begin)) { 35147 jhead.find('.Report_Begin_dt').val(new Date(jsonShipmentLookup.begin).toGloDate()); 35148 } 35149 35150 if (UTIL.isDate(jsonShipmentLookup.end)) { 35151 jhead.find('.Report_End_dt').val(new Date(jsonShipmentLookup.end).toGloDate()); 35152 } 35153 */ 35154 35155 if (!UTIL.isEmpty(jsonShipmentLookup.inventoryFilter)) { 35156 jhead.find('.Inventory_Filter').val(jsonShipmentLookup.inventoryFilter).change(); 35157 35158 if (isProductHistory) { 35159 return; 35160 } 35161 } 35162 35163 if (isReturnHistory) { 35164 jhead.find('.btnSearch > a').click(); 35165 } 35166 } 35167 } 35168 } 35169 35170 function _lookupShipmentFromUrl(hasPendingSearch) { 35171 var shipment = UTIL.coalesceString(GLO.Uri.hash('shipment'), GLO.Uri.hash('shipmentId')); 35172 var order = UTIL.coalesceString(GLO.Uri.hash('order'), GLO.Uri.hash('orderId')); 35173 var audit = UTIL.coalesceString(GLO.Uri.hash('audit'), GLO.Uri.hash('auditId')); 35174 35175 var inventoryFilter = $.trim(GLO.Uri.hash('id')); 35176 //not neccessary, now set on server var begin = GLO.Uri.url('begin'), end = GLO.Uri.url('end'); 35177 35178 var hasPendingSearch = !UTIL.isEmpty(inventoryFilter); 35179 var json = { "hasPendingSearch": hasPendingSearch, "searchHeader": "Report", "inventoryFilter": inventoryFilter }; //only auto-run search from client on product-history or return-history report 35180 35181 if (!UTIL.isEmpty(shipment)) { 35182 json.shipment = shipment; 35183 } else if (!UTIL.isEmpty(order)) { 35184 json.shipment = order; 35185 json.isOrder = true; 35186 json.searchHeader = "Order"; 35187 } else if (!UTIL.isEmpty(audit)) { 35188 json.shipment = audit; 35189 json.isAudit = true; 35190 json.searchHeader = "Audit"; 35191 } 35192 35193 return json; 35194 } 35195 35196 _conInventoryRpt.findShipmentInReportSummary = function(shipment) { 35197 if (UTIL.isEmpty(shipment)) { return; } 35198 35199 var jrpt = $('#bd #report-main .inventory-report:visible .tablesorter'); 35200 var tr = jrpt.find('tr[shipment_id="' + shipment + '"]'); 35201 35202 if (tr.length) { 35203 tr.click(); 35204 return true; 35205 } else { 35206 tr = jrpt.find('tr[shipment_nr="' + shipment + '"]'); 35207 35208 if (tr.length) { 35209 tr.click(); 35210 return true; 35211 } 35212 } 35213 35214 return false; 35215 } 35216 function _initAuditHistory() { 35217 var style = 'display: block; margin-right: 40px; padding: 6px;'; 35218 var title = SA.Resource.InventoryAuditHelp; 35219 var auditButton = '<span id="inventory-audit-button" class="btnAdd btnAction2" style="' + style + '" title="' + title + '">' 35220 + '<a href="/inventory#action=audit" style="white-space: nowrap;">' + SA.Resource.NewCheck + '</a>' 35221 + '</span>'; 35222 35223 var jaudit = $('#report-audit-history'); 35224 var jhead = jaudit.find('.report-search-header'); 35225 35226 jaudit.find('#rpt-filter-pay-method').remove(); 35227 35228 //jhead.find('table').css({ "": "" }); 35229 jhead.find('table td:first').append(auditButton); 35230 } 35231 35232 function _initOrderHistory() { 35233 var style = 'display: block; margin-right: 40px; padding: 6px;'; 35234 var newOrderButton = '<span id="inventory-create-order-button" class="btnAdd btnAction2" style="' + style + '">' 35235 + '<a href="/inventory#action=order-create" style="white-space: nowrap;">' + SA.Resource.New + ' ' + SA.Resource.Order + '</a>' 35236 + '</span>'; 35237 35238 $('#report-shipment-history').find('.report-search-header').find('table td:first').append(newOrderButton); 35239 } 35240 35241 _conInventoryRpt.hashOnChange = function() { 35242 var tab = GLO.Uri.hash('tab'); 35243 var id = GLO.Uri.hash('id'); 35244 35245 if (tab === 'product-history') { 35246 if (!UTIL.isEmpty(id) && !UTIL.isEmpty(_conInventoryRpt.currentTab) && id != _conInventoryRpt.currentTab) { 35247 _conInventoryRpt.goToTab(tab, false); 35248 } 35249 } else { 35250 _conInventoryRpt.goToTab(tab, false); 35251 } 35252 } 35253 35254 _conInventoryRpt.loadReturnReport = function(jrpt) { 35255 GLO.Report.CellSummary.initReport(jrpt, true, true); 35256 GLO.Report.initIcons(jrpt); 35257 } 35258 35259 function _initReturns() { 35260 var jrptReturnExchange = $('#report-returns-exchanges'); 35261 jrptReturnExchange.find('#rpt-filter-pay-method').remove(); 35262 jrptReturnExchange.find('.service-filter-container').remove(); 35263 35264 jrptReturnExchange.find('.inventory-filter-container').find('option[value="-1"]').remove(); 35265 35266 jrptReturnExchange.find('.inventory-filter-container').css({ "margin-left": "-50px", "margin-right": "150px" }); 35267 jrptReturnExchange.find('.btnSearch').css({ "margin-left": "100px" }); 35268 35269 GLO.Inventory.Reports.loadReturnReport(jrptReturnExchange); 35270 35271 var ifilter = GLO.Uri.query('inventoryfilter'); 35272 35273 if (!UTIL.isEmpty(ifilter)) { 35274 $('#report-returns-exchanges .report-search-header .Inventory_Filter').val(ifilter); 35275 } 35276 } 35277 35278 function _initProductHistory() { 35279 var jrpt = $('#report-product-history'); 35280 jrpt.find('#rpt-filter-pay-method').remove(); 35281 jrpt.find('.service-filter-container').remove(); 35282 35283 jrpt.find('.btnSearch').click(GLO.Inventory.Reports.productSearchUpdateUrlHash); 35284 var tmp = jrpt.find('#product-history-inventory-dd'); 35285 35286 var dd = jrpt.find('.Inventory_Filter'); 35287 //var len = tmp.find('option').length; 35288 35289 dd = dd.html(tmp.html()); 35290 dd.change(function() { $('#report-product-history').find('.report-inventory-header-search:visible').click(); }); 35291 tmp.html(''); 35292 35293 _addProductAutocomplete(jrpt, dd); 35294 35295 dd.addClass('required'); 35296 dd.css({ "width": "300px" }); 35297 35298 if (innerWidth < 600) { 35299 $('#report-tab-product-history span').html('<b>1</b>' + SA.Resource.History); 35300 $('#report-tab-audit-history span').html('<b>3</b>' + SA.Resource.Audit); 35301 $('#report-tab-returns-exchanges span').html('<b>4</b>' + SA.Resource.Returns); 35302 } 35303 } 35304 35305 function _addProductAutocomplete(jrpt, dd) { 35306 dd.before('<input type="text" id="product-history-autocomplete" placeholder="' + SA.Resource.ProductName + '" style="width: 140px;"/>'); 35307 35308 jrpt.find('#product-history-autocomplete').autocomplete({ 35309 source: GLO.Link.Object.Provider.Ajax + 'ProductSearch?retailonly=0', 35310 minLength: 2, 35311 select: function(event, ui) { 35312 //var productName = ui.item.value; 35313 var jrpt = $('#report-product-history'); 35314 35315 jrpt.find('.Inventory_Filter').val(ui.item.id); 35316 jrpt.find('#product-history-autocomplete').val(''); 35317 jrpt.find('.report-inventory-header-search:visible').click(); 35318 35319 window.setTimeout(function() { 35320 $('#product-history-autocomplete').val(''); 35321 }, 200); 35322 35323 GLO.Report.CellSummary.initReport(jrpt, true, true); 35324 } 35325 }); 35326 } 35327 35328 _conInventoryRpt.productSearchUpdateUrlHash = function() { 35329 var id = $('#report-product-history').find('.Inventory_Filter').val();
35330 document.location.hash = 'tab=product-history&id=' + UTIL.cleanString(id); 35331 } 35332 35333 function _getTab(tab, id) { 35334 GLO.Info.init(); 35335 35336 if (GLO.Info.providerPackage == 4) { 35337 if (tab === 'product-history' || tab == '1') { 35338 GLO.Info.isRequireGold(false, 'Product Detail History report'); 35339 } else if (tab === 'order-and-restock' || tab == '2') { 35340 GLO.Info.isRequireGold(false, 'Product Order report'); 35341 } else if (tab === 'audit-history' || tab == '3') { 35342 GLO.Info.isRequireGold(false, 'Audit History report'); 35343 } 35344 35345 tab = 4; 35346 } else if (!UTIL.isEmpty(tab)) { 35347 tab = String(tab).toLowerCase(); 35348 35349 if (tab === 'product-history' || tab == '1') { 35350 tab = 1; 35351 } else if (tab === 'order-and-restock' || tab == '2') { 35352 tab = 2; 35353 } else if (tab === 'audit-history' || tab == '3') { 35354 tab = 3; 35355 } else if (tab === 'returns-exchanges' || tab == '4') { 35356 tab = 4; 35357 } 35358 } else { 35359 tab = _conInventoryRpt.currentTab; 35360 } 35361 35362 return tab; 35363 } 35364 35365 _conInventoryRpt.goToTab = function(tab, isInit) { 35366 var id = GLO.Uri.hash('id'); 35367 tab = _getTab(tab, id) 35368 35369 if (tab == _conInventoryRpt.currentTab && !isInit && tab != 4) { 35370 return; //avoids infinite recursion; 35371 } else if (tab != _conInventoryRpt.currentTab && !isInit) { 35372 id = ''; 35373 } 35374 35375 if (tab > _conInventoryRpt.MAX_TAB) { 35376 tab = _conInventoryRpt.MAX_TAB; 35377 } else if (tab < 1) { 35378 tab = 1; 35379 } 35380 35381 $('#report-returns-exchanges').addClass('hide'); 35382 $('#report-shipment-history').addClass('hide'); 35383 $('#report-audit-history').addClass('hide'); 35384 $('#report-product-history').addClass('hide'); 35385 35386 if (tab === 1) { 35387 var currentReport = $('#report-product-history').removeClass('hide'); 35388 } else if (tab === 2) { 35389 var currentReport = $('#report-shipment-history').removeClass('hide'); 35390 } else if (tab === 3) { 35391 var currentReport = $('#report-audit-history').removeClass('hide'); 35392 } else if (tab === 4) { 35393 var currentReport = $('#report-returns-exchanges').removeClass('hide'); 35394 } 35395 35396 var backColor = $('.shadow-content0').css('backgroundColor'); 35397 var jhead = $('#report-portal-header'); 35398 var oj = jhead.find('table tr td span b'); 35399 35400 oj.each(function() { 35401 $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent'); 35402 }); 35403 35404 //oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent(); //didn't work if not all tabs were displayed. 35405 oj = jhead.find('table td[tab="' + tab + '"]'); 35406 35407 oj.addClass('report-tab'); 35408 oj.css('backgroundColor', backColor); 35409 35410 _conInventoryRpt.currentTab = tab; 35411 var hashTab = ''; 35412 35413 if (tab == '1') { 35414 hashTab = 'product-history'; 35415 35416 if (isInit) { 35417 var start = UTIL.coalesce(GLO.Uri.hash('start'), GLO.Uri.query('start')); 35418 var end = UTIL.coalesce(GLO.Uri.hash('end'), GLO.Uri.query('end')); 35419 35420 if (UTIL.isDate(start)) { 35421 currentReport.find('.Report_Begin_dt').val( new Date(start).toGloDate() ); 35422 } 35423 35424 if (UTIL.isDate(end)) { 35425 currentReport.find('.Report_End_dt').val( new Date(end).toGloDate() ); 35426 } 35427 35428 if (!UTIL.isEmpty(id)) { 35429 $('.Inventory_Filter').val(id).change(); 35430 } 35431 } 35432 } else if (tab == '2') { 35433 hashTab = 'order-and-restock'; 35434 } else if (tab == '3') { 35435 hashTab = 'audit-history'; 35436 } else if (tab == '4') { 35437 hashTab = 'returns-exchanges'; 35438 35439 if (!UTIL.isEmpty(id)) { 35440 var jrpt = $('#report-product-history'); 35441 jrpt.find('.Inventory_Filter').val(id); 35442 jrpt.find('.report-inventory-header-search:visible').click(); 35443 } 35444 } 35445 35446 _setHashUrl(hashTab, id); 35447 } 35448 35449 function _setHashUrl(hashTab, id) { 35450 var hash = 'tab=' + hashTab; 35451 begin = GLO.Uri.hash('begin'), end = GLO.Uri.hash('end'); 35452 35453 if (!UTIL.isEmpty(id)) { 35454 hash += '&id=' + id; 35455 } 35456 35457 if (UTIL.isDate(begin)) { 35458 hash += '&begin=' + begin; 35459 } 35460 35461 if (UTIL.isDate(end)) { 35462 hash += '&begin=' + end; 35463 } 35464 35465 document.location.hash = hash; 35466 } 35467 35468 _conInventoryRpt.backFromShipmentDetail = function(isAudit) { 35469 if (isAudit) { 35470 var jrpt = $('#report-audit-history'); 35471 } else { 35472 var jrpt = $('#report-shipment-history'); 35473 } 35474 35475 jrpt.find('.inventory-report-container').remove(); 35476 35477 var jHistory = jrpt.find('.inventory-report-container-hide').addClass('inventory-report-container').removeClass('inventory-report-container-hide'); 35478 } 35479 35480 _conInventoryRpt.editShipment = function(id, editButton) { 35481 document.location = GLO.Link.WebsiteDomain + 'inventory/index?EditShipmentId=' + id; //toDo: Need to optimize so ajax doesn't re-request order detail or just use --> "/inventory/index#action=order&id=66" ~~> "/inventory/index#action=order&id=" + id 35482 GLO.UI.Form.beginProcessing( $(editButton).parent() ); 35483 } 35484 _conInventoryRpt.exportShipment = function(shipmentId) { 35485 if (UTIL.isEmpty(shipmentId)) { 35486 shipmentId = GLO.Inventory.Restock.getShipmentId(); 35487 } 35488 35489 if (UTIL.isEmpty(shipmentId)) { 35490 GLO.Popup.Warning.open('Please Save Order before Exporting', 'Export Order'); 35491 return; 35492 } 35493 35494 var url = GLO.Link.WebsiteDomain + 'report/ShipmentDetail?isExportToExcel=1&id=' + shipmentId; 35495 var btnExport = $('#shipment-detail-header').find('.btnExportToExcel'); 35496 GLO.UI.Form.beginProcessing(btnExport); 35497 35498 window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 2500); 35499 35500 UI.openChildWindow(url, '', true); 35501 } 35502 _conInventoryRpt.viewShipment = function(id, thisRow, isAudit) { 35503 if (isAudit === 0 && $('h2.inventory-header:visible').length === 1) { 35504 GLO.Inventory.updateHash('order', id, 'order-list'); //GLO.Inventory.Order.openEdit(id); 35505 return; 35506 } 35507 35508 var url = GLO.Link.WebsiteDomain + 'report/ShipmentDetail?id=' + id; 35509 if (isAudit === 1) { url += '&isAudit=1'; } 35510 35511 var btnSearch = $('.report-search-header:visible').find('.btnSearch'); 35512 GLO.UI.Form.beginProcessing( btnSearch ); 35513
35514 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 35515 .success(function(data, textStatus, jqXHR) { 35516 GLO.UI.Form.resetProcessing(); 35517 var word = 'shipment'; 35518 if (isAudit === 1) { word = 'audit'; } 35519 35520 if (!UTIL.isEmpty(data)) { 35521 var j = $('#report-' + word + '-history'); 35522 35523 j.find('.inventory-report-container-hide').remove(); 35524 var jrpt = j.find('.inventory-report-container').addClass('inventory-report-container-hide').removeClass('inventory-report-container'); 35525 35526 jrpt.before('<div class="inventory-report-container"/>'); 35527 jrpt = $('#report-' + word + '-history').find('.inventory-report-container').html(data); 35528 35529 UI.initTableSorter( $('table.tablesorter:visible') ); 35530 35531 if (isAudit === 1) { 35532 if (GLO.Info.isMobile()) { 35533 var strID = ''; 35534 } else { 35535 var strID = '<span id="audit-number-container"> <b id="audit-number-label">Audit #</b> <span id="audit-number">' + $(thisRow).find('td.shipment-number').text() + '</span> </span>'; 35536 } 35537 35538 var div = '<div id="audit-detail-header">' 35539 + '<span class="btnBack" onclick="GLO.Inventory.Reports.backFromShipmentDetail(1)"><a>' + SA.Resource.Back + '</a></span>' 35540 + strID 35541 + '<span id="audit-date-container"> <b id="audit-date-label">' + SA.Resource.AuditDate + ':</b> <span id="audit-date">' + $(thisRow).find('td.shipment-create-dt').text() + '</span> </span>' 35542 + '</div>'; 35543 35544 jrpt.prepend(div); 35545 } 35546 } else { 35547 GLO.Popup.Info('No ' + word + ' was found. Please try again.'); 35548 } 35549 }) 35550 .error(function(jqXHR, textStatus, errorThrown) { 35551 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 35552 GLO.UI.Form.resetProcessing(); 35553 }); 35554 } 35555 35556 _conInventoryRpt.openReturnUsedHelp = function(element, isUsed, isUnopened) { 35557 var msgUsed = '<p>Returned product so will not be returned to the inventory stock and the cost of the product will be subtracted from your profitability</p>'; 35558 var msgUnUsed = '<p>Returned product added product back to the inventory stock; the existing inventory count for the product increases by 1 when returned</p>'; 35559 35560 var msgUsed2 = 'If you are returning this product to the vendor (or distributor) for a refund then create an invoice (via "Sell Product") for the vendor/distributor where ths product is sold at cost'; 35561 var htmUsed2 = '<p style="margin-top: 12px;">' + msgUsed2 + '</p>'; 35562 var h1 = 'Returning Products Used vs Not Used'; 35563 35564 if (isUsed) { 35565 h1 = 'Product Returned Opened / Used'; 35566 var msg = '<p>' + $(element).parent().attr('helptext') + '</p>' + htmUsed2; 35567 } else if (isUnopened) { 35568 h1 = 'Product Returned Un-Opened / Un-Used'; 35569 var msg = '<p>' + $(element).parent().attr('helptext') + '</p>'; 35570 } else { 35571 var msg = '<div><h3 style="margin-top: 0;">Product Returned Opened/Used:</h3>' + msgUsed + htmUsed2 + '</div>'; 35572 msg += '<div><h3>Product Returned Un-Opened / Un-Used:</h3>' + msgUnUsed + '</div>'; 35573 } 35574 35575 var htm = '<div id="pop-return-used-help">' + msg + '</div>'; 35576 var ojInfo = new GLO.Popup.Info.open(htm, h1); 35577 } 35578 35579 return _conInventoryRpt; 35580})(); 35581 35582 35583 35584WIZ = (function() { 35585 //var jsURL = '/outGlo/wizard/index.php?page='; 35586 _constructor.numberInputType = "text"; 35587 _constructor.pageContext; 35588 _constructor.isAjaxTab = false; 35589 _constructor.Update_By_Staff_By_Password_id = null; 35590 _constructor.Update_By_Role_Type_By_Password_cd = null;
35591 _constructor.Update_By_Password_interval = null; 35592 35593 _constructor.Popup = {}; 35594 _constructor.Popup.urlOnSave; 35595 _constructor.Popup.onSave; 35596 35597 //_constructor.prevPage = ''; 35598 //_constructor.nextPage = ''; 35599 _constructor.page; 35600 35601 _constructor.isWizard; 35602 35603 _constructor.modalAdjustHeight = 0; 35604 _constructor.modalAdjustWidth = 0; 35605 _constructor.modalDefaultHeight = 360; 35606 _constructor.modalDefaultWidth = 555; 35607 35608 function _constructor(name) { 35609 var that = this; 35610 var args = Array.prototype.slice.apply(arguments); 35611 } 35612 35613 var goToPage = function(e, page) { 35614 //$('.shadow-content').slideUp('slow'); 35615 //$('.shadow-content').fadeOut('normal'); 35616 35617 //document.location = jsURL + page; 35618 //GLO.Uri.query('page', page); 35619 } 35620 35621 _constructor.initWizard = function(fname, mi, lname, email, phone, username, password, language) { 35622 var jwiz = $('#wiz1-form'); 35623 35624 if (!UTIL.isEmpty(fname)) { jwiz.find('#First_Name_vc').val(fname); } 35625 if (!UTIL.isEmpty(mi)) { jwiz.find('#Middle_Initial_c').val(mi); } 35626 if (!UTIL.isEmpty(lname)) { jwiz.find('#Last_Name_vc').val(lname); } 35627 35628 if (!UTIL.isEmpty(email)) { jwiz.find('#Email_vc').val(email); } 35629 35630 if (!UTIL.isEmpty(phone) && phone.length === 10) { 35631 setTimeout(function() { 35632 jwiz.find('#Mobile_Phone_vc').val(phone).blur(); 35633 }, 80); 35634 } 35635 35636 if (!UTIL.isEmpty(username)) { 35637 jwiz.find('#Username_vc').val(username).change(); 35638 } else if (!UTIL.isEmpty(email)) { 35639 jwiz.find('#Username_vc').val(email).change(); 35640 } 35641 35642 if (!UTIL.isEmpty(password)) { 35643 jwiz.find('#Password_vc').val(password); 35644 jwiz.find('#Password2_vc').val(password); 35645 } 35646 35647 //if (!UTIL.isEmpty(language)) { jwiz.find('#Language_cd').val(language); } 35648 //if (!UTIL.isEmpty(mprovider)) { jwiz.find('#Mobile_Provider_cd').val(mprovider); } 35649 } 35650 35651 _constructor.addScrollBarsToSimpleModal = function() { 35652 if (GLO.Info.isMobile()) { return; } 35653 35654 var isRealign = false; 35655 var jmodal = $('#simplemodal-container'); 35656 var jwrap = jmodal.find('.simplemodal-wrap'); 35657 35658 if (jwrap.height() > innerHeight - 20) { 35659 var headerHeight = UTIL.coalesceInt(jmodal.find('> h1, > h2').height(), 0); 35660 var footerHeight = UTIL.coalesceInt(jmodal.find('#wiz1-popupNext, #wiz5-popupStatus-buttons-div, #wiz5-popupButtons').height(), 0); 35661 var maxWrapHeight = (innerHeight - 20 - headerHeight - footerHeight); 35662 35663 jwrap.addClass('friendly-mini-scroll').css({ "max-height": maxWrapHeight + 'px' }); 35664 isRealign = true; 35665 } 35666 35667 if (jmodal.height() > innerHeight - 20) { 35668 jmodal.css({ "max-height": (innerHeight - 20) + 'px' }); 35669 isRealign = true; 35670 } 35671 35672 if (isRealign) { 35673 $.modal.update(); 35674 } 35675 } 35676 35677 _constructor.clickPrev = function(e) { 35678 if (GLO.Info.isIosApp) { 35679 var msg = '<div class="friendly-msg2">' 35680 + '<h1 class="friendly-msg2">Go To Previous Page</h1>' 35681 + '<div>Do you want to go to the previous page?</div>' 35682 '</div>'; 35683 new GLO.Popup.Confirm(msg, WIZ.clickPrevConfirmed); 35684 } else { 35685 _constructor.clickPrevConfirmed(); 35686 } 35687 } 35688 35689 _constructor.clickPrevConfirmed = function() { 35690 if ( (GLO.Info.providerPackage == 1 || WIZ.isWizard) && WIZ.page === 6) { WIZ.page--; } 35691 35692 return _constructor.goToPage(--WIZ.page, false); 35693 } 35694 35695 _constructor.goToPageFromHeader = function(page) { 35696 //if (GLO.Info.isIosApp && page == 6) { SA.App.openLinkInBrowser(GLO.Link.WebsiteDomain + 'provider/profile/' + page, true); } 35697 35698 if (WIZ.isWizard && page - 1 > $.cookies.get('pstatus')) { 35699 return false; 35700 } else { 35701 return _constructor.goToPage(page); 35702 } 35703 } 35704 35705 _constructor.goToPage = function(page, mustPost) { 35706 var jform = $('form').eq(0); 35707 var url = "wizard/"; 35708 if (!_constructor.isWizard) { url = "provider/profile/"; } 35709 if (supports_history_api()) { url = url + "part/"; } 35710 url = GLO.Link.WebsiteDomain + url + page; 35711 35712 if (mustPost) { 35713 var type = "POST"; 35714 } else { 35715 var type = "GET"; 35716 } 35717 35718 if (supports_history_api() && false) { 35719 GLO.UI.Form.beginProcessing(jform.find('#btnNext, .btnSave')); 35720
35721 var jqxhr = $.ajax({ type: type, url: url, "cache": false, data: $("form").serialize() }) 35722 .success(function(data, textStatus, jqXHR) { 35723 pushState('wiz', "yo"); //CHANGE (very low priority): this changes the URL, but I cannot get the context to change in the history (like it does with the hash change event). 35724 $('#wizBody').html(data); 35725 35726 // //If switch to push state will have to manually set these values for each new state: 35727 // WIZ.pageContext 35728 // WIZ.page 35729 // WIZ.modalAdjustHeight / WIZ.modalAdjustWidth / WIZ.modalDefaultHeight / WIZ.modalDefaultWidth 35730 // //how change URL: document.location.pathname.substring(document.location.pathname.length-1) 35731 35732 }) 35733 .error(function(jqXHR, textStatus, errorThrown) { 35734 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 35735 }) 35736 35737 //$.ajax({ type: type, url: url, data: null, success: WIZ.editCallback, dataType: "html" }); 35738 } else { 35739 if (mustPost) { 35740 GLO.UI.Form.beginProcessing(jform.find('#btnNext, .btnSave')); 35741 UTIL.DefaultText.deInit($("#wizBody")); 35742 35743 setTimeout(function() { 35744 $('form').attr('action', ''); 35745 document.forms[0].submit(); 35746 }, 100); 35747 } else { 35748 GLO.UI.Form.beginProcessing($('#btnPrev')); 35749 35750 if (page == 0) { url = GLO.Link.WebsiteDomain + 'login'; } 35751 35752 setTimeout(function() { 35753 document.location = url; 35754 }, 400); 35755 } 35756 } 35757 } 35758 35759 _constructor.UsernameIsUnique = function(jContext, isPopup) { //WIZ 35760 var url = GLO.Link.Object.Provider.Ajax + "UsernameIsUnique"; 35761 var user = jContext.find('#Username_vc').val(); 35762 var sid = jContext.find('#Staff_id').val(); 35763 35764 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { 'Username_vc': user, 'Staff_id': sid} }) 35765 .success(function(data, textStatus, jqXHR) { 35766 var jdata = $(data); 35767 35768 if (!UTIL.parseBool(jdata.attr('is_unique_fl'))) { 35769 var msg = '<div class="friendly-msg2">' 35770 + '<h1 class="friendly-msg2">' + SA.Resource.UsernameAlreadyTaken2 + '</h1>' 35771 + '<div>' + SA.Resource.Username + '<b style="color: #4F81BD;">' + user + '</b> ' + SA.Resource.NotUnique + '</div>' 35772 + '<div style="margin-top: 12px;">' + SA.Resource.PleasePickDifferentUsername + '</div>' 35773 '</div>'; 35774 35775 GLO.Popup.Warning(msg); 35776 GLO.UI.Form.resetProcessing(); 35777 return; 35778 } 35779 35780 if (isPopup) { 35781 if ( $('#Password2_vc').length === 1 ) { 35782 if (!UTIL.isValidPassword(true)) { //if (!_passwordsMatch()) { 35783 GLO.UI.Form.resetProcessing(); 35784 return; 35785 } 35786 } 35787 35788 popupSave2($('#simplemodal-container')); 35789 } else { 35790 save3(); 35791 } 35792 }) 35793 .error(function(jqXHR, textStatus, errorThrown) { 35794 GLO.UI.Form.resetProcessing(); 35795 }); 35796 } 35797 35798 _constructor.verifyRequireEditPassword = function(fnSave) { 35799 var jpop = $('#pop-require-edit-password').closest('.glopop'); 35800 var saveForStaff = UTIL.cleanString(jpop.find('#Save_For_Staff_id').val()); 35801 var pass = jpop.find('#Edit_Password_vc').val(); 35802 var urlLookup = GLO.Link.Object.Provider.Ajax + "VerifyStaffPassword?password=" + pass + '&save-staff=' + saveForStaff; 35803 35804 var jsave = jpop.find('.btnSave'); 35805 GLO.UI.Form.beginProcessing(jsave); 35806 35807 $.ajax({ type: "GET", url: urlLookup, "cache": false }) 35808 .success( function(data, textStatus, jqXHR) { 35809 GLO.UI.Form.resetProcessing(); 35810 var jdata = $(data); 35811 35812 if (!UTIL.isEmpty(jdata.attr('error_cd'))) { 35813 new GLO.Popup.Error(jdata); 35814 } else if (!UTIL.isEmpty(jdata.attr('warning_cd'))) { 35815 new GLO.Popup.Warning(jdata); 35816 } else { 35817 GLO.Popup.close(jpop); 35818 _setUpdateByPassword(jdata); 35819 fnSave(); 35820 } 35821 }) 35822 .error( function(jqXHR, textStatus, errorThrown) { 35823 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 35824 }); 35825 } 35826 35827 function _setUpdateByPassword(jdata) {
35828 clearTimeout(_constructor.Update_By_Password_interval); 35829 35830 _constructor.Update_By_Staff_By_Password_id = UTIL.coalesceInt(jdata.attr('update_by_staff_id')); 35831 _constructor.Update_By_Role_Type_By_Password_cd = UTIL.coalesceInt(jdata.attr('update_by_role_type_cd')); 35832 35833 _constructor.Update_By_Password_interval = setTimeout(function() { 35834 _constructor.Update_By_Password_interval = _constructor.Update_By_Staff_By_Password_id = _constructor.Update_By_Role_Type_By_Password_cd = null; 35835 }, 90000); 35836 } 35837 35838 _constructor.openRequireEditPassword = function(fnSaveOnComplete, saveForStaff) { 35839 var htm = $('<div id="pop-require-edit-password"> <h1 class="friendly-msg4">Enter Your Password or PIN Code</h1>' 35840 + '<div class="friendly-msg4" style="min-width: 300px; margin-top: 12px;">' 35841 + '<label for="Edit_Password_vc">Password or PIN Code</label>' 35842 + '<input id="Edit_Password_vc" type="password" autocomplete="new-password" style="width: 100px; letter-spacing: 1px;"/>' 35843 + '<input id="Save_For_Staff_id" type="hidden" value="' + UTIL.cleanString(saveForStaff) + '"/>' 35844 + '</div> </div>'); 35845 35846 var fnSave = function() { _constructor.verifyRequireEditPassword(fnSaveOnComplete); } 35847 35848 var ojpop = new GLO.Popup.Custom(htm, fnSave); 35849 var jpop = ojpop.getPopup().addClass('no-persist'); 35850 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" }); 35851 35852 ojpop.saveOnEnter(); 35853 } 35854 35855 _constructor.clickNext = function(e) { 35856 if ($('.btnCreateServices:visible').length > 0) { 35857 $('.btnCreateServices:visible:first > a').click(); 35858 return; 35859 } 35860 35861 save2(); 35862 return UTIL.cancelEvent(e); 35863 } 35864 35865 _constructor.save = function(e) { 35866 if (e) { UTIL.cancelEvent(e); } 35867 35868 if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) { 35869 _constructor.openRequireEditPassword(save2); 35870 } else { 35871 save2(); 35872 } 35873 35874 return false; 35875 } 35876 35877 function save2() { 35878 if (_constructor.page == 1) { 35879 $('#Image_Path_vc').val($('#newUploadedFilePath').attr('src')); 35880 35881 //if (Wiz1.displayTextAlertConfirm()) { return; } 35882 35883 if ($('#portal').val() === 'wizard') { 35884 var sid = GLO.Info.getStaffId(); 35885 var jStaffId = $('#Staff_id'); 35886 if (UTIL.isEmpty(jStaffId.val()) && !UTIL.isEmpty(sid)) { jStaffId.val(sid); } //Fixes problem, if user used back button during wizard to go back to wiz-1. 35887 } 35888 } else if (_constructor.page == 3) { 35889 if (!WIZ.validateHours()) { return false; } 35890 } 35891 35892 return save3(); 35893 } 35894 35895 function save3() { 35896 if (!$('#btnNext').prop('disabled')) { 35897 if (_constructor.page == 1) { 35898 if (!UTIL.isValidPassword(true)) { 35899 return false; 35900 } else if ($('#UsernameUniqueStatus').hasClass('bad')) { // .text().toLowerCase() == SA.Resource.already_taken 35901 var u = $('#Username_vc'); 35902 var fn = function() { $('#client-form').find('#Username_vc').focus(); }; 35903 35904 var msg1 = '<p>The username <b style="white-space: nowrap; color: red;">' + u.val() + '</b> ' + SA.Resource.is_already_taken + '</p>'; 35905 var msg2 = '<p style="text-align: center;">' + SA.Resource.PleaseUseDiffUsername + '</p>'; 35906 var htm = '<div id="pop-warning-bad-username">' + msg1 + msg2 + '</div>'; 35907 35908 GLO.Popup.Warning.open(htm, 'Username Not Valid', fn); 35909 //GLO.Popup.Warning('<p style="white-space: nowrap;">' + SA.Resource.TheUsername + ' <b style="color:red;">' + u.val() + '</b> ' + SA.Resource.is_already_taken + '.</p><p style="text-align: center;">' + SA.Resource.PleaseUseDiffUsername + '</p>'); 35910 return false; 35911 } else if (!UTIL.isValidPIN(null, true)) { 35912 return false; 35913 } 35914 35915 if (SA.Parent.processProfileUpdateFromMe()) { 35916 return; 35917 } 35918 } 35919 35920 _constructor.saveProfile(); 35921 } 35922 } 35923 35924 _constructor.saveProfile = function() { 35925 if (UTIL.Validate.run(_constructor.pageContext)) { 35926 $('#btnNext').addClass('positive-active').prop('disabled', true); 35927 _constructor.goToPage(_constructor.page, true); 35928 35929 UTIL.Validate.changeReset(); 35930 $('#btnNext').removeClass('positive-active').prop('disabled', false); 35931 return true; //note: the WIZ.save fn can't return true because that causes a postback. 35932 } 35933 } 35934 35935 function _passwordsMatch() { 35936 var wiz1 = $('#wiz1-password'); 35937 var p1 = wiz1.find('#Password2_vc').val(); 35938 var p2 = wiz1.find('#Password_vc').val(); 35939 35940 if (p1 !== p2 && !(p1 === 'yyyyyyyyyy' && p2 === 'xxxxxxxxxx')) { 35941 if (wiz1.find('#Password_vc, #Password2_vc').length === 2) { //= hidden for independent-staff on free + basic plans. 35942 GLO.Popup.Warning(SA.Resource.TwoPasswordsMustMatch); 35943 wiz1.find('#Password2_vc').focus(); 35944 return false; 35945 } 35946 } 35947 35948 return true; 35949 } 35950 35951 function pushState(title, localPath, data) { 35952 window.history.pushState(data, title, localPath); 35953 document.title = title; 35954 } 35955 35956 function supports_history_api() { 35957 return false; //CHANGE (very low priority): this changes the URL, but I cannot get the context to change in the history (like it does with the hash change event). 35958 //return !!(window.history && history.pushState); 35959 } 35960 35961 _constructor.closePopup = function() { 35962 $.modal.close(); 35963 } 35964 35965 _constructor.popupSave = function(isOverride) { 35966 var jPopup = $('#simplemodal-container'); 35967 var isWiz1 = jPopup.find('#wiz1-header').length; 35968 35969 if (!isOverride && GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) { 35970 var fnSave = function() { _constructor.popupSave(true); }; 35971 var saveForStaff = UTIL.cleanString(jPopup.find('#Staff_id').val()); 35972 35973 _constructor.openRequireEditPassword(fnSave, saveForStaff); 35974 return; 35975 } 35976 35977 //if (isWiz1 && Wiz1.displayTextAlertConfirm()) { return; } 35978 35979 if ($('#simplemodal-container #wizNormalHours').length > 0) { 35980 if (!WIZ.validateHours()) { 35981 return false; 35982 } else if (GLO.Info.roleType > 169) { 35983 var editSID = jPopup.find('form').attr('edit_staff_id'); 35984 var manualAdjustCount = UTIL.coalesceInt($('#wizNormalHours').attr('startOrEndTimeAdjustCount'), 0); 35985 Wiz5.askResetHourManualAdjust(editSID, manualAdjustCount); 35986 } 35987 } 35988 35989 if (WIZ.page == 5) { 35990 Wiz5.processingCellUpdate(); 35991 } 35992 35993 if (isWiz1 && !UTIL.isEmpty(jPopup.find('#Username_vc').val())) { 35994 var jsave = $('#simplemodal-container .btnSave, #wiz1-Save'); 35995 GLO.UI.Form.beginProcessing(jsave); 35996 35997 _constructor.UsernameIsUnique(jPopup, true); 35998 } else { 35999 return popupSave2(jPopup); 36000 } 36001 } 36002 36003 function popupSave2(jPopup) { 36004 if (UTIL.Validate.run('#simplemodal-container')) { 36005 UTIL.DefaultText.deInit(jPopup); 36006 36007 var jForm = jPopup.find('form'); 36008 var frmAction = jForm.attr('action'); 36009 var allowedPaymentType = null, staffName = null; 36010 var isAddStaff = false, editStaffId = jPopup.find('#Staff_id').val(); 36011 36012 if (jForm.attr('id') === 'wiz1-form') { 36013 _verifyMerchantType(jForm); 36014 staffName = jForm.find('#First_Name_vc').val() + ' ' + jForm.find('#Last_Name_vc').val(); 36015 36016 if (UTIL.isEmpty(jForm.find('#Staff_id').val())) { 36017 isAddStaff = true; 36018 } 36019 } else if (jPopup.find('#wiz5-popupPermission').length > 0 && GLO.Info.StaffId == editStaffId) { 36020 allowedPaymentType = jPopup.find('#wiz5-popupPermission #Allowed_Payment_cd').val(); 36021 } 36022
36023 if (_constructor.Update_By_Staff_By_Password_id) { 36024 if (frmAction.indexOf("?") === -1) { frmAction += '?'; } else { frmAction += '&'; } 36025 36026 frmAction += 'Update_By_Staff_By_Password_id=' + _constructor.Update_By_Staff_By_Password_id; 36027 frmAction += '&Update_By_Role_Type_By_Password_cd=' + _constructor.Update_By_Role_Type_By_Password_cd; 36028 } 36029 36030 var jqxhr = $.ajax({ type: "POST", url: frmAction, "cache": false, data: jForm.serialize() }) 36031 .success(function(data, textStatus, jqXHR) { 36032 GLO.UI.Form.resetProcessing(); 36033 36034 if ($(data).hasClass('warning')) { 36035 GLO.Popup.Warning.open(jqXHR.responseText, 'Save Not Completed'); 36036 return; 36037 } 36038 36039 if (_saveOnStaffReport()) { return; } 36040 36041 if (UTIL.isNumber(allowedPaymentType)) { 36042 GLO.Data.Staff.allowedPaymentType = parseInt(allowedPaymentType); 36043 } 36044 36045 if (isAddStaff) { 36046 _displayAddStaffMessage(data); 36047 } else if (!_processData(data)) { 36048 return; 36049 } 36050 36051 if (!UTIL.isEmpty(_constructor.Popup.onSave)) { 36052 _constructor.Popup.onSave(data, staffName); 36053 } else if (!UTIL.isEmpty(_constructor.Popup.urlOnSave)) { 36054 document.location = _constructor.Popup.urlOnSave; 36055 } 36056 }) 36057 .error(function(jqXHR, textStatus, errorThrown) { 36058 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 36059 }); 36060 36061 _constructor.closePopup(); 36062 } else { 36063 GLO.UI.Form.resetProcessing(); 36064 } 36065 } 36066 36067 function _saveOnStaffReport() { 36068 return; 36069 /* 36070 if (location.pathname.toLowerCase() === '/reports/staffprofile') { 36071 var msg = '<div><div style="margin-bottom: 24px;">Changes Saved</div><div>Refreshing Report</div></div>'; 36072 GLO.Popup.Processing.open(msg, 'Refreshing Report...'); 36073 36074 setTimeout(function() { 36075 location.reload(); 36076 }, 200); 36077 } 36078 */ 36079 } 36080 36081 function _displayAddStaffMessage(data) { 36082 var sname = $(data).find('.wiz5-column-name').text(); 36083 36084 GLO.Popup.Success.open(sname + ' Created', 'New Staff'); 36085 } 36086 36087 function _processData(data) { 36088 if (UTIL.isEmpty(data)) { return; } 36089 36090 var jd = $(data); 36091 var msg = '<div id="pop-success-wizard">'; 36092 36093 if (!UTIL.isEmpty(jd.attr('error_cd'))) { 36094 GLO.Popup.Error.open(jd.html(), 'Save Error'); 36095 return false; 36096 } else if (!UTIL.isEmpty(jd.attr('warning_cd'))) { 36097 GLO.Popup.Warning.open(jd.html(), 'Save Warning'); 36098 return false; 36099 } else if (data === 'good' || data == 1) { 36100 msg += 'Update Successful'; 36101 } else { 36102 msg += UTIL.coalesceString(jd.html(), 'Update Successful'); 36103 } 36104 36105 GLO.Popup.Success.open(msg + '</div>', 'Save Successful', 12000); 36106 return true; 36107 } 36108 36109 function _verifyMerchantType(jform) { 36110 var juse = jform.closest('#wiz5-popupStaffProfile').parent().find('#Use_House_Merchant_fl'); 36111 if (juse.length === 0) { return; } 36112 36113 var useHouse = juse.prop('checked'); 36114 var jmt = jform.find('#Merchant_Type_cd'); 36115 36116 if (!useHouse && (!UTIL.isEmpty(jmt.val()) && GLO.Info.roleType > 219)) { 36117 jmt.val(99); 36118 } else if (useHouse) { 36119 jmt.val(GLO.Data.provider.merchant_type_cd); 36120 } 36121 } 36122 36123 /* _constructor.textMe_OnClick = function(me) { 36124 MobileProviderPopup.originalValue = $('#Mobile_Provider_cd').val(); 36125 36126 if (WIZ.page == 1) { 36127 if (me.checked) { 36128 $('#mobileProvider').val($('#Mobile_Provider_cd').val()); 36129 $('#other-desc').val($('#Mobile_Provider_vc').val()); 36130 36131 UTIL.DefaultText.init($('#text-me-popup')); 36132 $("#text-me-popup").modal({ onClose: MobileProviderPopup.close }); 36133 36134 if (GLO.Info.isMobile()) { 36135 var jpop = $('#text-me-popup'); 36136 jpop.find('label[for="mobileProvider"]').css({ "margin-top": "-11px", "display": "block", "text-align": "center" }); 36137 36138 var jbtns = $('#mobile-provider-buttons') 36139 jbtns.css({ "margin-bottom": "30px", "margin-top": "10px", "padding-left": "20px", "padding-right": "20px" }); 36140 jbtns.find('.btnCancel').css({ "width": "90px", "margin-left": "0" }); 36141 jbtns.find('.btnOk').css({ "float": "right", "width": "50px", "margin-left": "0" }); 36142 36143 $.modal.update(220, 285); 36144 } else { 36145 $.modal.update(185, 450); 36146 } 36147 36148 MobileProviderPopup.onChange(document.getElementById('mobileProvider')); 36149 } 36150 } else { // if (WIZ.page == 5 || is staff profile report 36151 if (me.checked) { 36152 $('#labelTextReminders').text(''); 36153 $('#mobileProviderInfo').removeClass('hide'); 36154 $('#Mobile_Provider_cd').removeClass('hide').focus(); 36155 } else { 36156 $('#Mobile_Provider_cd').addClass('hide'); 36157 $('#mobileProviderInfo').addClass('hide'); 36158 $('#labelTextReminders').text(SA.Resource.TextMeScheduleChanges); 36159 } 36160 } 36161 36162 $('#mobileProvider-faq').parent().remove(); 36163 } */ 36164 36165 _constructor.toolTip_OnHover = function(tip) { 36166 if (WIZ.page == 4) { 36167 var price = this.attr('price_vc'), hourlyRate = this.attr('hourly_mn'); 36168 36169 if (UTIL.isNumber(price, true)) { 36170 price = UTIL.displayMoney(price); 36171 } else if (UTIL.isNumber(hourlyRate, true)) { 36172 price = UTIL.displayMoney(hourlyRate) + '/hour'; 36173 } 36174 36175 tip.find('#desc').text(this.attr('description_tx') ? this.attr('description_tx') : ''); 36176 tip.find('#wiz4-tip-Price').text(price); 36177 36178 var tm = this.attr('time_nr'); 36179 36180 if (!UTIL.isEmpty(tm)) { 36181 var p = this.attr('process_nr'); 36182 var f = this.attr('finish_nr'); 36183 36184 if (!UTIL.isEmpty(p) && p != '0') { tm += '+ ' + p + ' (' + SA.Resource.Processing.toLowerCase() + ')'; } 36185 if (!UTIL.isEmpty(f) && f != '0') { tm += '+ ' + f + ' (' + SA.Resource.FinishOut.toLowerCase() + ')'; } 36186 } else { 36187 tm = ''; 36188 } 36189 36190 tip.find('#wiz4-tip-Time').text(tm); 36191 return true; 36192 } else { 36193 var tmp = $(this).parent().find('span').text(); 36194 if (tmp.length == '') { 36195 return false; 36196 } else { 36197 tip.find('p').text(tmp); 36198 return true; 36199 } 36200 } 36201 } 36202 36203 _constructor.genericUserPage = function(jContext) { 36204 jContext.find('#wiz1-body #labelTextReminders').text(SA.Resource.TextMeScheduleChanges); 36205 jContext.find('#wiz1-body #labelEmailReminders').text(SA.Resource.EmailAppointmentReminders); 36206 jContext.find('#wiz1-header').addClass('hide'); 36207 jContext.find('#wiz1-body').css('marginTop', '15px'); 36208 } 36209 36210 _constructor.openUserLogin = function(staffId, pop, isMinimal) { 36211 pop = _constructor.minimalUserLogin(pop, isMinimal); 36212 UTIL.DefaultText.init(pop); 36213 pop.modal(); 36214 36215 _constructor.updateModal(); 36216 $('#wiz1-body #wiz1-Save').click(function() { WIZ.popupSave(); }); 36217 _constructor.genericUserPage(pop); 36218 } 36219 36220 _constructor.minimalUserLogin = function(pop, isMinimal) { 36221 var row = 0; 36222 pop = pop ? pop : '#wiz1-body'; 36223 pop = $(pop); 36224 36225 if (isMinimal) { 36226 pop.find(".widegap > tbody > tr").each(function(i) { 36227 if (++row > 4) { 36228 $(this).addClass('hide'); 36229 } 36230 }); 36231 36232 $('#wiz1-showMore-container').removeClass('hide').css('margin-left', '130px'); 36233 } else { 36234 pop.find(".widegap > tbody > tr").each(function(i) { 36235 if (++row > 4) { 36236 $(this).removeClass('hide'); 36237 } 36238 }); 36239 36240 $('#wiz1-showMore-container').addClass('hide').css('margin-left', '70px'); 36241 } 36242 36243 //$('table.widegap').css('margin-left', '10px'); 36244 $('#wiz1-EmailReminders').addClass('hide'); 36245 $('#wiz1-popupNext').removeClass('hide'); 36246 return pop; 36247 } 36248 36249 _constructor.init = function(page, context) { //= WIZ.init 36250 if (GLO.Info.portal === undefined) { GLO.Info.init(); } 36251 36252 if (GLO.Info.portal === 'wizard') { 36253 _constructor.isWizard = true; 36254 } else { 36255 _constructor.isWizard = false; 36256 } 36257 36258 if (GLO.Info.isAndroid) { _constructor.numberInputType = "number"; } 36259 36260 _constructor.page = page; 36261 _constructor.pageContext = context ? context : 'body'; 36262 36263 var backColor = $('.shadow-content0').css('backgroundColor'); 36264 36265 if (!WIZ.isWizard && WIZ.page == 21) { // = manage web template. 36266 var jHeader = $('#wiz-status-header'); 36267 jHeader.removeClass('hide'); 36268 jHeader.find('#wiz-h21').addClass('wiz-tab').css('backgroundColor', backColor); 36269 36270 _loadSetupWebsite(); 36271 } else if ((WIZ.isWizard && WIZ.page !== 0) || (!WIZ.isWizard)) { 36272 $('#wiz-status-header').removeClass('hide'); 36273 36274 /* 36275 var individual5bonus = 0; 36276 var packageType = $.cookies.get('package'); 36277 36278 if (_constructor.page === 6 && packageType == 1) { 36279 individual5bonus = -1; 36280 } else if (!WIZ.isWizard && parseInt(GLO.Info.roleType) < 200) { 36281 individual5bonus = -1; 36282 } 36283 */ 36284 36285 var packageTabAdjust = 0; 36286 36287 if (WIZ.isWizard && page == 6) { packageTabAdjust = -1; } 36288 36289 /* //Jan 2016: if !WIZ.isWizard --> always display 'Staff' tab. 36290 if (!WIZ.isWizard && parseInt(GLO.Info.roleType) > 189) { 36291 if (GLO.Info.providerPackage !== 1) { 36292 //packageTabAdjust = -1; 36293 } else if (GLO.Info.providerPackage === 1 && GLO.Data.provider.signup == 50 && _constructor.page > 4) { 36294 packageTabAdjust = -1; 36295 } 36296 } 36297 */ 36298 36299 var oj = $('#wiz-status-header table tr td span b').eq(_constructor.page - 1 + packageTabAdjust).parent().parent(); 36300 oj.addClass('wiz-tab'); 36301 oj.css('backgroundColor', backColor); 36302 } 36303 36304 if (WIZ.isWizard) { 36305 //if ($.cookies.get('package') != '1') { $('#wiz-h4').removeClass('hide'); } 36306 36307 if (WIZ.page !== 0) { $('#btnPrev, #wiz-arrowLeft').click(WIZ.clickPrev).removeClass('hide'); } 36308 36309 if (WIZ.page === 6) { 36310 $('#btnNext').click(WIZ.clickNext).removeClass('hide'); 36311 $(context).find('input.required, select.required').removeClass('required'); 36312 } else { 36313 $('#btnNext, #wiz-arrowRight').click(WIZ.clickNext).removeClass('hide'); 36314 } 36315
36316 UI.setAccessKey('form.wizard', null, WIZ.clickNext); 36317 36318 var j = $('#wiz-status-header'); 36319 j.find('#wiz-h1').attr('title', SA.Resource.Step + ' #1'); 36320 j.find('#wiz-h2').attr('title', SA.Resource.Step + ' #2'); 36321 j.find('#wiz-h3').attr('title', SA.Resource.Step + ' #3'); 36322 j.find('#wiz-h4').attr('title', SA.Resource.Step + ' #4'); 36323 36324 if ($.cookies.get('package') != "1") { 36325 j.find('#wiz-h5').attr('title', SA.Resource.Step + ' #5'); 36326 j.find('#wiz-h6').attr('title', SA.Resource.Step + ' #6 (' + SA.Resource.LastStep.toLowerCase() + ')'); 36327 } else { 36328 j.find('#wiz-h6').attr('title', SA.Resource.Step + ' #5 (' + SA.Resource.LastStep.toLowerCase() + ')'); 36329 } 36330 36331 var pstatus = $.cookies.get('pstatus'); 36332 36333 if (UTIL.isEmpty(pstatus)) { 36334 pstatus = 0; 36335 } else { 36336 pstatus = parseInt(pstatus); 36337 } 36338 36339 if (pstatus < 5) { j.find('#wiz-h6').addClass('not-yet'); } 36340 if (pstatus < 4) { j.find('#wiz-h5').addClass('not-yet'); } 36341 if (pstatus < 3) { j.find('#wiz-h4').addClass('not-yet'); } 36342 if (pstatus < 2) { j.find('#wiz-h3').addClass('not-yet'); } 36343 if (pstatus < 1) { j.find('#wiz-h2').addClass('not-yet'); } 36344 36345 if (WIZ.page == 2 && pstatus == 1) { 36346 $('#Create_Appt_Hr_nr').val(1); 36347 $('#Update_Appt_Hr_nr').val(24); 36348 } 36349 } else { 36350 //if ($.cookies.get('package') != '1') { $('#wiz-h4').removeClass('hide').find('span').html('<b>4</b>Alerts'); } 36351
36352 if (WIZ.page === 1 || WIZ.page === 2 || WIZ.page == 3 || WIZ.page === 6) { 36353 if (GLO.Info.roleType > 169 || !UTIL.parseBool($('#wiz1-main').find('#Hide_Client_Contact_fl').val())) { 36354 $('#btnNext').css("margin-left", "").removeClass('hide').find('a').html(SA.Resource.Save).click(WIZ.save); 36355 } 36356 36357 if (WIZ.page === 2 || WIZ.page === 3) { 36358 $('#btnNext').css({ "position": "relative", "right": "inherit", "width": "60px", "margin": "auto" }); 36359 } 36360 36361 var jWizForm = $('form.wizard'); 36362 jWizForm.find('input, select, textarea').change(UTIL.Validate.changeUnsaved); 36363 UI.setAccessKey('form.wizard', null, WIZ.save); 36364 window.setTimeout(function() { UTIL.Validate.saveButton = $('#btnNext').find('a'); }, 10); 36365 } 36366 36367 $('#search-bar').removeClass('hide'); 36368 var tab = GLO.Uri.hash('tab'); 36369 36370 if (parseInt(GLO.Info.roleType) > 219) { 36371 if (tab === 'website') { 36372 _constructor.isAjaxTab = true; 36373 $('#wiz-h21').click(); 36374 } else if (tab === 'security') { 36375 _constructor.isAjaxTab = true; 36376 $('#wiz-h22').click(); 36377 } else if (tab === 'client-config') { 36378 $('.wiz5-column-client-config').click(); 36379 36380 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 36381 var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase(); 36382 36383 if (highlight.toLowerCase() == 'confirmation' || popuptab === 'client-messages') { 36384 Wiz5.initPopupUrlAction(popuptab, highlight, 1); 36385 } 36386 } 36387 } 36388 } 36389 36390 //if (GLO.Info.isMobile() && WIZ.page !== 5) { GLO.Mobile.setPageHeader(); } 36391 36392 if (GLO.Info.isMobile(true)) { 36393 GLO.Info.setupFastClick($('#bd')[0]); 36394 } 36395 36396 if (page == 4 && !WIZ.isAjaxTab) { 36397 $('#wiz4-btnAddBox').click(Wiz4.Popup.Edit.newBox); 36398 36399 if (WIZ.isWizard && $('#primary-select-container').length > 0) { 36400 if ($('#boxContainer .shadow2').length > 0) { 36401 _constructor.initWiz4(); 36402 } else { 36403 $('#wiz4-top-buttons').addClass('hide'); 36404 $('#wiz-button-top-padding').css({ "height": "40px" }); 36405 $('.shadow0, .shadow-content0').css({ "height": "" }); 36406 36407 var btnCSS = 'position: absolute; right: 8px; width: 140px;'; 36408 var btnCreateSvc = '<span class="btnCreateServices btnSave" style="' + btnCSS + '"> <a onclick="WIZ.generateServiceList()">' + SA.Resource.CreateServices + '</a> </span>'; 36409 $('#btnNext').addClass('hide').after(btnCreateSvc); 36410 } 36411 } else { 36412 _constructor.initWiz4(); 36413 } 36414 } 36415 36416 _initPage2(); 36417 _initIsCompanyDevice(); 36418 _initWizUrl(); 36419 } 36420 function _initIsCompanyDevice() { 36421 if (!UTIL.isEmpty($.cookies.get('pcg'))) { 36422 $('#wiz-status-header').addClass('is-company-device'); 36423 } 36424 } 36425 function _initPage2() { 36426 if (_constructor.page !== 2) { return; } 36427 36428 if (!_constructor.isWizard && GLO.Info.providerPackage != 1) { 36429 $('#wiz2-main #wiz2-email').removeClass('hide'); 36430 } else if (_constructor.isWizard) { 36431 $('#wiz2-staff-type').removeClass('hideX'); 36432 } 36433 } 36434 function _initWizUrl() { 36435 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 36436 36437 if (!UTIL.isEmpty(highlight)) { 36438 var jhigh = $('#' + highlight); 36439 36440 if (jhigh.length === 0) { 36441 var jhigh = $('.' + highlight); 36442 } 36443 36444 if (jhigh.length) { 36445 UI.highlight(jhigh, 100, 9500, true); 36446 } 36447 } 36448 } 36449 36450 _constructor.initServiceSetup = function() { 36451 var nm = UTIL.cleanString($.cookies.get('pname')).toLowerCase(); 36452 var industry = null; 36453 36454 if (nm.indexOf('nail') !== -1) { 36455 industry = 'i1'; 36456 } else if (nm.indexOf('hair') !== -1) { 36457 industry = 'i2'; 36458 } else if (nm.indexOf('barber') !== -1) { 36459 industry = 'i6'; 36460 } else if (nm.indexOf('lash') !== -1) { 36461 industry = 'i3'; 36462 } else if (nm.indexOf('massage') !== -1) { 36463 industry = 'i40'; 36464 } 36465 36466 if (industry) { 36467 $('#Industry_cd').val(industry).change(); 36468 } 36469 } 36470 36471 _constructor.initWiz4 = function() { 36472 Wiz4.calculateHeight();
36473 Wiz4.Popup.Edit.init(); 36474 UI.init_Tooltip(".shadow-content2 ul li", WIZ.toolTip_OnHover); 36475 36476 $(".shadow-content2").click(Wiz4.Popup.Edit.open); 36477 var gt = GLO.Uri.query('goto').toLowerCase(); 36478 var hi = GLO.Uri.query('highlight').toLowerCase(); 36479 var sgid = GLO.Uri.query('sgid'); 36480 var edit = GLO.Uri.query('edit').toLowerCase(); 36481 36482 if (gt === 'fee' && GLO.Info.roleType > 219) { 36483 $('#set-service-commission-fees').find('a').click(); 36484 } 36485 36486 if (hi === 'ccfee') { 36487 $('#wiz4-set-ccfee').addClass('help-highlight').find('input').focus(); 36488 } 36489 36490 if (UTIL.isNumber(sgid)) { 36491 $('#wiz4-main').find('#wiz4-box-' + sgid).click(); 36492 36493 if (edit === 'color') { 36494 $('#services-edit-popup #color-picker-image').click(); 36495 } 36496 } 36497 } 36498 36499 function _initSetupWebsite() { 36500 _constructor.changeCustomDomain($('#Website_Url_vc')[0], true); 36501 //GLO.Template.Manage.enableWebTemplate($('#ManageTemplate #Active_fl')[0]); 36502 36503 UTIL.Validate.saveButton = '#step-3.select-web-address .btnSave a'; 36504 36505 var js = $('#step-3.select-web-address').find('input, textarea, select'); 36506 js.change(UTIL.Validate.changeUnsaved); 36507 js.keyup(UTIL.Validate.changeUnsaved); 36508 36509 /* 36510 $('#faq-wizard-step-2>a').click(function() { 36511 window.setTimeout(function() { 36512 if ($('#step-2 .sl_examples').find('.sl-wrapper').length === 0) { 36513 $('.sl_examples').find('td > a').hoverwords({ overlay: true, dir: 'rightleft' }); 36514 } 36515 }, 100); 36516 }); 36517 */ 36518 36519 _initSetupWebsiteLanguage(); 36520 } 36521 36522 function _initSetupWebsiteLanguage() { 36523 if ($.cookies.get('language') === 'vi') { 36524 $('faq-wizard-title').text(SA.Resource.MarketYourBusinessWithYourOwnWebsite); 36525 } 36526 } 36527 36528 function _initSortGallery() { 36529 var jlist = $('#website-galleries').find('>dl'); 36530 jlist.find('dt.gallery-custom').append('<span class="gallery-drag ui-sortable-handle"></span>'); 36531 36532 jlist.sortable({ 36533 handle: '.gallery-drag' 36534 //, cancel: 'dt,input,select' 36535 , update: function(event, ui) { 36536 var dts = $('#website-galleries').find('>dl>dt'); 36537 36538 for (var i=0; i < dts.length; i++) { 36539 dts.eq(i).attr('order_sr', i+10); 36540 } 36541 36542 _saveOrder(); 36543 } 36544 }); 36545 } 36546 36547 function _saveOrder() { 36548 var xml = '', url = GLO.Link.Page.Provider.WebTemplate + 'GalleryOrder'; 36549 var dts = $('#website-galleries').find('dl > dt.gallery-custom'); 36550 36551 for (var i=0; i < dts.length; i++) { 36552 xml += '<dt order_sr="' + (i+10) + '" gallery_id="' + dts.eq(i).attr('gallery_id') + '"/>'; 36553 } 36554 36555 xml = UTIL.htmlEncode('<dl>' + xml + '</dl>'); 36556 36557 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "order_xml": xml } }) 36558 .success(function(data, textStatus, jqXHR) { 36559 36560 }) 36561 //.error(function (jqXHR, textStatus, errorThrown) { }); 36562 } 36563 36564 function _loadSetupWebsite() { 36565 _initSetupWebsite(); 36566 _initSortGallery(); 36567 36568 var hash = window.location.hash; 36569 36570 if (!UTIL.isEmpty(hash)) { 36571 hash = hash.toLowerCase(); 36572 36573 if (hash.indexOf('step=2') !== -1) { 36574 FaqWizard.clickHeader($('#faq-wizard-step-2>a')[0]); 36575 } else if (hash.indexOf('step=3') !== -1) { 36576 FaqWizard.clickHeader($('#faq-wizard-step-3>a')[0]); 36577 } else if (hash.indexOf('step=4') !== -1) { 36578 var tmp = $('#faq-wizard-step-4>a:visible'); 36579 36580 if (tmp.length === 1) { 36581 FaqWizard.clickHeader(tmp[0]); 36582 } 36583 } 36584 } 36585 36586 if (GLO.Data.Staff.require_password_appointment_edit_fl) { 36587 var css = 'position: absolute; display: block; width: 100%; height: 100%; line-height: 200%; letter-spacing: 2px; text-align: center;'; 36588 css += 'font-size: 40px; font-weight: bold; color: black; background-color: #dde; z-index: 9999; opacity: .9;'; 36589 36590 var msg = 'To edit your website please Login as Manager, Admin, or Receptionist that does not require password on edit';
36591 var overlay = '<div class="receptionist-required" style="' + css + '"> <div style="padding-top: 100px; padding-bottom: 20px; padding-left: 20px; padding-right: 12px;">' + msg + '</div> </div>'; 36592 $('#wizBody').prepend(overlay); 36593 } 36594 } 36595 36596 _constructor.updateModal = function(hgt, width) { 36597 var hgt = (hgt ? hgt : _constructor.modalDefaultHeight) + _constructor.modalAdjustHeight; 36598 var width = (width ? width : _constructor.modalDefaultWidth) + _constructor.modalAdjustWidth; 36599 36600 if (width > innerWidth) { width = innerWidth; } 36601 36602 $.modal.update(hgt, width); 36603 } 36604 36605 _constructor.closeModalPopup = function(popup) { 36606 UTIL.DefaultText.deInit(popup); 36607 $.modal.close(); 36608 } 36609 36610 _constructor.openManageWebsite = function(me) { 36611 if (WIZ.page == 6) { 36612 document.location = GLO.Info.http + document.location.host + '/wizard/website#tab=website'; 36613 return; 36614 } 36615 36616 _setupWebsite(me, 21); 36617 36618 //var url = GLO.Link.Page.Provider.WebTemplate + 'manage?isPartial=true&dt=' + UTIL.getDateString(); 36619 var url = GLO.Link.WebsiteDomain + 'wizard/website?isPartial=1&dt=' + UTIL.getDateString(); 36620 36621 var ajax_load = "<div style='width: 100px; margin: auto; margin-top: 100px;'><img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' /></div>"; 36622 var throbber = $('.loadingDiv').clone().find('img').css({ "display": "block", "margin": "auto", "padding-top": "50px" }); 36623 36624 if ( $('#change-website-template').length === 1 ) { 36625 _loadSetupWebsite(); 36626 } else { 36627 $('#wizBody').html(throbber).load(url, function() { 36628 if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; } 36629 36630 //if (GLO.Info.isIPad) { GLO.Mobile.updateViewPort('user-scalable=no, width=1040'); } 36631 36632 //GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0'); 36633 _initSetupWebsite(); 36634 }); 36635 } 36636 36637 _setWebsiteProfileUrl(); 36638 } 36639 36640 function _setupWebsite(tab, page) { 36641 WIZ.page = page; 36642 $('#feedback-container').addClass('hide'); 36643 $('.shadow0, .shadow-content0').css({ "height": "" }); 36644 $('#doc3.sa-responsive').css({ "max-width": "1240px" }); 36645 36646 var backColor = $('.shadow-content0').css('backgroundColor'); 36647 var jCurrTab = $('#wiz-status-header .wiz-tab'); 36648 jCurrTab.css('backgroundColor', '').removeClass('wiz-tab'); 36649 36650 if (UTIL.isEmptyObject(tab)) { tab = $('#wiz-h21'); } 36651 $(tab).addClass('wiz-tab').css('backgroundColor', backColor); 36652 36653 $('.wiz-buttons').remove(); 36654 36655 _setWebsiteProfileUrl(); 36656 setTimeout(GLO.Mobile.resizeStaffProfile, 450); 36657 } 36658 36659 function _setWebsiteProfileUrl() { 36660 if (GLO.Uri.hash('tab') !== 'website') { 36661 if (window.history.pushState) { 36662 window.history.pushState('Website Profile', 'Website Profile', '/wizard/website#tab=website'); 36663 } else { 36664 GLO.Uri.hash('tab', 'website'); 36665 } 36666 } 36667 } 36668 36669 function _getThrobber() { 36670 var ajax_load = "<div style='width: 100px; margin: auto; margin-top: 100px;'><img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' /></div>"; 36671 36672 var mleft = ((innerWidth - 100) * .96)/2 + 'px'; 36673 36674 return $('.loadingDiv').clone().find('img').css({"margin": "100px auto", "margin-left": mleft }); 36675 } 36676 36677 _constructor.openSetupDomain = function(company) { 36678 _setupWebsite(undefined, 22); 36679 36680 var url = GLO.Link.WebsiteDomain + 'wizard/website/' + company + '?isPartial=1&dt=' + UTIL.getDateString(); 36681 var throbber = _getThrobber(); 36682 36683 if ( $('#setup-godaddy:visible').length !== 1 ) { 36684 $('#wizBody').html(throbber).load(url, function() { 36685 if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; } 36686 36687 //GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0'); 36688 }); 36689 } 36690 } 36691 36692 _constructor.changeCustomDomain = function(element, alwaysDisplay) { 36693 if (alwaysDisplay || !UTIL.isEmpty(element.value)) { 36694 //$('.swMain ul.anchor').width(1020); 36695 $('#faq-wizard-step-4').removeClass('hide'); 36696 } else { 36697 $('#faq-wizard-step-4').addClass('hide'); 36698 //$('.swMain ul.anchor').width(1020 - 255); 36699 } 36700 } 36701 36702 _constructor.openManageSecurity = function(me) { 36703 var backColor = $('.shadow-content0').css('backgroundColor'); 36704 $('#wiz-status-header .wiz-tab').css('backgroundColor', '').removeClass('wiz-tab'); 36705 $(me).addClass('wiz-tab').css('backgroundColor', backColor); 36706 36707 $('.wiz-buttons').remove(); 36708 36709 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer?isPartial=true&dt=' + UTIL.getDateString(); 36710 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto", "margin-left": "350px" }); 36711 36712 $('#wizBody').html(throbber).load(uri, function() { 36713 if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; } 36714 36715 //if (GLO.Info.isIPad) { GLO.Mobile.updateViewPort('user-scalable=no, width=1040'); } 36716 36717 UTIL.Validate.saveButton = '#security-setup-page .btnSave a';
36718 $('#security-setup-page').find('input:visible').keyup(UTIL.Validate.changeUnsaved); 36719 $('.shadow0, .shadow-content0').css({ "height": "" }); 36720 36721 if (GLO.Info.isMobile()) { 36722 $('#doc3').css({ "width": "100%", "max-width": "720px" }); 36723 //GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0'); 36724 } 36725 36726 WIZ.SetupSecurity.init(); 36727 }); 36728 36729 _setSecurityProfileUrl(); 36730 } 36731 36732 function _setSecurityProfileUrl() { 36733 if (GLO.Uri.hash('tab') !== 'security') { 36734 if (false && window.history.pushState) { //--> need to implement this on the server-side. 36735 window.history.pushState('Website Profile', 'Website Profile', '/wizard/security#tab=security'); 36736 } else { 36737 GLO.Uri.hash('tab', 'security'); 36738 } 36739 } 36740 } 36741 36742 function _validateHoursForAndroid() { 36743 var tr = $('#wizHoursTable').find('tr'); 36744 var open, close; 36745 36746 for (var i=0; i < tr.length; i++) { 36747 if (!tr.eq(i).find('.bizClosed').prop('checked')) { 36748 open = tr.eq(i).find('.open-time'); 36749 close = tr.eq(i).find('.close-time'); 36750 36751 if (!UTIL.isEmpty(open.val()) || !UTIL.isEmpty(close.val())) { 36752 if (!UTIL.isValidTime(open.val())) { 36753 new GLO.Popup.Warning('<div><b>' + open.val() + '</b> ' + SA.Resource.IsNotValidTime + '</div>', function() { open.focus(); }); 36754 return false; 36755 } else if (!UTIL.isValidTime(close.val())) { 36756 new GLO.Popup.Warning('<div><b>' + close.val() + '</b> ' + SA.Resource.IsNotValidTime + '</div>', function() { close.focus(); }); 36757 return false; 36758 } 36759 36760 //toDo: if NOT a valid time, but is numeric --> try to make a time (i.e. '9' + ':00') 36761 } 36762 } 36763 } 36764 36765 return true; 36766 } 36767 36768 _constructor.validateHours = function() { 36769 //if (GLO.Info.isAndroid && !_validateHoursForAndroid()) { return false; } 36770 36771 var trs = $('#wizHoursTable').find('tr'); 36772 36773 for (var i=0; i < trs.length; i++) { 36774 var tr = trs.eq(i); 36775 36776 if (!tr.find('.bizClosed').prop('checked')) {
36777 var open = UTIL.timeToInt(tr.find('.open-time').val()); 36778 var strClose = $.trim(tr.find('.close-time').val()).toLowerCase(); 36779 var close = UTIL.timeToInt(strClose); 36780 36781 if (strClose == '12:00 am') { 36782 tr.find('.close-time').val(''); 36783 } else if (open > close) { 36784 if (close === 0) { 36785 tr.find('.close-time').val('11:59 pm'); 36786 } else { 36787 var weekday = UTIL.getWeekDayName(i); 36788 var h1 = '<h1 class="friendly-msg2">Invalid Time Range on ' + weekday + '</h1>'; 36789 var msg = '<p>The open time must be before the close time</p> <p>On ' + weekday + ' the open time is after the close time</p>'; 36790 var htm = '<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>'; 36791 36792 var fn = function() { tr.find('.open-time').focus(); }; 36793 new GLO.Popup.Warning(htm, fn); 36794 return false; 36795 } 36796 } 36797 } 36798 } 36799 36800 return true; 36801 } 36802 36803 _constructor.changeIndustry = function() { 36804 var industry = $('#Industry_cd').val(); 36805 var j = _hideIndustryService(); 36806 var classCount = 0; 36807 36808 if (UTIL.isEmpty(industry)) { 36809 j.addClass('hide'); 36810 } else { 36811 var jli = j.find('li.i' + industry).removeClass('hide'); 36812 var jli_opt = j.find('li.i' + industry + '-opt').removeClass('hide'); 36813 36814 if (jli_opt.length + jli.length > 1) { 36815 j.removeClass('hide'); 36816 j.find('#svc-other').removeClass('hide').find(':checkbox'); 36817 36818 for (var i=0; i < jli.length; i++) { 36819 jli.find(':checkbox').prop('checked', true); 36820 36821 if (UTIL.parseBool(jli.attr('has_class_fl'))) { ++classCount; } 36822 } 36823 36824 if (industry == 1) { 36825 //$('#primary-nail-salon').removeClass('hide'); 36826 } 36827 36828 if (classCount === 0) { 36829 j.find('#svc-other-classes').find('label').text(SA.Resource.OfferClasses); 36830 } 36831 36832 if ($('#wiz4-form #boxContainer').length > 0) { Wiz4.calculateHeight(); } 36833 } else { 36834 _constructor.generateServiceList(industry); 36835 } 36836 } 36837 } 36838 36839 function _hideIndustryService() { 36840 var j = $('#services-offered-container').addClass('hide'); 36841 var li = j.find('li').addClass('hide'); 36842 36843 for (var i=0; i < li.length; i++) { 36844 li.find(':checkbox').prop('checked', false); 36845 } 36846 36847 j.find('#create-services-button').removeClass('hide'); 36848 j.find('#svc-other-classes').find('label').text(SA.Resource.OtherClasses); 36849 36850 $('#primary-nail-salon').addClass('hide'); 36851 $('#wiz4-top-buttons').addClass('hide'); 36852 return j; 36853 } 36854 36855 _constructor.generateServiceList = function(industry) { 36856 var jlist = $('#service-setup').find(':checkbox:checked'); 36857 var svc_xml = ''; 36858 36859 if (UTIL.isEmpty(industry) && jlist.length === 0) { 36860 if ($('#services-offered-container:visible').find(':checkbox:visible').length > 0) { 36861 var msg = '<div> <h1 class="friendly-msg">' + SA.Resource.PleaseSelectService + '</h1> <div class="friendly-msg" style="font-size: large;">' + SA.Resource.PleaseCheckServiceBox + '</div> </div>'; 36862 var fn = null; 36863 } else { 36864 var msg = '<div> <h1 class="friendly-msg">' + SA.Resource.PleaseSelectService + '</h1> <div class="friendly-msg" style="font-size: large;">' + SA.Resource.PleaseSelectAService + '</div> </div>'; 36865 var fn = function() { $('#Industry_cd').focus() }; 36866 } 36867 36868 new GLO.Popup.Warning(msg, fn); 36869 return; 36870 } 36871 36872 for (var i=0; i < jlist.length; i++) { 36873 svc_xml += '<service>' + jlist.eq(i).attr('id') + '</service>'; 36874 } 36875 36876 if (i > 0) { svc_xml = UTIL.htmlEncode('<list>' + svc_xml + '</list>'); } 36877 36878 if (UTIL.isEmpty(industry)) { industry = $('#Industry_cd').val(); } //= industry empty if svc checkboxes are visible. 36879 36880 var url = GLO.Link.Object.Provider.Ajax + 'GenerateServiceList'; 36881 GLO.UI.Form.beginProcessing($('.btnCreateServices:visible')); 36882 36883 var btnNext = $('#btnNext, .wiz-buttons .btnCreateServices').addClass('hide'); 36884
36885 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "industry_cd": industry, "service_list_xml": svc_xml } }) 36886 .success(function(data, textStatus, jqXHR) { 36887 GLO.UI.Form.resetProcessing(); 36888 btnNext.removeClass('hide'); 36889 36890 var jdata = $(data).find('#boxContainer'); 36891 var jdataForm = $(data).find('form'); 36892 36893 $('#boxContainer').remove(); 36894 36895 var frm = $('#wiz4-form').removeClass('hide'); 36896 frm.prepend(jdata); 36897 36898 frm.attr('has_class_fl', jdataForm.attr('has_class_fl')); 36899 frm.attr('has_appt_fl', jdataForm.attr('has_appt_fl')); 36900 frm.attr('class_is_event_fl', jdataForm.attr('class_is_event_fl')); 36901 36902 _hideIndustryService(); 36903 $('#wiz4-top-buttons').removeClass('hide'); 36904 36905 var jbtns = $('.wiz-buttons'); 36906 jbtns.find('.btnCreateServices').addClass('hide'); 36907 jbtns.find('#btnNext').removeClass('hide'); 36908 36909 _constructor.initWiz4(); 36910 }) 36911 .error(function (jqXHR, textStatus, errorThrown) { 36912 GLO.UI.Form.resetProcessing(); 36913 btnNext.removeClass('hide'); 36914 //new GLO.Popup.Error('Unable to delete. Please try again.'); 36915 }); 36916 } 36917 36918 return _constructor; 36919})(); 36920 36921 36922WIZ.SetupSecurity = (function() { 36923 function _conSecurity() { } 36924 _conSecurity.companyComputerGuid = ''; 36925 var _suppressPopups = false; 36926 36927 _conSecurity.init = function() { 36928 var jclockin = $('#security-setup-clock-in'); 36929 var isClockInAnywhere = UTIL.parseBool(jclockin.attr('clock_in_anywhere_fl')); 36930 36931 jclockin.find(':radio').change(WIZ.SetupSecurity.saveClockInSetup); 36932 36933 if (isClockInAnywhere) { 36934 jclockin.find('#clock-in-anywhere').prop('checked', true); 36935 } else { 36936 jclockin.find('#clock-in-company-device-only').prop('checked', true); 36937 } 36938 } 36939 36940 _conSecurity.whatIsThis = function(thisIcon, isCompanyCpu, noCpuNameRequired) { 36941 var p = '<p style="white-space: pre-wrap; margin-bottom: 8px; padding-left: 12px; line-height: 170%;">'; 36942 36943 if (isCompanyCpu) { 36944 var htm = p + SA.Resource.CompanyComputerHelp1 + '</p>' + p + SA.Resource.CompanyComputerHelp2 + '</p>'; 36945 } else { 36946 var htm = p + SA.Resource.CompanyComputerHelp3 + '</p>' + p + SA.Resource.CompanyComputerHelp4 + '</p>'; 36947 36948 if (!noCpuNameRequired) { 36949 htm += p + SA.Resource.CompanyComputerHelp5 + '</p>'; 36950 } 36951 } 36952 36953 var aMoreInfo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=staff&id=faq-staff-setup-company-device\', this, null, true);">More Information</a>'; 36954 var htmMore = '<div style="margin: 8px 0 32px; text-align: center; font-weight: bold;">' + aMoreInfo + '</div>'; 36955 var ojInfo = GLO.Popup.Info.open('<div id="pop-info-company-devices">' + htm + htmMore + '</div>', 'Company Devices'); 36956 } 36957 36958 _conSecurity.addCpu = function() { 36959 var tbl = $('#security-setup-this-cpu'); 36960 var cpu = tbl.find('#Computer_Name_vc').val(); 36961 36962 if (UTIL.isEmpty(cpu)) { 36963 var cpu = _getDefaultDeviceName(); 36964 36965 if (UTIL.isEmpty(cpu)) { 36966 tbl.find('#Computer_Name_vc').parent().css('background-color', 'pink'); 36967 36968 GLO.Popup.Warning('<div style="line-height: 200%;">' + SA.Resource.PleaseEnterCompanyComputerName + '<br/>' + SA.Resource.ItCanBeAnyName + '</div>', function() { window.setTimeout( 36969 function() { $('#security-setup-this-cpu').find('#Computer_Name_vc').parent().css('background-color', ''); } 36970 , 2500) }); 36971 36972 return; 36973 } 36974 } 36975 36976 _conSecurity.addCpuConfirmed(cpu); 36977 } 36978 function _getDefaultDeviceName() { 36979 var tr = $('#current-company-computers').find('tbody > tr'); 36980 var deviceNumber = 1; 36981 36982 for (var i=0; i < tr.length; i++) { 36983 var device = $.trim(tr.eq(i).find('.column-company-cpu-name').text().toLowerCase().replace('device', '')); 36984 36985 if (UTIL.isNumber(device)) { 36986 var test = UTIL.coalesceInt(device, 0) + 1; 36987 36988 if (test > deviceNumber) { 36989 deviceNumber = test; 36990 } 36991 } 36992 } 36993 36994 return 'Device ' + deviceNumber; 36995 } 36996 36997 _conSecurity.addCpuConfirmed = function(cpu) { 36998 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer'; 36999 GLO.UI.Form.beginProcessing($('#security-setup-save')); 37000
37001 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Is_Company_Computer_fl": "1", "Computer_Name_vc": cpu, "Status_cd": "2" } }) 37002 .success(function(data, textStatus, jqXHR) { 37003 var jd = $(data); 37004 var guid = jd.attr('guid'); 37005 var pcid = jd.attr('provider_computer_id'); 37006 37007 if (guid.length > 30) { 37008 if (GLO.Info.isIPad || GLO.Info.isIPhone) { 37009 SA.App.setCompanyDevice(guid); //GLO.Mobile.iosNativeBridge.call("setCompanyDevice", [guid]); //GLO.Mobile.iosNativeBridge.call("setCompanyDevice", [guid], callbackFn); 37010 } 37011 37012 if (_suppressPopups) { 37013 _suppressPopups = false; 37014 } else { 37015 setTimeout(function() { location.reload(); }, 900); 37016 } 37017 } 37018 }) 37019 .error(function(jqXHR, textStatus, errorThrown) { 37020 if (!_suppressPopups) { 37021 new GLO.Popup.Error('Unable to setup this computer as a company computer at this time'); 37022 GLO.UI.Form.resetProcessing(); 37023 } 37024 }); 37025 } 37026 37027 _conSecurity.addRemoteCpu = function() { 37028 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer'; 37029 var tbl = $('#security-setup-generate-link-popup'); 37030 var cpu = tbl.find('#Remote_Computer_Name_vc').val(); 37031 var sid = tbl.find('#Send_To_Staff_id option:selected').val(); 37032 37033 if (UTIL.isEmpty(cpu)) { 37034 tbl.find('#Remote_Computer_Name_vc').parent().css('background-color', 'pink'); 37035 37036 GLO.Popup.Warning(SA.Resource.PleaseEnterCompanyComputerName, function() { 37037 $('#security-setup-generate-link-popup').find('#Remote_Computer_Name_vc').focus(); 37038 window.setTimeout( function() { $('#security-setup-generate-link-popup').find('#Remote_Computer_Name_vc').parent().css('background-color', ''); }, 2500) }); 37039 return; 37040 } 37041 37042 if (UTIL.isEmpty(sid)) { 37043 tbl.find('#Send_To_Staff_id').closest('tr').css('background-color', 'pink'); 37044 37045 GLO.Popup.Warning('<div style="width: 550px;">' + SA.Resource.CompanyComputerEmailHelp + '<b>' + SA.Resource.CompanyComputer + '</b></div>', function() { 37046 $('#security-setup-this-cpu').find('#Send_To_Staff_id').focus(); 37047 window.setTimeout( function() { $('#security-setup-this-cpu').find('#Send_To_Staff_id').parent().css('background-color', ''); }, 2500) }); 37048 return; 37049 } 37050 37051 GLO.UI.Form.beginProcessing($('#security-setup-generate-button')); 37052 37053 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Is_Company_Computer_fl": "1", "Computer_Name_vc": cpu, "Status_cd": "1", "Send_To_Staff_id": sid } }) 37054 .success(function(data, textStatus, jqXHR) { 37055 location.reload(); 37056 }) 37057 .error(function(jqXHR, textStatus, errorThrown) { 37058 new GLO.Popup.Error('Unable to setup this computer as a company computer at this time'); 37059 GLO.UI.Form.resetProcessing(); 37060 }); 37061 } 37062 37063 _conSecurity.removeCpu = function(btnRemove) { 37064 btnRemove = $(btnRemove); 37065 var tr = btnRemove.closest('tr'); 37066 var cpu = tr.find('.security-setup-current-cpu-name').text(); 37067 var id = tr.attr('provider_computer_id'); 37068 var guid = tr.attr('guid'); 37069 37070 var msg = '<p style="margin-bottom: 24px;">' + SA.Resource.Remove + ' <b>' + cpu + '</b> ' + SA.Resource.as_a_company_computer + '?</p>'; 37071 var fnSave = function() { WIZ.SetupSecurity.removeCpuConfirmed(id, guid, btnRemove); }; 37072 var staffCountCompanyDeviceOnly = UTIL.coalesceInt(tr.attr('logged_in_staff_device_only_sr'), 0); 37073 37074 if (staffCountCompanyDeviceOnly > 0) { 37075 msg += '<p style="margin-bottom: 24px;">This will logout the staff - because the staff logged in is only allowed to login on company devices</p>'; 37076 } 37077 37078 GLO.Popup.Confirm.open(msg, 'Remove As Company Device?', fnSave); 37079 } 37080 37081 _conSecurity.removeCpuConfirmed = function(providerCpuId, guid, btnRemove) { 37082 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer'; 37083 37084 GLO.UI.Form.beginProcessing(btnRemove); 37085
37086 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Provider_Computer_id": providerCpuId, "Status_cd": "3", "guid": guid } }) 37087 .success(function(data, textStatus, jqXHR) { 37088 GLO.Popup.Success.open('Company Device Removed Successfully', 'Device Removed'); 37089 37090 setTimeout(function() { 37091 location.reload(); 37092 }, 2500); 37093 }) 37094 .error(function(jqXHR, textStatus, errorThrown) { 37095 GLO.Popup.Error.open('Unable to remove this computer as a company computer at this time', 'Problem Removing Company Device'); 37096 GLO.UI.Form.beginProcessing(btnRemove); 37097 37098 setTimeout(function() { 37099 location.reload(); 37100 }, 2500); 37101 }); 37102 } 37103 37104 _conSecurity.remoteSetup = function() { 37105 GLO.Popup.Confirm(SA.Resource.CompanyComputerConfirm 37106 , function() { WIZ.SetupSecurity.remoteSetupConfirmed(); } 37107 , function() { document.location = GLO.Link.Page.Provider.Profile; }); 37108 } 37109 37110 _conSecurity.remoteSetupConfirmed = function() { 37111 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputerRemotely'; 37112 var guid = GLO.Uri.query("g"); 37113 var sid = GLO.Uri.query("s"); 37114 37115 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Provider_Computer_guid": guid, "Status_cd": "2", "Staff_id": sid } }) 37116 .success(function(data, textStatus, jqXHR) { 37117 GLO.Popup.Info(SA.Resource.ComputerSuccessfullySetupHello, function() { document.location = GLO.Link.Page.Provider.Profile; }); 37118 }) 37119 .error(function(jqXHR, textStatus, errorThrown) { 37120 new GLO.Popup.Error('Unable to setup this computer as a company computer at this time'); 37121 //GLO.UI.Form.resetProcessing(); 37122 }); 37123 } 37124 37125 _conSecurity.openRemotely = function() { 37126 $('#security-setup-generate-link-popup').modal(); 37127 var jModal = $('#simplemodal-container').draggable({ "handle": "h2" }); 37128 37129 jModal.find('#security-setup-generate-link-popup').css({ "padding": "0" }); 37130 jModal.find('fieldset').css({ "margin-bottom": "10px", "border-radius": "0" }); 37131 jModal.css({ "padding": "0", "left": "3px" }); 37132 37133 if (GLO.Info.isMobile()) { 37134 jModal.find('.modalCloseImg').attr("style", "top: 3px !important"); 37135 } 37136 37137 if (jModal.height() < 10 || jModal.width() < 10 || GLO.Info.isMobile()) { 37138 $.modal.update(510, 555); 37139 } else { 37140 if (GLO.Info.isIE) { 37141 jModal.find('fieldset').css({ "margin-bottom": "20px" }); 37142 } 37143 37144 $.modal.update(); 37145 } 37146 } 37147 37148 _conSecurity.justLoggedIn = function() { 37149 if (UTIL.isEmpty(WIZ.SetupSecurity.companyComputerGuid) && GLO.Info.roleType > 229) { 37150 var iconSrc = GLO.Data.cdnDirectory + 'image/questionMark.png'; 37151 var iconTitle = SA.Resource.RegisterThisComputer + ' \'' + SA.Resource.CompanyComputer + '\''; 37152 var iconCSS = 'margin-left: 20px;'; 37153 37154 var h5CSS = 'margin-left: 10px; margin-bottom: 20px;'; 37155 37156 var icon = '<span class="helpIcon2 sa-sprite" onclick="WIZ.SetupSecurity.whatIsThis(this, false, true)" alt="' + iconTitle + '" title="' + iconTitle + '" style="' + iconCSS + '"></span>'; 37157 var htm = '<div> <h5 style="' + h5CSS + '">' + SA.Resource.IsThisACompanyComputer + icon + '</h5></div>'; 37158 37159 //Temporary Disable: need to ask this less often: GLO.Popup.Confirm(htm, WIZ.SetupSecurity.askConfirmed); 37160 } 37161 } 37162 37163 _conSecurity.askConfirmed = function(cpuName) { 37164 _suppressPopups = true; 37165 _conSecurity.addCpuConfirmed(cpuName); 37166 } 37167 37168 _conSecurity.saveClockInSetup = function() { 37169 var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/ClockInSetup'; 37170 var clockAnywhere = $('#security-setup-page').find(':radio:checked').val(); 37171 37172 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Clock_In_Anywhere_fl": clockAnywhere } }) 37173 .success(function(data, textStatus, jqXHR) { 37174 var j = $('#security-setup-this-cpu'); 37175 37176 if (clockAnywhere == 0 && j.length > 0) { 37177 var nm = UTIL.coalesce(j.find('#Computer_Name_vc').val(), 'Main Computer'); 37178 37179 j.find('#Computer_Name_vc').val(nm); 37180 j.find('#security-setup-save').find('a').click(); 37181 } 37182 }); 37183 } 37184 37185 _conSecurity.openRemoteRequest = function() { 37186 var jpop0 = $('#pop-company-device-remote-request').closest('.glopop'); 37187 var username = UTIL.coalesceString(GLO.Uri.query('username'), jpop0.find('#coUser').val(), ''); 37188 var password = UTIL.cleanString(jpop0.find('#coPass').val(), $('#login-password').val()); 37189 37190 var msg1 = '<p>Send Company Device Request Email to your admin</p>'; 37191 var msg2 = '<p style="margin-bottom: 36px;">This email contains the verification code you can then enter to set this as a company device</p>'; 37192 37193 var htmUser = '<div> <label for="coUser">Your Username</label> <input type="text" id="coUser" value="' + username + '"/> </div>'; 37194 var htmPass = '<div> <label for="coPassword">Your Password</label> <input type="password" id="coPass" value="' + password + '"/> </div>'; 37195 var htmDevice = '<div> <label for="coDevice" title="What name do you want to give this device?">Device Name</label> <input type="text" id="coDevice"/> </div>'; 37196 37197 var btn = '<div><span class="btnAdd">
37197<a onclick="WIZ.SetupSecurity.sendRemoteRequest()">Send Admin Request</a></span></div>'; 37198 var htm = '<form id="pop-company-device-remote-request">' + msg1 + msg2 + htmUser + htmPass + htmDevice + '</form>'; 37199 37200 GLO.Popup.closeIfExist(jpop0); 37201 37202 var jpop = new GLO.Popup.Custom.openSimple(htm, 'Send Company Device Request', WIZ.SetupSecurity.sendRemoteRequest); 37203 jpop.find('h1').css({ "background-color": "forestgreen", "color": "white" }); 37204 jpop.find('.btnSave').css({ "min-height": "20px" }).find('> a').text('Send Email'); 37205 } 37206 _conSecurity.openRemoteVerification = function() { 37207 var tpid = $('#login-form').attr('verify_provider_id'); 37208 var jpop0 = $('#pop-company-device-remote-request').closest('.glopop'); 37209 var username = UTIL.coalesceString(GLO.Uri.query('username'), jpop0.find('#coUser').val(), ''); 37210 var password = UTIL.cleanString(jpop0.find('#coUser').val()); 37211 37212 var btnBegin = '<span class="btnAdd"><a onclick="WIZ.SetupSecurity.openRemoteRequest()" style="letter-spacing: 0;">Begin Remote Setup</a></span>'; 37213 var htmArrow = '<b class="arrow-right" style="margin-right: 4px;">➜</b>'; 37214 var msg1 = '<p>Enter verification code sent to admin email</p>'; 37215 var msg2 = '<p style="margin-bottom: 36px;">If do not have verification code ' + htmArrow + btnBegin + '</p>'; 37216 37217 var htmUser = '<div> <label for="coUser">Your Username</label> <input type="text" id="coUser" value="' + username + '"/> </div>'; 37218 var htmPass = '<div> <label for="coPassword">Your Password</label> <input type="password" id="coPass" value="' + password + '"/> </div>'; 37219 var htmVerify = '<div> <label for="Verification_Code_vc">Verification Code</label> <input type="text" id="Verification_Code_vc"/> </div>'; 37220 37221 var btn = '<div><span class="btnAdd"><a onclick="WIZ.SetupSecurity.sendRemoteRequest(' + tpid + ')">Send Admin Request</a></span></div>'; 37222 var htm = '<form id="pop-company-device-remote-request">' + msg1 + msg2 + htmUser + htmPass + htmVerify + '</form>'; 37223 37224 var jpop = new GLO.Popup.Custom.openSimple(htm, 'Company Device Complete Remote Setup', WIZ.SetupSecurity.sendRemoteRequestVerifyCode); 37225 jpop.find('h1').css({ "background-color": "forestgreen", "color": "white" }); 37226 jpop.find('.btnSave').css({ "min-height": "20px" }); 37227 } 37228 _conSecurity.sendRemoteRequest = function() { 37229 var jpop = $('#pop-company-device-remote-request').closest('.glopop'); 37230 var jsave = jpop.find('.btnSave'); 37231 37232 var user = jpop.find('#coUser').val(); 37233 var pass = jpop.find('#coPass').val(); 37234 var device = jpop.find('#coDevice').val(); 37235 37236 if (!_isValidRemoteRequest(jpop, jsave, user, pass, false)) { 37237 return; 37238 } 37239 37240 var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemoteRequest'; 37241 var json = { "username": user, "password": pass, "device": UTIL.htmlEncode(device) }; 37242 GLO.UI.Form.beginProcessing(jsave); 37243 37244 $.ajax({ type: "POST", url: url, "cache": false, data: json }) 37245 .success(function(data, textStatus, jqXHR) { 37246 var jdata = $(data); 37247 37248 if (jdata.hasClass('error')) { 37249 var ojpop2 = GLO.Popup.Warning.open(data, SA.Resource.CompanyComputerEmailFail); 37250 } else if (jdata.hasClass('success')) { 37251 GLO.Popup.closeIfExist(jpop); 37252 37253 var tpid = jdata.find('tpid'); 37254 var ojpop2 = GLO.Popup.Success.open('Please ask admin to check their email for verification code', 'Admin Sent Email'); 37255 37256 $('#login-form').attr('verify_provider_id', tpid); 37257 } else { 37258 var ojpop2 = GLO.Popup.Warning.open(data, 'Verification Code Not Sent'); 37259 } 37260 37261 GLO.UI.Form.resetProcessing(); 37262 //ojpop2.getPopup().find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "black", "color": "white" }); 37263 ojpop2.getPopup().find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" }); 37264 }) 37265 .error(function(jqXHR, textStatus, errorThrown) { 37266 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 37267 }); 37268 } 37269 _conSecurity.sendRemoteRequestVerifyCode = function(tpid) { 37270 var jpop = $('#pop-company-device-remote-request').closest('.glopop'); 37271 var jsave = jpop.find('.btnSave'); 37272 37273 var user = jpop.find('#coUser').val(); //not required 37274 var pass = jpop.find('#coPass').val(); //not required 37275 var code = jpop.find('#Verification_Code_vc').val(); 37276 37277 if (!_isValidRemoteRequest(jpop, jsave, user, pass, true, code)) { 37278 return; 37279 } 37280 37281 var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemoteComplete'; 37282 var json = { "username": user, "password": pass, "code": code, "provider": tpid }; 37283 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 37284
37285 $.ajax({ type: "POST", url: url, "cache": false, data: json }) 37286 .success(function(data, textStatus, jqXHR) { 37287 if ($(data).hasClass('error')) { 37288 var ojpop2 = GLO.Popup.Error.open(data, 'Unable to Process Verification Code'); 37289 } else if ($(data).hasClass('success')) { 37290 GLO.Popup.closeIfExist(jpop); 37291 37292 var ojpop2 = GLO.Popup.Success.open(SA.Resource.CompanyComputerNowRegistered, 'Company Device Successfully Setup'); 37293 var url = $(data).attr('url'); 37294 var jform = $('#login-form'); 37295 37296 if (jform.length) { 37297 jform.find('#login-user').val(user); 37298 jform.find('#login-password').val(pass); 37299 37300 window.setTimeout(function() { 37301 jform.find('#btnLogin').click(); 37302 }, 2500); 37303 } else if (url) { 37304 window.setTimeout(function() { 37305 document.location = GLO.Link.WebsiteDomain + url; 37306 }, 1500); 37307 } 37308 } else { 37309 var ojpop2 = GLO.Popup.Warning.open(data, 'Verification Code Not Processed'); 37310 } 37311 37312 GLO.UI.Form.resetProcessing(); 37313 //ojpop2.getPopup().find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "black", "color": "white" }); 37314 ojpop2.getPopup().find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" }); 37315 }) 37316 .error(function(jqXHR, textStatus, errorThrown) { 37317 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 37318 }); 37319 } 37320 function _isValidRemoteRequest(jpop, jsave, user, pass, isRequireVerify, verify) { 37321 var warnMsg = null, jfield = null; 37322 37323 if (jsave.hasClass('btnProcessing4')) { 37324 return false; 37325 } else if ($.trim(user).length < 4) { 37326 warnMsg = 'Please enter valid <b>Username</b>'; 37327 jfield = jpop.find('#CoUser'); 37328 } else if ($.trim(pass).length < 4) { 37329 warnMsg = 'Please enter valid <b>Password</b>'; 37330 jfield = jpop.find('#CoPass'); 37331 } else if (isRequireVerify && $.trim(verify).length < 8) { 37332 warnMsg = 'Please enter valid remote company device setup <b>Verification Code</b>'; 37333 jfield = jpop.find('#Verification_Code_vc'); 37334 } 37335 37336 if (warnMsg) { 37337 var fn = function() { 37338 jfield.focus(); 37339 UI.highlight(jfield); 37340 } 37341 37342 var jpop = GLO.Popup.Warning.open(warnMsg, 'In-Complete Warning').getPopup(); 37343 //jpop.find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "orange", "color": "white" }); 37344 jpop.find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" }); 37345 return false; 37346 } else { 37347 return true; 37348 } 37349 } 37350 37351 _conSecurity.setupRemotely = function() { 37352 new GLO.Popup.Confirm(SA.Resource.SetupThisDeviceAsA + ' <b>' + SA.Resource.CompanyComputer + '</b>?' 37353 , function() { 37354 var jform = $('#remote-company-computer-setup'); 37355 var guid = jform.find('#Provider_Computer_guid').val(); 37356 37357 var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemotely?g=' + guid; 37358 GLO.UI.Form.beginProcessing(jform.find('#progress2')); 37359 37360 $.ajax({ type: "POST", url: url, "cache": false, data: { "Provider_Computer_guid": guid } }) 37361 .success(function(data, textStatus, jqXHR) { 37362 var url = $(data).attr('url'); 37363 37364 if (url === 'err') { 37365 new GLO.Popup.Warning(SA.Resource.CompanyComputerEmailFail); 37366 } else { 37367 new GLO.Popup.Success(SA.Resource.CompanyComputerNowRegistered); 37368 37369 window.setTimeout(function() { document.location = GLO.Link.WebsiteDomain + url; }, 1500); 37370 } 37371 }) 37372 .error(function(jqXHR, textStatus, errorThrown) { 37373 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 37374 }); 37375 } 37376 ); 37377 } 37378 37379 return _conSecurity; 37380})(); 37381 37382 37383var Wiz1 = (function() { 37384 function _constructor(name) { } 37385 _constructor.header = null; 37386 37387 _constructor.init = function(pop, profileType) { 37388 if (pop != null) { 37389 var jWiz1 = pop.find('#wiz1-body'); 37390 } else { 37391 var jWiz1 = $('#wiz1-body'); 37392 } 37393 37394 UI.phoneMask(jWiz1.find("#Mobile_Phone_vc")); 37395 UI.phoneMask(jWiz1.find("#Other_Phone_vc")); 37396 jWiz1.find("#Birth_Year_sr").mask("9999"); 37397 var isNew = true; 37398 37399 if (GLO.Info.isAndroid) { 37400 jWiz1.find("#Mobile_Phone_vc, #Other_Phone_vc").attr('type', 'tel'); 37401 } 37402 37403 if (!UTIL.isEmpty(jWiz1.find('#Staff_id').val())) { 37404 isNew = false;
37405 jWiz1.find('#First_Name_vc, #Middle_Initial_c, #First_Name_vc').css({ "text-transform": "inherit" }); 37406 } 37407 37408 _initLanguage(WIZ.page, isNew, jWiz1); 37409 SA.Parent.initLinkStaffButton(jWiz1, isNew); 37410 37411 if (WIZ.page == 1) { 37412 WIZ.init(1, '#wiz1-body'); 37413 37414 /* 37415 var loadUrl = GLO.Link.Object.MobileProvider + '?dt=' + UTIL.getDateString(); 37416 37417 jWiz1.find("#mobile-providers").load(loadUrl, function() { 37418 UI.setAccessKey('#text-me-popup', null, MobileProviderPopup.save); 37419 }); 37420 */ 37421 37422 if (WIZ.isWizard) { 37423 var jrefer = jWiz1.find('#wiz-referred-by').removeClass('hide2').find('#Referred_By_vc'); 37424 var refer = UTIL.coalesce(GLO.Uri.query('Referred_By_vc'), GLO.Uri.query('refer'), GLO.Uri.query('referby'), jrefer.val(), ''); 37425 jrefer.val(refer); 37426 } else { 37427 $('#btnNext').css({ "margin": "auto", "letter-spacing": "2px" }); 37428 } 37429 } else { 37430 if (pop == null && WIZ.page != 5) { 37431 UI.setAccessKey('#wiz1-body', null, WIZ.save) 37432 } else { 37433 UI.setAccessKey('#wiz1-body', null, WIZ.popupSave, null); 37434 } 37435 37436 if (profileType === 'client' || profileType === 'clientadmin') { 37437 jWiz1.find('#wiz1-profilePhoto').addClass('hide'); 37438 jWiz1.find('#wiz1-showMore-container').addClass('hide'); 37439 jWiz1.find('#wiz1-popupNext').removeClass('hide'); 37440 } else { 37441 var imgProfile = jWiz1.find('#Image_Path_vc').val(); 37442 var staffId = jWiz1.find('#Staff_id').val(); 37443 jWiz1.find('#wiz1-profilePhoto').remove(); 37444 jWiz1.find('#wiz1-editPhoto').removeClass('hide'); 37445 37446 if (!GLO.Info.isIosApp) { var target = ' target="_blank"'; } else { var target = ''; } 37447 37448 if (!UTIL.isEmpty(imgProfile)) { 37449 var existingImg = '<a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '><img src="/upload-folder/' + imgProfile + '" height="55px" style="margin:0;"/></a>'; 37450 existingImg += '<span style="margin-left: 50px;"><a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '>' + SA.Resource.EditPhoto + '</a></span>' 37451 37452 jWiz1.find('#editPhoto').html(existingImg); 37453 } else { 37454 var noImg = '<span style="margin-left: 5px;"><a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '>' + SA.Resource.UploadPhoto + '</a></span>'; 37455 jWiz1.find('#editPhoto').css('height', '65px').html(noImg); 37456 } 37457 } 37458 37459 return; 37460 } 37461 37462 if (innerWidth < 500) { 37463 jWiz1.find('#First_Name_vc').css({ "margin-left": "8px", "margin-right": "8px" }); 37464 jWiz1.find('#Password2_vc').css({ "margin-left": "8px" }); 37465 } 37466 37467 if (innerWidth < 800) { 37468 jWiz1.find('#labelTextReminders').text('Text Me'); 37469 } 37470 37471 jWiz1.find('#wiz1-header').css('padding', '20px'); 37472 37473 if (_constructor.header == null) { 37474 jWiz1.find('.shadow0 #wiz1-header').text(SA.Resource.PleaseTellUsAboutYou); 37475 } else { 37476 jWiz1.find('#wiz1-header').text(_constructor.header); 37477 } 37478 37479 _initForPhone(); 37480 _initDisplayMessage(); 37481 _initUrlActions(); 37482 } 37483 37484 function _initUrlActions() { 37485 var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase(); 37486 var highlight = UTIL.cleanString(GLO.Uri.query('highlight')); 37487 var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase(); 37488 var btns = $('#wiz1-staff-buttons'); 37489 37490 if (!UTIL.isEmpty(open)) { 37491 if (open === 'link') { 37492 btns.find('#btnLinkStaff > a').click(); 37493 } else if (open === 'alert' || open === 'role') { 37494 btns.find('.btnAlert > a').click(); 37495 } else if (open === 'service') { 37496 btns.find('.btnService > a').click(); 37497 } else if (open === 'hour') { 37498 btns.find('.btnHour > a').click(); 37499 } else if (open === 'client') { 37500 btns.find('.btnClientSetup > a').click(); 37501 37502 if (GLO.Uri.query('tab') == 2) { popuptab = 'client-messages'; } 37503 37504 if (highlight == 'confirmation' || popuptab === 'client-messages' || popuptab === 'policy') { 37505 Wiz5.initPopupUrlAction(popuptab, highlight, 1); 37506 } 37507 } else if (open === 'bio') { 37508 btns.find('.btnBio > a').click(); 37509 } 37510 } 37511 37512 if (UTIL.cleanString(GLO.Uri.query('msg')) == 'pastdue') { 37513 var msg1 = '<p style="font-weight: bold; color: red;">Your account is past due</p>'; 37514 var msg2 = '<p>Please login as a Manager or Admin to update the card-on-file with ' + GLO.Info.getScheduleAnyoneHtm(
37514) + '</p>'; 37515 var msg3 = '<p></p>'; 37516 37517 var htm = '<div id="pop-warn-past-due">' + msg1 + msg2 + '</div>'; 37518 var jpop = GLO.Popup.Warning.open(htm, 'Account Past Due').getPopup().css({ "background-color": "#eee" }); 37519 37520 GLO.Popup.Custom.singleButton(jpop, 'Close'); 37521 } 37522 37523 UI.highlightCheck(highlight, null, 2800); 37524 } 37525 37526 function _initLanguage(page, isNew, jWiz1) { 37527 var jlanguage = jWiz1.find('#wiz-language'); 37528 var language = (window.navigator.userLanguage || window.navigator.language); 37529 var hasSaLanguage = (!UTIL.isEmpty(jlanguage.find('select').val())); 37530 var isViet = (language.indexOf('vi-') === 0); 37531 var isMS = (GLO.Data && GLO.Data.provider && GLO.Data.provider.var_cd === 3); 37532 var isNail = (GLO.Data && GLO.Data.provider && GLO.Data.provider.industry_cd === 8); 37533 var isActive = true; //($.cookies.get('pstatus') == 11); 37534 37535 if (isActive && page == 1 && (hasSaLanguage || isViet || isNew || isNail || isMS)) { 37536 jlanguage.removeClass('hide'); 37537 37538 if (isViet && isNew) { 37539 jlanguage.find('select').val(2); 37540 } 37541 } else if (jlanguage.is(':visible')) { 37542 jlanguage.remove(); 37543 $.modal.update($('#simplemodal-container').height() - 60, null); 37544 } 37545 } 37546 37547 function _initDisplayMessage() { 37548 if (GLO.Uri.query('username') == 'duplicate') { 37549 var jmsg = $('<div class="friendly-msg2"> <h1 class="friendly-msg2">' + SA.Resource.InvalidUsername + '</h1> <div>' + SA.Resource.UsernameAlreadyTaken + '</div> <div>' + SA.Resource.PleaseUseDiffUsername + '</div> </div>'); 37550 new GLO.Popup.Warning(jmsg); 37551 } 37552 } 37553 37554 function _initForPhone() { 37555 if (!GLO.Info.isMobile()) { return; } 37556 37557 var jb = $('#wizBody'); 37558 jb.find('#labelTextReminders').text('Text Me'); 37559 37560 /* 37561 var jselect = jb.find('#Female_fl'); 37562 jselect.css({ "width": "50px" }); 37563 jselect.find('option').eq(1).text('M'); 37564 jselect.find('option').eq(2).text('F'); 37565 37566 jb.find('#First_Name_vc, #Last_Name_vc, #Password_vc, #Password2_vc').css({ "width": "100px" }) 37567 37568 var trMobile = jb.find('#row-mobilePhone'); 37569 trMobile.find('td:last').attr('colspan', 2).prepend( jb.find('#Mobile_Phone_vc') ); 37570 trMobile.find('td').eq(1).remove(); 37571 37572 jb.find('#Mobile_Phone_vc').css({ "margin-right": "40px" }); 37573 jb.find('#Mobile_Phone_vc').before('<label for="Mobile_Phone_vc">' + SA.Resource.Mobile + ':</label>'); 37574 37575 jb.find('#Email_vc').css({ "width": "310px" }); 37576 jb.find('#Username_vc').before('<b>' + SA.Resource.Username + ':</b>'); 37577 jb.find('#Password_vc').before('<b>' + SA.Resource.Password + ':</b>'); 37578 37579 if (WIZ.isWizard) { 37580 jb.find('#Username_vc').css({ "width": "210px" }); 37581 } else { 37582 jb.find('#Username_vc').css({ "width": "240px" }); 37583 } 37584 */ 37585 //$('#search-bar, #ft').css({ "width": "inherit", "min-width": "inherit" }); 37586 } 37587 37588 _constructor.changeNormalStaffRole = function(element) { 37589 var jmodal = $('#simplemodal-container'); 37590 var juser = jmodal.find('#wiz1-username'); 37591 var h = jmodal.height(), isResetUsername = false; 37592 var isVisible = juser.is(':visible'); 37593 37594 if (element.value > 199) { 37595 if (!isVisible) { 37596 if (UTIL.coalesce(juser.find('input').val(), 'Username') == 'Username') { 37597 isResetUsername = true; 37598 } 37599 37600 juser.removeClass('hide').after(juser.prop('password_htm')); 37601 var jpass = jmodal.find('#wiz1-password'); 37602 UTIL.DefaultText.init(jpass); 37603 37604 Wiz1.changeNormalStaffRole_display(isResetUsername); 37605 setTimeout(function() { Wiz1.changeNormalStaffRole_display(isResetUsername); }, 120); 37606 37607 h += 100; 37608 } 37609 } else if (isVisible) { 37610 var jpass = jmodal.find('#wiz1-password'); 37611 juser.addClass('hide'); 37612 juser.prop('password_htm', jpass.outerHTML()); 37613 jpass.remove(); 37614 h -= 100; 37615 } 37616 37617 $.modal.update(h, null); 37618 } 37619 37620 _constructor.changeNormalStaffRole_display = function(isResetUsername) { //clear any 'default password' from browser + set focus. 37621 var jmodal = $('#simplemodal-container'); 37622 var juser = jmodal.find('#wiz1-username'); 37623 var jpass = jmodal.find('#wiz1-password'); 37624 37625 if (isResetUsername) { 37626 jpass.find('input').val('').blur(); 37627 } 37628 37629 jpass.find('input').val('').blur(); 37630 37631 if (isResetUsername) { 37632 juser.find('input').focus(); 37633 } else {
37634 jpass.find('input:first').focus(); 37635 } 37636 } 37637 37638 _constructor.helpPinCode = function() { 37639 var msg1 = '<p>Passwords must be 8 characters or longer</p>'; 37640 var msg2 = '<p>PIN Codes can be shorter <span class="narrow-text" style="color: inherit;">(PIN Codes are 4-10 characters)</span></p>'; 37641 var msg3 = '<p>Use your password to login</p>'; 37642 var msg4 = '<p style="margin-top: 20px;">If your account is setup to require entering password when changing appointments or accessing reports then you can use your password or PIN Code</p>'; 37643 var htm = '<div id="pop-help-pin-code">' + msg1 + msg2 + msg3 + msg4 + '</div>'; 37644 37645 var ojpop = GLO.Popup.Info.open(htm, 'PIN Code vs Password'); 37646 } 37647 37648 _constructor.UsernameIsUnique = function() { 37649 var url = GLO.Link.Object.Provider.Ajax + "UsernameIsUnique"; 37650 var j = $('#wiz1-form'); 37651 37652 var sid = j.find('#Staff_id').val(); 37653 var user = j.find('#Username_vc').val(); 37654 37655 if (UTIL.isEmpty(user)) { 37656 $('#UsernameUniqueStatus').html('').removeClass('good').removeClass('bad'); 37657 return; 37658 } 37659 37660 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { 'Username_vc': user, 'Staff_id': sid} }) 37661 .success(function(data, textStatus, jqXHR) { 37662 var jdata = $(data); 37663 37664 if (UTIL.parseBool(jdata.attr('is_unique_fl'))) { 37665 $('#UsernameUniqueStatus').removeClass('bad').addClass('good').html(SA.Resource.Available.toLowerCase()); 37666 } else { 37667 $('#UsernameUniqueStatus').removeClass('good').addClass('bad').html(SA.Resource.already_taken); 37668 GLO.ClientProfile.changeUsernameAndRetry(j); 37669 } 37670 }) 37671 .error(function(jqXHR, textStatus, errorThrown) { 37672 //_saveReset(); 37673 }) 37674 } 37675 37676 _constructor.emailChange = function(el) { 37677 var jClient = $('#wiz1-form'); 37678 var username = jClient.find('#Username_vc'); 37679 37680 if (UTIL.isEmpty(username.val()) || username.val() == 'Username') { 37681 GLO.ClientProfile.setUsername(username, el.value); 37682 username.removeClass("defaultTextActive"); 37683 _constructor.UsernameIsUnique(); 37684 } 37685 } 37686 37687 _constructor.displayTextAlertConfirm = function() { 37688 if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) { return false; } 37689 if (GLO.Info.providerPackage === 4) { return false; } 37690 37691 var jwiz1 = $('#wiz1-form'); 37692 var jtext = jwiz1.find('#Text_Appt_Reminders_fl'); 37693 var jmp = jwiz1.find('#Mobile_Provider_cd'); 37694 37695 if (UTIL.parseBool(jmp.attr('override_fl')) || !UTIL.isEmpty(jmp.val())) { // && jtext.prop('checked') 37696 return false; 37697 } 37698 37699 if (UTIL.isEmpty(jwiz1.find('#Mobile_Phone_vc').val())) { return; } 37700 37701 var ddlabelCSS = 'width: 240px; margin: auto; font-size: 18px; font-weight: bold;'; 37702 if (innerWidth < 500) { ddlabelCSS += 'display: block;'; } else { ddlabelCSS += 'padding-right: 6px;'; } 37703 37704 var ddlabel = '<label for="Staff_Mobile_Provider_cd" style="' + ddlabelCSS + '">Mobile Phone Provider</label>'; 37705 var dd = '<select id="Staff_Mobile_Provider_cd" style="letter-spacing: 1px; font-size: 16px;">' + jwiz1.find('#Mobile_Provider_cd').html() + '</select>'; 37706 var frm = '<div style="margin-top: 8px; margin-bottom: 20px;">' + ddlabel + dd + '</div>'; 37707 37708 var msg0 = 'Do you'; 37709 if (jwiz1.closest('#simplemodal-container').length) { msg0 = 'Does ' + jwiz1.find('#First_Name_vc').val(); } 37710 37711 var msg = '<p>' + msg0 + ' want to receive text alerts when clients book appointments?</p>'; 37712 var htm = '<div id="pop-staff-mobile-provider" class="friendly-msg4"><h1 class="friendly-msg">Appointment Alerts?</h1><div class="friendly-msg">' + msg + frm + '</div></div>'; 37713 var jpop = new GLO.Popup.Confirm(htm, Wiz1.saveTextAlertConfirm, Wiz1.c
37713ancelTextAlertConfirm).getPopup(); 37714 37715 jpop.find('.btnYes > a').css({ "border-radius": "20px" }); 37716 37717 jmp.attr('override_fl', '1'); 37718 return true; 37719 } 37720 37721 _constructor.saveTextAlertConfirm = function() { 37722 var jpop = $('#pop-staff-mobile-provider').closest('.glopop'); 37723 var newMP = jpop.find('#Staff_Mobile_Provider_cd').val(); 37724 37725 if (UTIL.isEmpty(newMP)) { 37726 var warnH1 = 'Please Enter Phone Company'; 37727 37728 var jwiz1 = $('#simplemodal-container #wiz1-form'); 37729 var warnMsg0 = 'your'; 37730 if (jwiz1.length) { warnMsg0 = jwiz1.find('#First_Name_vc').val() + '\'s'; } 37731 37732 var warnMsg = 'Please enter ' + warnMsg0 + ' mobile phone company to opt-in to text alerts'; 37733 var warnHtm = '<div id="pop-staff-mobile-provider-warn" class="friendly-msg4"><h1 class="friendly-msg">' + warnH1 + '</h1><div class="friendly-responsive">' + warnMsg + '</div></div>'; 37734 var fnOk = function() { jpop.find('#Staff_Mobile_Provider_cd').focus(); } 37735 37736 new GLO.Popup.Warning(warnHtm, fnOk); 37737 return 'wait'; 37738 } 37739 37740 var jwiz1 = $('#wiz1-form'); 37741 jwiz1.find('#Text_Appt_Reminders_fl').prop('checked', true); 37742 jwiz1.find('#Mobile_Provider_cd').val(newMP); 37743 37744 _constructor.saveProfile(); 37745 } 37746 37747 _constructor.cancelTextAlertConfirm = function() { 37748 $('#wiz1-form #Text_Appt_Reminders_fl').prop('checked', false); 37749 _constructor.saveProfile(); 37750 } 37751 37752 _constructor.saveProfile = function() { 37753 var jsave = $('#wiz5-popupStaffProfile #wiz1-Save'); 37754 37755 if (jsave.length) { //WIZ.page == 5 37756 jsave.find('a').click(); 37757 } else { 37758 $('#btnNext > a').click(); 37759 } 37760 } 37761 37762 return _constructor; 37763})(); 37764 37765var Wiz2 = (function() { 37766 function _constructor(name) { } 37767 37768 _constructor.geocoder; 37769 37770 _constructor.setLatLong = function(element, event) { 37771 var street = $('#Street1_vc').val(); 37772 var city = $('#City_vc').val(); 37773 var state = $('#State_cc').val(); 37774 var zip = $('#Zip_vc').val(); 37775 37776 if (UTIL.isEmpty(street) || UTIL.isEmpty(city) || UTIL.isEmpty(state) || UTIL.isEmpty(zip)) { return; } 37777 if (street === $('#Street1_vc').attr('title') || city === $('#City_vc').attr('title') || state === $('#State_cc').attr('title') || zip === $('#Zip_vc').attr('title')) { return; } 37778 37779 GLO.Map.lookupLatLong(street, city, state, zip); 37780 37781 if (element && element.name === 'State_cc') { 37782 var state = element.value; 37783 37784 if (state === 'AB' || state === 'BC' || state === 'MB' || state === 'NB' || state === 'NL' || state === 'NS' || state === 'NT' || state === 'NU' 37785 || state === 'ON' || state === 'PE' || state === 'QC' || state === 'SK' || state === 'YT') { 37786 $('#Country_Code_c2').val('CA'); 37787 } else if (state !== 'OO' || state !== '') { 37788 $('#Country_Code_c2').val('US'); 37789 } 37790 } 37791 } 37792 37793 return _constructor; 37794})(); 37795 37796var Wiz5 = (function() { 37797 function _constructor(name) { } 37798 _constructor.newProfileIsLoaded = false; 37799 var _columnNumber, _staffId; 37800 37801 _constructor.init = function() { 37802 var sortList = [[2, 1]]; //sort by Role, then Staff Name 37803 37804 $("#wiz5-stafflist").tablesorter({ headers: { 0: { sorter: false}}, textExtraction: UI.tableSorterOrderBy, sortList: sortList }).bind("sortEnd", function() { 37805 var tbody = $("#wiz5-stafflist").find("tbody"); 37806 tbody.find("tr:even").removeClass('EveryOtherRowQuiet'); 37807 tbody.find("tr:odd").addClass('EveryOtherRowQuiet'); 37808 tbody.find("tr").css({ "background-color": "" }); 37809 }); 37810 37811 WIZ.init(5, '#wiz5-context'); 37812 37813 //if ($.cookies.get('package') == "1") { $('#wiz-status-header').find('.wiz-tab').removeClass('wiz-tab').css({ "background-color": "" }); } 37814 37815 var j = $('.wiz-buttons') 37816 37817 if (WIZ.isWizard) { 37818 if (!GLO.Info.isMobile()) {
37819 j.find('#wiz5-AddProvider').removeClass('hide'); 37820 } 37821 } else { 37822 j.find('#wiz5-AddProvider').removeClass('hide'); 37823 } 37824 37825 _initHeaderLinks(); 37826 _expandHeight(); 37827 _initUrlActions(); 37828 37829 if (!WIZ.isWizard) { 37830 if (GLO.Info.isMobile()) { 37831 $('.wiz-buttons, #wiz-button-top-padding').remove(); 37832 } else { 37833 j.find('.btnDelete').removeClass('hide'); 37834 } 37835 } 37836 37837 if (GLO.Info.providerPackage === 2 || GLO.Info.providerPackage === 3 || GLO.Info.providerPackage === 10) { 37838 if (GLO.Info.roleType > 219) { 37839 GLO.Report.enableFullPageCheck(); 37840 } 37841 } else if (GLO.Info.providerPackage === 4) { 37842 _initSilverPackage(); 37843 } 37844 } 37845 37846 function _initSilverPackage() { 37847 if (innerWidth > 800) { return; } 37848 37849 var jtbl = $('#wiz5-stafflist'); 37850 var td = jtbl.find('.wiz5-column-staff-service'); 37851 37852 for (var i=0; i < td.length; i++) { 37853 var svc = td.eq(i).text(); 37854 37855 if (svc.length > 30) { 37856 td.eq(i).text(svc.substring(0,28) + '..'); 37857 } 37858 } 37859 } 37860 37861 function _initUrlActions() { 37862 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 37863 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 37864 var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase(); 37865 var sid = GLO.Uri.url('staff'); 37866 37867 if (!UTIL.isEmpty(open)) { 37868 if (sid == 0) { 37869 var tr = $('#wiz5-stafflist').find('tbody tr:first'); 37870 37871 if (tr.attr('is_fa') == '1') { tr = $('#wiz5-stafflist').find('tbody tr').eq(1); } 37872 } else { 37873 var tr = $('#wiz5-stafflist').find('#trStaff' + sid); 37874 } 37875 37876 if (open === 'profile') { 37877 tr.find('.wiz5-column-name').click(); 37878 } else if (open === 'alert' || open === 'role') { 37879 tr.find('.wiz5-column-alerts-and-role').click(); 37880 37881 if (open == 'alert') { 37882 Wiz5.initPopupUrlAction('#wiz-tab-alert > a', highlight, 1); 37883 } else if (open == 'role') { 37884 Wiz5.initPopupUrlAction('#wiz-tab-role > a', highlight, 1); 37885 } 37886 } else if (open === 'service') { 37887 tr.find('.wiz5-column-staff-service').click(); 37888 } else if (open === 'hour') { 37889 tr.find('.wiz5-column-hours').click(); 37890 } else if (open === 'client') { 37891 tr.find('.wiz5-column-client-config').click(); 37892 37893 if (highlight == 'confirmation' || popuptab === 'client-messages' || popuptab == 2) { 37894 Wiz5.initPopupUrlAction(popuptab, highlight, 1); 37895 } 37896 } else if (open === 'permission') { 37897 tr.find('.wiz5-permission-item').click(); 37898 } else if (open === 'add-staff') { 37899 $('#wiz5-AddProvider').find('a').click(); 37900 } else if (open === 'link-staff') { 37901 $('#wiz5-AddProvider').find('a').click(); 37902 37903 setTimeout(function() { 37904 $('#pop-add-staff-create-or-copy #btnAddLinkStaff').find('a').click(); 37905 }, 600); 37906 } 37907 } 37908 37909 _initHighlightColumn(highlight); 37910 } 37911 37912 _constructor.initPopupUrlAction = function(popuptab, highlight, attempt) { 37913 var jtabs = $('#simplemodal-container .tab-control'); 37914 var highlightTest = highlight.toLowerCase(); 37915 37916 if (jtabs.length > 0) { 37917 if (highlightTest == 'confirmation') { 37918 jtabs.find('#wizcc-tab-appt-message > a').click(); 37919 37920 UI.highlight($('#wiz5-cc-confirm-row'), 100); 37921 } else if (popuptab == 2 || popuptab === 'client-messages') { 37922 jtabs.find('#wizcc-tab-appt-message > a').click(); 37923 37924 if (highlightTest === 'reminder') { 37925 UI.highlight($('#wiz5-cc-reminder-row'), 100); 37926 } else if (highlightTest === 'unconfirm') { 37927 UI.highlight($('#wiz-cc-allow-unconfirm-row, #wiz-cc-text-on-unconfirm-row')); 37928 } else if (highlightTest === 'prices') { 37929 UI.highlight($('#wiz-cc-display-prices-row'), 100); 37930 } else { 37931 UI.highlightCheck(highlight, null, 800); 37932 } 37933 } else { 37934 jtabs.find(popuptab).click(); 37935 37936 if (highlightTest == 'client-note-access') { 37937 UI.highlight($('#wiz5-popupStatus-client-note-access'), 100); 37938 } else { 37939 UI.highlightCheck(highlight, null, 800); 37940 } 37941 } 37942 } else if (attempt < 9) { 37943 setTimeout(function() { 37944 Wiz5.initPopupUrlAction(popuptab, highlight, ++attempt); 37945 }, 800) 37946 } 37947 } 37948 37949 function _initHighlightColumn(highlightValue) { 37950 var highlightColumn = null; 37951 var highlight = highlightValue.toLowerCase(); 37952 37953 if (highlight == 'checkbox-column' || highlight == 'column0') { 37954 highlightColumn = 0; 37955 } else if (highlight == 'profile-column' || highlight == 'column1') { 37956 highlightColumn = 1; 37957 } else if (highlight == 'alert-column' || highlight == 'column2') { 37958 highlightColumn = 2; 37959 } else if (highlight == 'service-column' || highlight == 'column3') { 37960 highlightColumn = 3; 37961 } else if (highlight == 'hour-column' || highlight == 'column4') { 37962 highlightColumn = 4; 37963 } else if (highlight == 'client-column' || highlight == 'column5') { 37964 highlightColumn = 5; 37965 } else if (highlight == 'permission-column' || highlight == 'column6') { 37966 highlightColumn = 6; 37967 } 37968 37969 if (highlightColumn) { 37970 ++highlightColumn; 37971 var jcolumn = $('#wiz5-stafflist').find('tr th:nth-child(' + highlightColumn + '), tr td:nth-child(' + highlightColumn + ')'); 37972 37973 UI.highlight(jcolumn, 800, 9800); 37974 } 37975 } 37976 37977 function _expandHeight() { 37978 var docHeight = $('#doc3').height();
37979 var extraHeight = innerHeight - docHeight; 37980 var listHeight = $('#wiz5-stafflist-container').height(); 37981 37982 if (innerHeight > listHeight + 80) { 37983 if (listHeight < 500 && innerHeight - 400 > listHeight) { 37984 listHeight = innerHeight - 400; 37985 } 37986 37987 $('#wiz5-main').height(listHeight + 100); 37988 $('#wiz5-staffparent').height(listHeight + 20); 37989 } else if (extraHeight > 0 && listHeight > 400) { 37990 $('#wiz5-main').height(480 + extraHeight); 37991 $('#wiz5-staffparent').height(420 + extraHeight); 37992 } else if (docHeight - listHeight > 300) { 37993 if (listHeight < 300 && !GLO.Info.isMobile(true)) { 37994 if (innerHeight - listHeight > 600) { listHeight = innerHeight - 600; } 37995 if (listHeight < 300) { listHeight = 240; } 37996 } 37997 37998 $('#wiz5-main').height(150 + listHeight); 37999 $('#wiz5-staffparent').height(80 + listHeight); 38000 } 38001 } 38002 38003 function _initHeaderLinks() { 38004 $('#wiz5-th-profile').click( function(ev) { 38005 if (ev.altKey) { 38006 ev.stopPropagation(); 38007 GLO.UI.Form.beginProcessing($(this)); 38008 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/ProfileList'; 38009 } 38010 }); 38011 38012 $('#wiz5-th-notify').click( function(ev) { 38013 if (ev.altKey) { 38014 ev.stopPropagation(); 38015 GLO.UI.Form.beginProcessing($(this)); 38016 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/NotificationList'; 38017 } 38018 }); 38019 38020 $('#wiz5-services-offered').click( function(ev) { 38021 if (ev.altKey) { 38022 ev.stopPropagation(); 38023 GLO.UI.Form.beginProcessing($(this)); 38024 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll?fullpage=1'; 38025 } 38026 }); 38027 38028 $('#wiz5-th-hours').click( function(ev) { 38029 if (ev.altKey) { 38030 ev.stopPropagation(); 38031 GLO.UI.Form.beginProcessing($(this)); 38032 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/StaffHourList'; 38033 } 38034 }); 38035 38036 $('#wiz5-th-client-config').click( function(ev) { 38037 if (ev.altKey) { 38038 ev.stopPropagation(); 38039 GLO.UI.Form.beginProcessing($(this)); 38040 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/ClientConfigList'; 38041 } 38042 }); 38043 38044 $('#wiz5-permission').click( function(ev) { 38045 if (ev.altKey) { 38046 ev.stopPropagation(); 38047 GLO.UI.Form.beginProcessing($(this)); 38048 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/PermissionList?fullpage=1'; 38049 } 38050 }); 38051 } 38052 38053 _constructor.openStaffColorSelector = function() { 38054 var j = $('#color-selector'); 38055 var oj = new GLO.Popup.Custom(j); 38056 j = oj.getPopup(); 38057 38058 var aCal = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)" class="narrow-text" style="font-weight: bold; color: #139ad2;">Front Desk Calendar</a>'; 38059 var aPos = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)" class="narrow-text" style="font-weight: bold; color: #139ad2;">P.O.S. Screen</a>'; 38060 var htmHelp = '<p style="padding-top: 0; padding-left: 12px; padding-right: 6px; padding-bottom: 24px;">Color used on ' + aCal + ' Header + ' + aPos + '</p>'; 38061 var htmUseDefault = '<div> <span cd="" class="" style="border: 1px outset black; color: black;"> Use Default Color </span> </div>'; 38062 38063 j.find('#color-selector-scroll').prepend(htmHelp + htmUseDefault); 38064 j.find('#color-selector-scroll>div>span').click(Wiz5.clickStaffColorSelector); 38065 38066 var bcolor = $('#simplemodal-container').css('background-color'); 38067 j.find('#color-selector h1').css({ "background-color": bcolor }); 38068 38069 var jfoot = j.find('.pop-buttons-parent'); 38070 jfoot.find('.btnSave').remove(); 38071 jfoot.find('.btnCancel').css({ "float": "none" }).find('a').text(SA.Resource.Close); 38072 } 38073 _constructor.clickStaffColorSelector = function() { 38074 var j = $(this); 38075 var color = j.css("background-color"); 38076 var colorValue = UTIL.replaceAll($.trim(color).replace('rgba(', '').replace('rgb(', '').replace(')', ''), ' ', ''); 38077 38078 if (UTIL.replaceAll(colorValue, ',', '') == 0) { 38079 colorValue = ''; 38080 } 38081 38082 var jmodal = $('#simplemodal-container'); 38083 jmodal.find('.btnSave').find('a').css({ "border": "3px solid Red" }); 38084 jmodal.find('#Color_Rgb_vc').val(colorValue); 38085 38086 var jStaffHeader = jmodal.find('#pop-staff-profile-header'); 38087 jStaffHeader.attr('css_class_vc', j.attr('class')); 38088 jStaffHeader.css({ "background-color": color }); 38089 38090 GLO.Popup.close(); 38091 } 38092 38093 _constructor.askResetHourManualAdjust = function(editSID, manualAdjustCount) { 38094 if (manualAdjustCount > 0) { 38095 var msg1 = 'The start or end time was manually adjusted for ' + UTIL.pluralLabel(manualAdjustCount, 'day'); 38096 var msg1b = '<small style="display: block;">(by dragging the start/end time up or down)</small>'; 38097 var msg2 = 'Reset ' + UTIL.pluralLabel(manualAdjustCount, 'Day') + ' with Adjusted Start/End Time?'; 38098 var htm = '<div id="pop-confirm-wiz-day-manual-reset" style="line-height: 1.4;"><p style="margin-bottom: 24px;">' + msg1 + msg1b + '</p><p>' + msg2 + '</p></div>'; 38099 var fnReset = function() { Wiz5.saveResetHourManualAdjustment(editSID); }; 38100 38101 GLO.Popup.Confirm.open(htm, 'Reset Adjusted Start/End Times?', fnReset); 38102 } 38103 } 38104 38105 _constructor.saveResetHourManualAdjustment = function(saveForStaff) { 38106 var url = GLO.Link.WebsiteDomain + 'fragment/wizard/wiz5HoursManualAdjustReset?editstaff=' + saveForStaff; 38107 38108 GLO.Popup.close($('#pop-confirm-wiz-day-manual-reset').closest('.glopop')); 38109 38110 var jqxhr = $.ajax({ type: "GET", url: url }) 38111 .success(function(data, textStatus, jqXHR) { 38112 var test = 123; 38113 }) 38114 .error(function(jqXHR, textStatus, errorThrown) { 38115 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 38116 }); 38117 } 38118 38119 _constructor.changeDefaultScreenOnly = function(element) { 38120 _constructor.changeDefaultScreen(element); 38121 } 38122 _constructor.changeDefaultScreen = function(element) { 38123 var jpop = $('#wiz5-popupStaffConfig').closest('#simplemodal-container'); 38124 var jdefaultScreen = jpop.find('#Default_Screen_Type_cd'); 38125 var isDefaultScreenOnly = jpop.find('#Default_Screen_Only_fl').prop('checked'); 38126 38127 if (isDefaultScreenOnly && UTIL.isEmpty(jdefaultScreen.val())) { 38128 var msg = '<p style="font-size: larger; font-weight: bold;">For this login, what screen would you like to use?</p>'; 38129 var msg2 = '<p>Please select the <b>Home Screen</b></p>' 38130 var icon = '<span class="helpIcon2 sa-sprite" onclick="SA.Help.Profile.openHelpHomeScreen(this)" title="Can lock Limited Receptionist login to the home screen"></span>'; 38131 var htm = '<div id="pop-default-screen" style="text-align: center;">' + msg + msg2 + '<div>' + icon + '</div></div>'; 38132 38133 var onClosePopup = function() { 38134 UI.highlight(jdefaultScreen); 38135 jdefaultScreen.focus(); 38136 } 38137 38138 GLO.Popup.Warning.open(htm, 'Home Screen Only', onClosePopup); 38139 } 38140 } 38141 _constructor.changeRoleType = function(element, event) { 38142 var newRole = UTIL.coalesceInt(element.value); 38143 var jpop = $('#wiz5-popupStaffConfig'); 38144 var jHideClient = jpop.find('#wiz5-popupStatus-hide-client'); 38145 var jNoteAccess = jpop.find('#wiz5-popupStatus-client-note-access'); 38146 var jtrReportRole = jpop.find('#wiz5-popupStatus-role-report'); 38147 var jtrRequirePass = jpop.find('#wiz5-popupStatus-require-password'); 38148 var jtrRequireRole = jpop.find('#wiz5-popupStatus-require-role'); 38149 var jtrDefaultScreen = jpop.find('#wiz5-staff-default-screen'); 38150 var jtrDefaultScreenOnly = jpop.find('#wiz5-staff-default-screen-only').addClass('hide'); 38151 38152 if (GLO.Info.roleType > 219) { 38153 if (newRole > 149) { 38154 jNoteAccess.removeClass('hide'); 38155 } else { 38156 jNoteAccess.addClass('hide'); 38157 } 38158 38159 if (newRole > 169) { 38160 jHideClient.removeClass('hide'); 38161 } else { 38162 jHideClient.addClass('hide'); 38163 } 38164 } else { 38165 jHideClient.addClass('hide'); 38166 jNoteAccess.addClass('hide'); 38167 } 38168 38169 if (newRole > 199) { 38170 jtrRequirePass.removeClass('hide'); 38171 jtrRequireRole.removeClass('hide'); 38172 jtrDefaultScreen.removeClass('hide'); 38173 38174 if (newRole == 200) { 38175 jtrDefaultScreen.find('td.default-screen-is-report').addClass('hide'); 38176 jtrDefaultScreenOnly.removeClass('hide'); 38177 } else { 38178 jtrDefaultScreen.find('td.default-screen-is-report').removeClass('hide'); 38179 } 38180 } else { 38181 jtrRequirePass.addClass('hide'); 38182 jtrRequireRole.addClass('hide'); 38183 jtrDefaultScreen.addClass('hide'); 38184 } 38185 38186 if (newRole > 200) { 38187 jtrReportRole.removeClass('hide'); 38188 } else { 38189 jtrReportRole.addClass('hide'); 38190 } 38191 } 38192 38193 _constructor.changeConfirmOnCreate = function(element, event) { 38194 if (!element.checked) { 38195 var jupd = $('#wiz5-cc-confirm-row #Confirm_On_Update_fl'); 38196 38197 if (jupd.prop('checked')) { 38198 jupd.prop('checked', false); 38199 } 38200 } 38201 } 38202 38203 _constructor.changeConfirmOnUpdate = function(element, event) { 38204 if (element.checked) { 38205 var jcreated = $('#wiz5-cc-confirm-row #Send_Confirmation_Email_fl'); 38206 38207 if (!jcreated.prop('checked')) { 38208 jcreated.prop('checked', true); 38209 } 38210 } 38211 } 38212 38213 _constructor.staffCheckAll = function(checkBox, context) { 38214 context = context ? context : '#wiz5-stafflist tbody'; 38215 var radioList = $(context + ' input:checkbox'); 38216 var isChecked = $(checkBox).prop('checked'); 38217 //window.setTimeout(function() { if (isChecked) $(checkBox).prop('checked', true); }, 1000); 38218 38219 radioList.each(function() { 38220 if (isChecked) { 38221 $(this).prop('checked', true); 38222 } else { 38223 $(this).prop('checked', false); 38224 } 38225 }); 38226 } 38227 38228 _constructor.deleteStaff = function(isOverride) { 38229 if (!isOverride && GLO.Data.Staff.require_password_appointment_edit_fl) { 38230 var fnSave = function() { Wiz5.deleteStaff(true); }; 38231 38232 WIZ.openRequireEditPassword(fnSave); 38233 return; 38234 } 38235 38236 var ojDel = $('#staffCheck:checked'); 38237 var msgDelLink = '', delCount = ojDel.size(); 38238 38239 if (delCount === 0) { 38240 GLO.Popup.Warning(SA.Resource.PleaseSelectPerson); 38241 } else { 38242 var msg = delCount + ' ' + SA.Resource.People.toLowerCase(); 38243 var id = ojDel.parent().parent().attr('id').substr(7); 38244 38245 if (delCount === 1) { msg = ojDel.closest('tr').find('td').eq(1).text(); } 38246 38247 if (id == GLO.Info.getStaffId()) { 38248 GLO.Popup.Warning(SA.Resource.YouCannotDeleteYourself); 38249 return false; 38250 } 38251 38252 if (_hasStaffParent(ojDel)) { 38253 msgDelLink = '<div style="padding-top: 16px; padding-bottom: 24px;">' 38254 + '<input type="checkbox" id="Also_Delete_Linked_Staff_fl" style="width: 20p
38254x; height: 20px; margin-top: -4px; margin-right: 8px;"/>' 38255 + '<label for="Also_Delete_Linked_Staff_fl">Also Delete Linked Staff</label>' 38256 + '</div>'; 38257 } 38258 38259 msg = '<div class="friendly-msg4"><h1 class="friendly-msg4">Confirm Delete Staff</h1><div><div>' + SA.Resource.ConfirmDelete + ' <b>' + msg + '</b>?</div>' + msgDelLink + '</div></div>'; 38260 38261 new GLO.Popup.Confirm(msg, function() { 38262 var delLinkedStaff = $('#Also_Delete_Linked_Staff_fl').prop('checked'); 38263 var btnDel = $('.wiz-buttons .btnDelete'); 38264 GLO.UI.Form.beginProcessing(btnDel); 38265 38266 $('#staffCheck:checked').each(function() { 38267 --delCount; 38268 var sid = $(this).parent().parent().attr('id').substr(7); 38269 38270 _constructor.deleteStaffConfirmed(sid, delLinkedStaff, delCount); 38271 38272 $(this).parent().parent().remove(); 38273 }); 38274 }); 38275 } 38276 } 38277 38278 _constructor.deleteStaffAsk = function(staffid, staffName) { 38279 var htm = 'Are you sure you want to delete <b style="white-space: nowrap;">' + staffName + '</b>'; 38280 38281 var fnYes = function() { 38282 var jbtns = $('#wiz5-popupStaffProfile #wiz1-popupNext'); 38283 jbtns.find('.btnSave').addClass('hide'); 38284 GLO.UI.Form.beginProcessing(jbtns.find('.btnDelete')); 38285 38286 Wiz5.deleteStaffConfirmed(staffid, false, 0, true); 38287 }; 38288 38289 GLO.Popup.Confirm.open(htm, 'Confirm Delete Staff', fnYes); 38290 } 38291 38292 _constructor.deleteStaffConfirmed = function(staffid, delLinkedStaff, delCount, mustDeleteRow) { 38293 var url = GLO.Link.Object.Provider.Ajax + 'DeleteStaff' + '?dt=' + UTIL.getDateString(); 38294 38295 var jqxhr = $.ajax({ type: "POST", url: url, data: { "Role_Type_cd": 0, "Staff_id": staffid, "Delete_Linked_Staff_fl": delLinkedStaff } }) 38296 .success(function(data, textStatus, jqXHR) { 38297 if (UTIL.coalesceInt(delCount, 0) == 0) { 38298 GLO.UI.Form.resetProcessing(); 38299 38300 if (mustDeleteRow) { 38301 $.modal.close(); 38302 $('#wiz5-stafflist').find('#trStaff' + staffid).remove(); 38303 } 38304 } 38305 }) 38306 .error(function(jqXHR, textStatus, errorThrown) { 38307 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 38308 }); 38309 } 38310 38311 function _hasStaffParent(ojDel) { 38312 if (!SA.Parent.canLinkStaff()) { return false; } 38313 38314 for (var i=0; i < ojDel.length; i++) { 38315 if (!UTIL.isEmpty(ojDel.eq(i).closest('tr').attr('staff_parent_id'))) { 38316 return true; 38317 } 38318 } 38319 38320 return false; 38321 } 38322 38323 _constructor.openStatus = function(sid, tabNumber) { 38324 //var ajax_load = "<img class='loading' src='" + GLO.Link.WebsiteDomain + "_static/image/processing.gif' alt='loading...' />"; 38325 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"}); 38326 38327 var loadUrl = GLO.Link.Object.Provider.Wiz5Config + '?dt=' + UTIL.getDateString(); 38328 if (sid !== null) { loadUrl += '&sid=' + sid; } 38329 var pop = $('#wiz5-popupStatus'); 38330 38331 pop.html(throbber).load(loadUrl, function() { 38332 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 38333 $('#simplemodal-container').css('padding', '0').find('.simplemodal-data').css('padding', '0'); 38334 38335 UI.setAccessKey('#wiz5-popupStatus', null, WIZ.popupSave); 38336 //$("#wiz5-popupStatus input:checkbox").change(UI.CrossOutCheckbox).change(); 38337 38338 if (GLO.Info.isAndroid) { 38339 pop.find('#Email_Reminder_Day_sr').attr('type', 'number').attr('step', 'any'); 38340 pop.find('#Text_Reminder_Hr_sr').attr('type', 'number').attr('step', 'any'); 38341 } 38342 38343 pop.find('#Text_Reminder_fl').click(function() { UI.changeFocus(this, 'Text_Reminder_Hr_sr'); });
38344 pop.find('#Text2_Reminder_fl').click(function() { UI.changeFocus(this, 'Text2_Reminder_Hr_sr'); }); 38345 pop.find('#Email_Reminder_fl').click(function() { UI.changeFocus(this, 'Email_Reminder_Day_sr'); }); 38346 pop.find('#Allow_Neighbor_Within_Day_fl').click(function() { UI.changeFocus(this, 'Allow_Neighbor_Within_Day_sr'); }); 38347 38348 pop.find('#Text_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text_Reminder_fl'); }).change(); 38349 pop.find('#Text2_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text2_Reminder_fl'); }).change(); 38350 pop.find('#Email_Reminder_Day_sr').change(function() { UI.markCheckbox(this, 'Email_Reminder_fl'); }).change(); 38351 pop.find('#Allow_Neighbor_Within_Day_sr').change(function() { UI.markCheckbox(this, 'Allow_Neighbor_Within_Day_fl'); }).change(); 38352 38353 pop.find('#Email_Reminder_Day_sr').change(); 38354 pop.find("input:checkbox").change(UI.CrossOutCheckbox).change(); 38355 38356 pop.find('form').attr('action', loadUrl); 38357 WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 5, null, data); } 38358 38359 var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text(); 38360 if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); } 38361 $('form#wiz5-form-clientConfig #wiz5-staffName').text(staffName); 38362 38363 if (UTIL.isEmpty(staffName)) { 38364 $('h2#wiz5-staffName').addClass('hide'); //.css({ "background-color": "transparent" }); 38365 } 38366 38367 pop.find('#Text_Reminder_Hr_sr').focus(); 38368 38369 if ($('#Provider_Has_Enabled_ReputationMgmt').val() === 'True') { 38370 $('#wiz5-cc-reputation-management-row').removeClass('hide'); 38371 } 38372 38373 pop.find('#Client_Access_cd1, #Client_Access_cd2, #Client_Access_cd3, #Client_Access_cd4').click(Wiz5.setClientAccess); 38374 _constructor.setClientAccess(); 38375 _columnNumber = 5; _staffId = sid; 38376 38377 if (GLO.Info.isMobile()) { 38378 $('#simplemodal-container .modalCloseImg').addClass('hide'); //.attr("style", "top: 3px !important"); 38379 $('#simplemodal-container .simplemodal-wrap').css({ "border-bottom-left-radius": "4px", "border-bottom-right-radius": "4px" }); 38380 38381 if (GLO.Info.isIPhone) { 38382 pop.find('.tblSlim').find('label').css({ "-webkit-text-size-adjust": "none" }); // "font-size": "12px", 38383 } 38384 } else { 38385 $('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 38386 } 38387 38388 UTIL.Validate.init(pop); 38389 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 38390 $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 38391 $('#simplemodal-container').css({ "max-height": "760px" }); 38392 38393 _differentPackageOptions(pop); 38394 38395 $.modal.update(pop.height() + 80); 38396 pop.closest('.simplemodal-wrap').css({ "background-color": "rgb(240,240,250)" }); 38397 WIZ.addScrollBarsToSimpleModal(); 38398 38399 if (tabNumber == 2) { pop.find('#wizcc-tab-appt-message > a').click(); } 38400 }); 38401 38402 pop.modal(); 38403 _openStatusDimensions() 38404 } 38405 38406 function _differentPackageOptions(pop) { 38407 if (!GLO.Provider.isPaidAccount(true)) { 38408 var price = SA.Upgrade.getPackagePriceNumber(GLO.Info.providerPackage); 38409 38410 _addClientEmailUpgrade(pop, price); 38411 _addExistingClientUpgrade(pop, price); 38412 } else if (GLO.Info.roleType > 169) { 38413 pop.find('#wiz-cc-allow-unconfirm-row, #wiz-cc-text-on-unconfirm-row').removeClass('hide'); 38414 } 38415 } 38416 38417 _constructor.displayStatusTab = function(tabElement, tabid) { 38418 var thisLI = $(tabElement).parent(); 38419 var jtabControl = thisLI.closest('.tab-control'); 38420 var j = jtabControl.parent(); 38421 var jpop = $('#wiz5-popupStaffConfig'); 38422 38423 jtabControl.find('li.active-tab').removeClass('active-tab'); 38424 j.find('.tab-body').addClass('hide'); 38425 38426 thisLI.addClass('active-tab'); 38427 j.find('#' + tabid).removeClass('hide'); 38428 38429 _verifyStaffConfigPopupHeight(jpop); 38430 } 38431 38432 function _addExistingClientUpgrade(pop, price) { 38433 //pop.find('#ccClient_Access_cd2 > td').css({ "border-radius": "40px", "z-index": "9", "background-color": "rgba(40,40,40,.8)", "color": "#62BECB" }); 38434 } 38435 38436 function _addClientEmailUpgrade(pop, price) { 38437 var msg = '<div class="block-msg">' + SA.Resource.UpgradeForOnly + ' $' + price + ' ' + SA.Resource.AutoSendEmail + '</div>'; 38438 var btnUpgrade = '<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'send-reminders\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>'; 38439 var htmUpgrade = '<div class="block-container">' + msg + btnUpgrade + '</div>'; 38440 38441 var jmsg = pop.find('#client-config-message-to-clients').css({ "opacity": ".4" }); 38442 jmsg.parent().css({ "position": "relative" }).prepend(htmUpgrade); 38443 } 38444 38445 function _openStatusDimensions() { 38446 $('#simplemodal-container').css({ "margin-top": "10px" }) 38447 38448 if (GLO.Info.isMobile() && !GLO.Info.isLandscape() && innerWidth > 340) { 38449 $('#client-config-message-to-clients').css({ "margin": "0 10px" }); 38450 } 38451 38452 var w = 650; 38453 38454 if (innerWidth < 400) { 38455 w = parseInt(innerWidth * .98); 38456 } else if (innerWidth < 550) { 38457 w = parseInt(innerWidth * .96); 38458 } else if (innerWidth < 660) { 38459 w = parseInt(innerWidth * .94); 38460 } 38461 38462 GLO.Popup.resizeSimpleModal(w, 530, 450); 38463 } 38464 38465 _constructor.openAddress = function(sid) { 38466 var uri = GLO.Link.WebsiteDomain + 'wizard2/StaffAddress?staff=' + sid; 38467 var ojProcessing = new GLO.Popup.Processing('Looking up staff address...'); 38468
38469 $.ajax({ type: "GET", url: uri, "cache": false }) 38470 .success(function(data, textStatus, jqXHR) { 38471 ojProcessing.close(); 38472 38473 var jdata = $(data); 38474 var header = jdata.find('#staff-name-header').text(); 38475 var htm = '<div id="pop-staff-address">' + data + '</div>'; 38476 38477 if (jdata.hasClass('warning')) { 38478 GLO.Popup.Warning.open(data, 'Staff Address'); 38479 return; 38480 } 38481 38482 var jpop = new GLO.Popup.Custom.openSimple(htm, header, Wiz5.saveAddress); 38483 var jform = jpop.find('#staff-address-form'); 38484 38485 //setup drop-down for state + country 38486 var stateCode = jform.attr('state_cc'), countryCode = jform.attr('country_cc'); 38487 var stateDD = '<select id="Staff_State_cc" name="Staff_State_cc">' + $('#State_cc').html() + '</select>'; 38488 var countryDD = '<select id="Staff_Country_Code_c2" name="Staff_Country_Code_c2">' + $('#Country_Code_c2').html() + '</select>'; 38489 38490 jform.find('#Staff_State_cc').replaceWith(stateDD); 38491 jform.find('#Staff_Country_Code_c2').replaceWith(countryDD); 38492 38493 jform.find('#Staff_State_cc').find('option[value="' + stateCode + '"]').prop('selected', true); 38494 jform.find('#Staff_Country_Code_c2').find('option[value="' + countryCode + '"]').prop('selected', true); 38495 }).error(function(jqXHR, textStatus, errorThrown) { 38496 GLO.UI.Form.resetProcessing(); 38497 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 38498 }); 38499 } 38500 _constructor.saveAddress = function() { 38501 var jpop = $('#pop-staff-address').closest('.glopop'); 38502 var jform = jpop.find('#staff-address-form'); //jform.serialize() 38503 38504 var street = jform.find('#Staff_Street1_vc').val(); 38505 var city = jform.find('#Staff_City_vc').val(); 38506 var state = jform.find('#Staff_State_cc').val(); 38507 var zip = jform.find('#Staff_Zip_vc').val(); 38508 var country = jform.find('#Staff_Country_Code_c2').val(); 38509 var max = jform.find('#Outcall_Mile_Max_sr').val(); 38510 38511 var jd = { "street": UTIL.htmlEncode2(street), "city": UTIL.htmlEncode2(city), "state": state, "zip": UTIL.htmlEncode2(zip), "country": country, "max": max }; 38512 var staffId = jform.attr('staff_id'); 38513 var uri = GLO.Link.WebsiteDomain + 'wizard2/StaffAddress?staff=' + staffId; 38514 38515 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 38516 38517 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 38518 .success(function(data, textStatus, jqXHR) { 38519 GLO.UI.Form.resetProcessing(); 38520 38521 if ($(data).hasClass('success')) { 38522 GLO.Popup.closeIfExist(jpop); 38523 GLO.Popup.Success.open(data, 'Address Updated'); 38524 38525 setTimeout(function() { 38526 document.location.reload(); 38527 }, 1500); 38528 } else { 38529 GLO.Popup.Warning.open(data, 'Edit Staff Address'); 38530 } 38531 }) 38532 .error(function(jqXHR, textStatus, errorThrown) { 38533 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 38534 }); 38535 } 38536 38537 _constructor.openHours = function(sid) { 38538 if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); } 38539 38540 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "200px auto"}); 38541 var loadUrl = GLO.Link.Object.Provider.Wiz5Hours + '?dt=' + UTIL.getDateString(); 38542 38543 if (sid !== null) { loadUrl += '&sid=' + sid; } 38544 var pop = $('#wiz5-popupHours'); 38545 38546 pop.html(throbber).load(loadUrl, function() { 38547 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 38548 38549 if (GLO.Data.provider.role_change_hours_cd > GLO.Info.roleType) { 38550 pop.find('input, select').prop('disabled', true); 38551 } 38552 38553 UTIL.DefaultText.init($('#wizHours')); 38554 38555 var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text(); 38556 if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); } 38557 $('#wiz5-staffName').text(staffName); 38558 38559 if (UTIL.isEmpty(staffName)) { 38560 $('#wiz5-staffName').css({ "background-color": "transparent" }); 38561 } 38562
38563 UI.setAccessKey('#wizHours', null, WIZ.popupSave); 38564 pop.find('form').attr('action', loadUrl).attr('edit_staff_id', sid); 38565 WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 4, null, data); } 38566 38567 pop.find('#Start_tm1').focus(); 38568 _initOpenHoursFirstAvailable(pop); 38569 38570 //pop.off('click', 'button.positive'); 38571 //$('#simplemodal-container').on('click', 'button.positive', function() { Wiz5.processingCellUpdate(sid, 4); }); 38572 //pop.find('button.positive').click(function() { Wiz5.processingCellUpdate(sid, 4); }); 38573 _columnNumber = 4; _staffId = sid; 38574 38575 GLO.Hours.initAdjustedDays(sid); 38576 38577 if (GLO.Info.isMobile()) { 38578 $('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important"); 38579 38580 if (innerWidth >= 400) { 38581 $.modal.update(540, null); 38582 } 38583 } else { 38584 $('#simplemodal-container').css({ "padding": 0 }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 38585 38586 if (innerWidth < 700) { 38587 $.modal.update(null, innerWidth - 20); 38588 } 38589 } 38590 38591 var jhelp = pop.find('.help-description'); 38592 38593 if (jhelp.length > 0) { 38594 var h = pop.height() + jhelp.height(); //need to add height to popup so buttons do not overlap help description 38595 } else { 38596 var h = pop.height() + 60; 38597 } 38598 38599 $.modal.update(h, null); 38600 38601 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 38602 $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 38603
38604 if (GLO.Info.isMobile() && (WIZ.page === 1 || WIZ.page === 5) ) { 38605 if (GLO.Info.isIPhone) { 38606 var scale = 'width=320, minimum-scale=.72, maximum-scale=.8, initial-scale=.8'; 38607 } else { 38608 var scale = 'width=440, minimum-scale=.8, maximum-scale=.8, initial-scale=.8'; 38609 } 38610 38611 //GLO.Mobile.updateViewPort(scale, undefined, 'STAFF HOURS'); 38612 } 38613 38614 WIZ.addScrollBarsToSimpleModal(); 38615 }); 38616 38617 pop.modal(); 38618 _openHoursDimensions(pop) 38619 } 38620 38621 function _initOpenHoursFirstAvailable(jpop) { 38622 var jfa = jpop.find('#first-available-hours-help'); 38623 38624 if (jfa.length) { 38625 if (SA.Data.resourceJson && SA.Data.resourceJson.length) { 38626 var msg = 'The hours set above change the regular hours for your resources like: '; 38627 var resourceList = ''; 38628 38629 for (var i=0; i < SA.Data.resourceJson.length; i++) { 38630 if (i > 0) { resourceList += ', '; } 38631 38632 resourceList += SA.Data.resourceJson[i].name; 38633 } 38634 38635 jfa.find('#first-avilable-hour-change-help').html(msg + resourceList); 38636 } 38637 } 38638 } 38639 38640 function _openHoursDimensions(pop) { 38641 var w = 420, h = 510; //h = 510 38642 38643 if (GLO.Info.isMobile()) { 38644 h = 460; 38645 pop.closest('#simplemodal-container').css({ "top": "10px", "padding": "6px" }); 38646 38647 if (GLO.Info.isLandscape()) { 38648 $.modal.update(h, 555); 38649 } else if (innerWidth < 330) { 38650 $.modal.update(h, 315); 38651 } else { 38652 $.modal.update(h, (innerWidth * .96)); 38653 } 38654 } else { 38655 $.modal.update(h, 650); 38656 } 38657 } 38658 38659 _constructor.openStaffConfig = function(sid, isSalonAdmin) { //isSalonAdmin == '1' if the currently logged in user is a salon admin or manager. 38660 if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); } 38661 38662 //var ajax_load = "<img class='loading' src='" + GLO.Link.WebsiteDomain + "_static/image/processing.gif' alt='loading...' />"; 38663 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"}); 38664 38665 var loadUrl = GLO.Link.Object.Provider.Wiz5StaffConfig + '?dt=' + UTIL.getDateString(); 38666 if (sid !== null) { loadUrl += '&sid=' + sid; } 38667 var pop = $('#wiz5-popupStaffConfig'); 38668 38669 pop.html(throbber).load(loadUrl, function() { 38670 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { 38671 return; 38672 } 38673 38674 UI.setAccessKey('#wiz5-popupStaffConfig', null, WIZ.popupSave); 38675 38676 if (GLO.Info.isAndroid) { 38677 pop.find('#Text_Notify_Hr_sr').change().attr('type', 'number'); 38678 pop.find('#Email_Notify_Day_sr').attr('type', 'number'); 38679 pop.find('#Service_Commission_pct').attr('type', 'number').attr('step', 'any'); 38680 pop.find('#Hourly_Wage_mn').attr('type', 'number').attr('step', 'any'); 38681 } 38682 38683 pop.find('#Text_Notify_Hr_sr').change(); 38684 pop.find('#Email_Notify_Day_sr').change(); 38685 38686 pop.find("input:checkbox").change(UI.CrossOutCheckbox).change(); 38687 pop.find('form').attr('action', loadUrl); 38688 WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 2, null, data); } 38689 38690 var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text(); 38691 if (UTIL.isEmpty(staffName)) { staffName = $('#staff-notification-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); } 38692 38693 if (GLO.Info.roleType > 200) { 38694 if (UTIL.isEmpty(staffName)) { //is on staff member (ie. role type = staff) profile. 38695 if (sid != GLO.Info.StaffId) { 38696 $('#notification-sent-to').text('Staff'); //$('#wiz5-myNotifications legend span.quiet7').addClass('hide'); 38697 } 38698 38699 $('#wiz5-staffName').css({ "background-color": "transparent" }); 38700 38701 var j = $('#wiz5-popup-staff-config-tbl1'); 38702 38703 j.find('tr#wiz5-history').remove(); 38704 j.find('tr#wiz5-popupStatus-inactive').remove(); 38705 j.find('tr#wiz5-popupStatus-role').remove(); 38706 } else { 38707 $('#wiz5-staffName').text(staffName); 38708 38709 if (innerWidth < 600) { 38710 var maxLen = parseInt((innerWidth * 2)/100); 38711 staffName = UTIL.maxString(staffName, maxLen, true); 38712 } 38713 38714 $('#notification-sent-to').text(staffName); 38715 } 38716 } 38717 38718 if (GLO.Info.providerPackage == 1) { 38719 pop.find('#wiz5-popupStatus-staff-alert').remove(); 38720 } else if (GLO.Info.providerPackage == 20) { 38721 pop.find('#wiz5-popupStatus-staff-alert').find('select, input').prop('disabled', 'disabled'); 38722 } 38723 38724 _initHourlyWageField(sid); 38725 _initCommission(pop); 38726 _initFirstAvailable_StaffConfig(pop, sid); 38727 _initStaffConfigRoleReport(pop); 38728 _initStaffConfigTab(pop); 38729 38730 //pop.off('click', 'button.positive'); 38731 //pop.on('click', '#simplemodal-container button.positive', function() { Wiz5.processingCellUpdate(sid, 2); }); 38732 _columnNumber = 2; _staffId = sid; 38733 $('#simplemodal-container').draggable({ "handle": "h2" }).css({ "padding": 0 }).find('h2').css({ "cursor": "move" }); 38734 38735 if (GLO.Info.isMobile()) { 38736 if (innerWidth < 330) { 38737 $('#simplemodal-container').css({ "width": "315px", "height": "auto", "padding": "0" }); 38738 } 38739 38740 38741 var jlbl = pop.find('#Email_Notify_fl-label1'); 38742 jlbl.text( jlbl.text().replace(SA.Resource.WhenA + ' ', '') ); 38743 38744 jlbl = pop.find('#Text_Notify_fl-label1'); 38745 jlbl.text( jlbl.text().replace(SA.Resource.WhenA + ' ', '') ); 38746 38747 $('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important"); 38748 38749 if (GLO.Info.isIPhone) { 38750 pop.find('.tblSlim').find('label').css({ "-webkit-text-size-adjust": "none" }); // "font-size": "12px", 38751 } 38752 } else if (innerWidth < 800) { 38753 var jmodal = $('#simplemodal-container').css({ "width": (innerWidth - 40) + "px", "padding": "0" }); //, "height": "auto" 38754 jmodal.find('.hidePhone').addClass('hide'); 38755 jmodal.find('.displayPhoneOnly').removeClass('displayPhoneOnly'); 38756 38757 $.modal.update(null, null); 38758 } 38759 38760 if (WIZ.page == 1 && (GLO.Info.isIPhone || GLO.Info.isIPad)) { // && GLO.Info.isIosApp 38761 $('#wiz5-popupStatus-appnotification-flag').removeClass("hide"); 38762 $('#wiz5-popupStatus-appnotification-status-flag').addClass("hide"); 38763 SA.App.checkPushNotificationEnabled(); 38764 } else { 38765 //check if push notification enabled on any device for that staff 38766 $('#wiz5-popupStatus-appnotification-flag').addClass("hide"); 38767 $('#wiz5-popupStatus-appnotification-status-flag').removeClass("hide"); 38768 //IsPushNotificationEnabled 38769 var uri = GLO.Link.WebsiteDomain + 'message/IsStaffPushNotificationEnabled?sid=' + sid; 38770
38771 $.ajax({ type: "GET", url: uri, "cache": false }) 38772 .success(function(data, textStatus, jqXHR) { 38773 if (data.length > 1 && data == 'ON') { 38774 $('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications: <b>ON</b></span>'); 38775 } 38776 else { 38777 $('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications: <b>OFF</b></span>'); 38778 } 38779 }).error(function(jqXHR, textStatus, errorThrown) { 38780 $('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications: <b>OFF</b></span>'); 38781 }); 38782 } 38783 38784 UTIL.Validate.init(pop); 38785 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 38786 $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 38787 pop.find('input, select').change(function() { $('#simplemodal-container').find('.btnSave a').css({ "border": "3px solid Red" }); }); 38788 38789 if ($('#simplemodal-container').outerHeight() < $('#wiz5-popupStaffConfig').outerHeight()) { 38790 var h = $('#wiz5-popupStaffConfig').outerHeight() + 10; 38791 $.modal.update(h, null); 38792 } 38793 38794 _addMyAlertsUpgrade(pop) 38795 _initFinishStaffConfig(pop); 38796 WIZ.addScrollBarsToSimpleModal(); 38797 }); 38798 38799 pop.modal(); 38800 _initPopupHeight(isSalonAdmin); 38801 } 38802 function _initFinishStaffConfig(jpop) { 38803 var jrole = jpop.find('#Role_Type_cd'); 38804 38805 if (GLO.Info.providerPackage === 1) { 38806 jpop.find('#wiz-alert-role-tabs').remove(); 38807 } else if (jrole.length) { 38808 _constructor.changeRoleType(jrole[0]); 38809 } 38810 } 38811 function _initStaffConfigRoleReport(jpop) { 38812 var tr = $('#wiz5-popupStatus-role-report'); 38813 38814 if (GLO.Info.roleType > 229) { 38815 if (jpop.find('#Role_Type_cd').val() > 200) { 38816 tr.removeClass('hide'); 38817 } 38818 } else { 38819 tr.addClass('hide'); 38820 } 38821 } 38822 function _initStaffConfigTab(jpop) { 38823 if (jpop.find('#Role_Type_cd').val() > 199) { 38824 jpop.find('#wiz-tab-role > a').click(); 38825 _verifyStaffConfigPopupHeight(jpop); 38826 } else { 38827 jpop.find('#Email_Notify_Day_sr').focus(); 38828 var contentHeight = jpop.find('#wiz5-form-staffConfig').height(); 38829 var buttonHeight = 100; //= height for buttons at bottom + App Notifications On/Off (which has not loaded yet) 38830 38831 if (contentHeight + buttonHeight > jpop.height()) { 38832 $.modal.update(contentHeight + buttonHeight, null); 38833 } 38834 } 38835 } 38836 function _verifyStaffConfigPopupHeight(jpop) { 38837 var popupHeight = jpop.height(); 38838 var tabHeaderHeight = jpop.find('#wiz5-staffName').height() + jpop.find('#wiz-alert-role-tabs').height(); 38839 var tabBodyHeight = jpop.find('#wiz5-popup-staff-config-tbl1').height(); 38840 var btnFooterHeight = jpop.find('#wiz5-popupStatus-buttons').height(); 38841 38842 if (tabHeaderHeight + tabBodyHeight + btnFooterHeight + 20 > popupHeight) { 38843 jpop.height(tabHeaderHeight + tabBodyHeight + btnFooterHeight + 32); 38844 jpop.closest('#simplemodal-container').css({ "height": "" }); 38845 } 38846 } 38847 function _initFirstAvailable_StaffConfig(jpop, sid) { 38848 if (!UserPortal.isFirstAvailable(sid)) { return false; } 38849 //if (!UTIL.parseBool(jpop.find('#Is_First_Available_fl').val())) { return false; } 38850 38851 jpop.find('#wiz5-popupStatus-hide-client, #wiz5-popupStatus-role, #wiz5-popupStatus-login, #wiz5-popupStatus-require-password, #wiz5-popupStatus-client-note-access').remove(); 38852 jpop.find('#wiz5-popupStatus-commission, #wiz5-popupStatus-hourly-wage-row').remove(); 38853 jpop.find('#wiz-tab-role').addClass('hideX'); 38854 38855 return true; 38856 } 38857 38858 function _addMyAlertsUpgrade(pop) { 38859 if (GLO.Provider.isPaidAccount(true) && GLO.Info.providerPackage !== 4) { return; } 38860 var price = SA.Upgrade.getPackagePriceNumber(GLO.Info.providerPackage); 38861 38862 var msg = '<div class="block-msg">' + SA.Resource.Upgrade + ' ' + SA.Resource.AutoReceiveNotifications + '</div>'; 38863 var btnUpgrade = '<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'send-reminders\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>'; 38864 var htmUpgrade = '<div class="block-container">' + msg + btnUpgrade + '</div>'; 38865 38866 var jmsg = pop.find('#wiz5-myNotifications').css({ "opacity": ".8" }); 38867 jmsg.css({ "position": "relative" }).prepend(htmUpgrade); 38868 38869 pop.find('#wiz5-popupStatus-commission, .helpIcon2, .btnSave').remove(); 38870 38871 var jbtns = pop.find('#wiz5-popup-staff-config-tbl1').css({ "position": "relative", "width": "100%", "max-width": "600px", "margin-top": "12px", "opacity": ".8" }); 38872 jbtns.find('tr td:first-child').css({ "padding-top": "8px", "padding-bottom": "8px" }); 38873 38874 var btnCancel = jbtns.find('.btnCancel').css({ "float": "none", "width": "60px", "margin-right": "0", "text-align": "center", "letter-spacing": "1px", "font-size": "14px" }); 38875 btnCancel.find('>a').text(SA.Resource.Close); 38876 btnCancel.closest('td').css({ "padding-top": "60px", "text-align": "center" }); 38877 38878 var a2 = '<a style="color: inherit;" href="/hello/SecurityRole">assign different security roles to each staff member</a>'; 38879 var msg2 = '<div class="block-msg">' + SA.Resource.Upgrade + ' to the gold package to enable clock-in/out and for the ability to ' + a2 + '</div>'; 38880 var btnUpgrade2 = ''; //'<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'staff roles\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>'; 38881 var htmUpgrade2 = '<div class="block-container" style="max-height: ' + (jbtns.height() - 40) + 'px;">' + msg2 + btnUpgrade2 + '</div>'; 38882 38883 jbtns.prepend(htmUpgrade2); 38884 } 38885 38886 function _initPopupHeight(isSalonAdmin) { 38887 var w = 780; 38888 if (GLO.Info.isMobile()) { w = 555; } 38889 38890 if (UTIL.parseBool(isSalonAdmin)) { 38891 if (GLO.Info.isMobile()) { 38892 var h = 500; 38893 } else { 38894 var h = 550; 38895 } 38896 } else { 38897 var h = 320; 38898 } 38899 38900 GLO.Popup.resizeSimpleModal(w, h); //$.modal.update(h, w); 38901 } 38902 38903 function _initCommission(jpop) { 38904 var cnt = UTIL.coalesceInt(jpop.find('#Service_Count_sr').val(), 0); 38905 38906 if (GLO.Info.providerPackage === 1) { 38907 jpop.find('tr#wiz5-popupStatus-commission').addClass('hide2') 38908 } else if (GLO.Info.roleType < 200) { 38909 var jc = $('#wiz5-popup-staff-config-tbl1'); 38910 jc.find('#wiz5-set-commission-by-service').addClass('hide').removeAttr('onclick').removeAttr('href').css({ "border-bottom": "none" }); 38911 var c = jc.find('#Service_Commission_pct').val(); 38912 38913 if (UTIL.coalesceMoney(c) > 0) { 38914 jc.find('#wiz5-popupStatus-commission').find('b').text(c + '%'); 38915 } 38916 38917 jc.find('#Service_Commission_pct').addClass('hide'); 38918 } else if (GLO.Info.roleType < 220) { 38919 jpop.find('#Service_Commission_pct').click(GLO.Provider.Commission.canEditStaffCommission).prop('readonly', true); 38920 } 38921 38922 if (cnt === 0) { 38923 $('#wiz5-set-commission-by-service').remove(); 38924 return; 38925 } 38926 38927 var defaultCommission = UTIL.coalesceFloat(jpop.find('#Service_Commission_pct').val(), 0); 38928 var minCommission = UTIL.coalesceFloat(jpop.find('#Min_Service_Commission_pct').val(), 0); 38929 var maxCommission = UTIL.coalesceFloat(jpop.find('#Max_Service_Commission_pct').val(), 0); 38930 38931 if (minCommission == 0 && maxCommission == 0) { return; } 38932 if (maxCommission == defaultCommission && (minCommission == 0 || minCommission == defaultCommission) ) { return; } 38933 38934 if (minCommission == maxCommission && UTIL.coalesceFloat(defaultCommission, 0) == 0) { 38935 jpop.find('#Service_Commission_pct').val(minCommission); 38936 return; 38937 } 38938 38939 if (UTIL.coalesceInt(jpop.find('#Use_Default_Commission_Count_sr').val()) > 0) { 38940 if (minCommission > 0 && minCommission > defaultCommission) { 38941 minCommission = defaultCommission; 38942 } 38943 38944 if (maxCommission < defaultCommission) { 38945 maxCommission = defaultCommission; 38946 } 38947 } 38948 38949 var crange = String(minCommission).replace('.00', '') + ' - ' + String(maxCommission).replace('.00', '') + '%'; 38950 38951 if (!GLO.Info.isMobile() && GLO.Info.roleType > 210) { crange += ' (edit)'; } 38952 38953 $('#wiz5-set-commission-by-service').removeClass('hide').text(crange).css({ "margin": "inherit", "letter-spacing": "1px" }); 38954 $('#wiz5-popupStatus-commission').find('td').css({ "padding-bottom": "20px" }).find('b, #Service_Commission_pct').addClass('hide'); 38955 } 38956 38957 function _initHourlyWageField(sid) { 38958 //if (GLO.Info.roleType < 220 && GLO.Info.StaffId != sid) { return; } 38959 38960 if (_displayHourlyWageField(sid)) { 38961 var tr = $('#wiz5-popupStatus-hourly-wage-row').removeClass('hide'); 38962 38963 if (GLO.Info.roleType > 219) { 38964 var wageSummary, minWage = tr.find('#Min_Hourly_mn').val(), maxWage = tr.find('#Max_Hourly_mn').val(); 38965 38966 if (minWage != maxWage) { 38967 wageSummary = UTIL.displayMoney(minWage) + ' - ' + UTIL.displayMoney(maxWage); 38968 } else { 38969 wageSummary = UTIL.coalesceString(UTIL.displayMoney(UTIL.coalesceMoney(maxWage, minWage)), 'none'); 38970 } 38971 38972 wageSummary = '<a onclick="GLO.Provider.Commission.openEditWage(this)">' + wageSummary + '</a>'; 38973 } else { 38974 var wageSummary, minWage = tr.find('#Min_Clock_mn').val(), maxWage = tr.find('#Max_Clock_mn').val(); 38975 38976 if (minWage != maxWage) { 38977 wageSummary = UTIL.displayMoney(minWage) + ' - ' + UTIL.displayMoney(maxWage); 38978 } else { 38979 wageSummary = UTIL.displayMoney(UTIL.coalesceMoney(maxWage, minWage)); 38980 } 38981 38982 if (UTIL.isEmpty(wageSummary)) { 38983 tr.remove(); 38984 } 38985 } 38986 38987 tr.find('#wiz5-hourly-row').html(wageSummary); 38988 38989 var h = $('#wiz5-popupStaffConfig').closest('#simplemodal-container').height() + 30; 38990 $.modal.update(h, null); 38991 } 38992 } 38993 38994 function _displayHourlyWageField(sid) { 38995 if (GLO.Data.provider.isCommissionBiz) { return true; } 38996 38997 var sids = UserPortal.getStaffWhoDoInternalService(); 38998 38999 if (sids.length > 0) { 39000 if (sids.has(sid)) { //= current user performs employee-service. 39001 return true; 39002 } 39003 39004 var j = $('#ServiceGroupOptionsClone option'); 39005 var dsg, i = 0, hasClientSvc = false; 39006 39007 if (UTIL.isEmpty(j.eq(0).attr('default_service_group_id'))) { ++i; } //=first option is blank. 39008 39009 for (; i < j.length; i++) { 39010 dsg = j.eq(i).attr('default_service_group_id'); 39011 39012 if (dsg != "1009" && dsg != '9') { 39013 if (j.eq(i).attr('staff_ids').split(',').has(sid)) { 39014 hasClientSvc = true; 39015 } 39016 } 39017 } 39018 39019 if (!hasClientSvc) { return true; } 39020 } 39021 39022 var jStaffServiceCell = $('#wiz5-stafflist').find('#trStaff' + sid + ' .wiz5-column-staff-service .wiz5-updated-cell'); //= an imperfect way to see if on wiz5 and just updated services (may have added staff to employee-service but wont yet be added to '#ServiceGroupOptionsClone'). 39023 if (jStaffServiceCell.length === 1) { return true; }
39023 //toDo: (this is a quick fix) Should do this check on the server when open staff config. 39024 39025 //if (GLO.Data.provider.isCommissionBiz) { return true; } 39026 return false; 39027 } 39028 39029 _constructor.openBio = function(url, me, event) { 39030 var fn = function() { GLO.Uri.gotoUri(url, me, event, true); }; 39031 39032 if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) { 39033 WIZ.openRequireEditPassword(fn); 39034 } else { 39035 fn(); 39036 } 39037 } 39038 _constructor.openBioSimple = function(me, event) { 39039 var jpop = $('#wiz5-popupStatus').closest('#simplemodal-container'); 39040 var staffId = jpop.find('#Staff_id').val(); 39041 var url = GLO.Data.provider.urikey + '/About/edit?staff=' + staffId + '&helloback=profile'; 39042 39043 _constructor.openBio(url, me, event); 39044 } 39045 39046 function _ifFirstAvailableDoesNotApply(element, msg) { 39047 var tr = $(element).closest('tr'); 39048 39049 if (tr.attr('is_fa') === '1') { 39050 msg += ' does not apply to First Available'; 39051 new GLO.Popup.Info('<div><h1 class="friendly-msg">First Available</h1><div class="friendly-msg2" style="margin-bottom: 12px;">' + msg + '</div></div>'); 39052 39053 return true; 39054 } else { 39055 return false; 39056 } 39057 } 39058 39059 _constructor.openPermission = function(element, sid) { 39060 if (_ifFirstAvailableDoesNotApply(element, 'Inventory Permissions')) { return; } 39061 39062 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "200px auto"}); 39063 var pop = $('#wiz5-popupPermission'); 39064 39065 var loadUrl = GLO.Link.WebsiteDomain + 'fragment/wizard/wiz5Permission?dt=' + UTIL.getDateString(); 39066 39067 if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); } 39068 if (sid !== null) { loadUrl += '&sid=' + sid; } 39069 39070 pop.html(throbber).load(loadUrl, function() { 39071 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 39072 UTIL.DefaultText.init($('#wizPermissions')); 39073 39074 var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text(); 39075 if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); } 39076 $('#wiz5-staffName').text(staffName); 39077 39078 if (UTIL.isEmpty(staffName)) { 39079 $('#wiz5-staffName').css({ "background-color": "transparent" }); 39080 } 39081 39082 UI.setAccessKey('#wizPermission', null, WIZ.popupSave); 39083 pop.find('form').attr('action', loadUrl); 39084 39085 WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 6, null, data); } 39086 _columnNumber = 6; _staffId = sid; 39087 39088 $('#simplemodal-container').css({ "padding": "0" }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 39089 39090 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 39091 $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 39092 39093 WIZ.addScrollBarsToSimpleModal(); 39094 }); 39095 39096 pop.modal(); 39097 39098 if (GLO.Info.isMobile()) { 39099 $('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important"); 39100 $.modal.update(700, (innerWidth * .98) ); 39101 } else if (innerWidth > 700) { 39102 $.modal.update(700, 690); 39103 } else { 39104 $.modal.update(700, (innerWidth * .98) ); 39105 } 39106 } 39107 39108 function _processForNonWizardPage() { 39109 var j = $('#commission-by-staff-service'); 39110 39111 if (j.length > 0) { 39112 var jpop = $('#simplemodal-container').css({ "padding": "0" }); 39113 jpop.find('.simplemodal-data').css({ "padding": "0" }); 39114 39115 var sname = UTIL.cleanString(j.find('h2').attr('staff_name_vc')); 39116 39117 setTimeout(function() { //= have to reset later so not overridden. 39118 WIZ.Popup.onSave = function() { 39119 new GLO.Popup.Processing('Updating Services for ' + sname); 39120 location.reload(); 39121 } 39122 }, 1500); 39123 39124 return sname; 39125 } else { 39126 return ''; 39127 } 39128 } 39129
39130 _constructor.openCopyStaffService = function(changeSid, changeSname) { 39131 $.modal.close(); 39132 39133 var ojProcessing = new GLO.Popup.Processing('Opening Staff List...'); 39134 var uri = GLO.Link.Object.Provider.Ajax + 'StaffModelList?ignore-staff=' + changeSid; 39135 39136 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false }) 39137 .success(function(data, textStatus, jqXHR) { 39138 ojProcessing.close(); 39139 39140 var h1 = 'Copy Staff Service Setup'; 39141 var msg = '<p style="margin: 0 8px;">Select Staff to Copy: Service Length, Prices, Commission, and Goals to ' + changeSname + '</p>'; 39142 var htm = '<div id="pop-copy-staff-list" change_staff_id="' + changeSid + '" change_staff_vc="' + changeSname + '">' + msg + data + '</div>'; 39143 var jpop = new GLO.Popup.Custom.openSimple(htm, h1); 39144 39145 GLO.Popup.Custom.singleButton(jpop); 39146 jpop.find('input[type="radio"]').change(Wiz5.saveCopyStaffService); 39147 }); //.error(function(jqXHR, textStatus, errorThrown) { }); 39148 } 39149 _constructor.saveCopyStaffService = function() { 39150 var jmsg = $('#pop-copy-staff-list'); 39151 var jpop = jmsg.closest('.glopop'); 39152 var changeSid = jmsg.attr('change_staff_id'); 39153 var changeStaffName = jmsg.attr('change_staff_vc'); 39154 39155 var jradio = $(this); 39156 var copySid = jradio.closest('li').attr('staff_id'); 39157 39158 //var changeStaffName = UserPortal.getStaffName(changeSid); 39159 var copyStaffName = jmsg.find('label[for="model-staff' + copySid + '"]').find('b').text(); 39160 39161 var htmArrow = ' ➜ '; 39162 var msg1 = '<p>Copy Service Setup from ' + copyStaffName + '?</p>'; 39163 var msg2 = '<p>' + copyStaffName + htmArrow + changeStaffName + '</p>'; 39164 var htm = '<div id="pop-confirm-copy-staff">' + msg1 + msg2 + '</div>'; 39165 39166 var fnYes = function() { 39167 Wiz5.saveCopyStaffServiceConfirmed(copySid, changeSid); 39168 } 39169 var fnNo = function() { 39170 jradio.prop('checked', false); 39171 GLO.UI.Form.resetProcessing(); 39172 } 39173 39174 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 39175 GLO.Popup.Confirm.open(htm, 'Confirm Copy Staff', fnYes, fnNo); 39176 } 39177 _constructor.saveCopyStaffServiceConfirmed = function(copySid, changeSid) { 39178 var jpop1 = $('#pop-confirm-copy-staff').closest('.glopop'); 39179 var jpop2 = $('#pop-copy-staff-list').closest('.glopop'); 39180 39181 GLO.Popup.close(jpop2); 39182 39183 jpop1.find('.btnNo').addClass('hide'); 39184 GLO.UI.Form.beginProcessing(jpop1.find('.btnYes')); 39185 39186 var uri = GLO.Link.Object.Provider.Ajax + 'StaffUpdateFromModel?copystaff=' + copySid + '&changestaff=' + changeSid; 39187 39188 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false }) 39189 .success(function(data, textStatus, jqXHR) { 39190 GLO.Popup.close(jpop1); 39191 GLO.Popup.Success.open('Service Setup Successfully Copied', 'Copy Completed'); 39192 39193 var j = $('#wiz5-stafflist'); 39194 var tdCopy = j.find('#trStaff' + copySid).find('td.wiz5-column-staff-service'); 39195 var tdChange = j.find('#trStaff' + changeSid).find('td.wiz5-column-staff-service'); 39196 tdChange.attr('title', tdCopy.attr('title')); 39197 tdChange.text(tdCopy.text()); 39198 }); //.error(function(jqXHR, textStatus, errorThrown) { }); 39199 } 39200 _constructor.openServicesOffered = function(sid, notPartialView) { 39201 if (UTIL.isEmpty(sid)) { 39202 sid = GLO.Info.getStaffId(); 39203 } 39204 39205 //var fnManual = function() { Wiz5.openServicesOffered2(sid, notPartialView); }; 39206 39207 if (GLO.Data.provider.packageType == 2 && GLO.Info.roleType > 209) { 39208 $('#quick-view-header') 39209 } 39210 39211 Wiz5.openServicesOffered2(sid, notPartialView); 39212 } 39213 _constructor.copyServicesOffered = function(sid, notPartialView) { 39214 var staffName = $('#quick-view-header').text(); 39215 39216 if (UTIL.isEmpty(staffName)) { 39217 staffName = $('#wiz5-stafflist').find('#trStaff' + sid).find('td.wiz5-column-name').text(); 39218 } 39219 39220 var fnCopy = function() { Wiz5.openCopyStaffService(sid, staffName); }; 39221 var fnManual = function() { }; 39222 39223 var msg = 'Would you like to copy the service times, prices, commission, and goals of another staff member?'; 39224 var htm = '<div id="pop-confirm-copy-service-setup">' + msg + '</div>'; 39225 39226 var jpop = GLO.Popup.Confirm.open(htm, 'Copy Service Setup', fnCopy, fnManual).getPopup(); 39227 jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" }); 39228 jpop.find('.btnNo').removeClass('btnNo').addClass('btnAdd').find('>
39228a').text(' No ').css({ "position": "absolute", "left": "8px", "font-size": "16px" }); 39229 jpop.find('.btnYes').removeClass('btnYes').addClass('btnAdd').find('>a').text('Yes, Copy').css({ "position": "absolute", "right": "8px", "font-size": "16px" }); 39230 } 39231 _constructor.openServicesOffered2 = function(sid, notPartialView) { 39232 var staffName = $('#quick-view-header').text(); 39233 $.modal.close(); 39234 39235 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"}); 39236 var loadUrl = GLO.Link.Object.Provider.Wiz5Service + '?dt=' + UTIL.getDateString(); 39237 if (sid !== null) { loadUrl += '&sid=' + sid; } 39238 39239 if (notPartialView) { 39240 document.location = loadUrl + '&fullpage=1&helloback=profile&pageback=1'; 39241 return; 39242 } 39243 39244 var pop = $("#wiz5-popupServices"); 39245 39246 pop.html(throbber).load(loadUrl, function() { 39247 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 39248 39249 UI.setAccessKey('#wiz5-popupServices', null, WIZ.popupSave); 39250 _setServicesStaffName(staffName, sid); 39251 39252 pop.find('td > input:checkbox').each(function() { 39253 Wiz5.staffServiceChecked(this); 39254 }); 39255 39256 pop.find('td > input[type="number"], td > input[type="text"]').each(function() { 39257 $(this).change(function() { 39258 if (this.value != '') { 39259 var chk = $(this).parent().parent().find(':checkbox'); 39260 Wiz5.staffServiceChecked(chk); 39261 } 39262 }) 39263 }); 39264 39265 initServicesPopup(); 39266 39267 UTIL.Validate.init(pop.find('form#wiz5-form-services')); 39268 pop.find('form').attr('action', loadUrl); 39269 WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 3, null, data); } 39270 39271 //pop.off('click', 'button.positive'); 39272 //pop.on('click', '#simplemodal-container button.positive', function() { Wiz5.processingCellUpdate(sid, 3); }); 39273 _columnNumber = 3; _staffId = sid; 39274 $('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 39275 39276 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 39277 $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 39278 $('#wiz5-popup-service .shadow2:first').css({ "margin-top": "8px" }); 39279 39280 pop.find('#price1').focus(); 39281 39282 _initNarrowPopup(pop); 39283 _initNonWizardPage(pop); 39284 _initTallPopup(); 39285 }); 39286 39287 pop.modal(); 39288 _openServicesDimensions(pop); 39289 } 39290 39291 _constructor.openUpdateQuickNote = function() { 39292 if (GLO.Info.roleType < 209) { return; } 39293 39294 var jmodal = $('#simplemodal-container'); 39295 var jhead = jmodal.find('#quick-view-header'); 39296 var text = '<textarea>' + $('#quick-view-note-text').text() + '</textarea>'; 39297 39298 var htm = '<div id="pop-staff-quick-note" staff_id="' + jhead.attr('staff_id') + '">
39298' + text + '</div>'; 39299 var header = 'Quick Staff Note for ' + jhead.text(); 39300 39301 GLO.Popup.Custom.openSimple(htm, header, Wiz5.saveQuickNote); 39302 } 39303 _constructor.saveQuickNote = function() { 39304 var jpop = $('#pop-staff-quick-note'); 39305 var staffId = jpop.attr('staff_id'); 39306 jpop = jpop.closest('.glopop'); 39307 39308 var uri = GLO.Link.Object.Provider.Ajax + 'StaffQuickNote?staff=' + staffId; 39309 var note = UTIL.htmlEncode2(jpop.find('textarea').val()); 39310 39311 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 39312 39313 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "note": note } }) 39314 .success(function(data, textStatus, jqXHR) { 39315 GLO.Popup.close(jpop); 39316 GLO.Popup.Success.open('Service Note Changed', 'Update Successful'); 39317 $.modal.close(); 39318 }) 39319 .error(function(jqXHR, textStatus, errorThrown) { }); 39320 } 39321 39322 function _setServicesStaffName(staffName, sid) { 39323 if (UTIL.isEmpty(staffName)) { 39324 staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text(); 39325 } 39326 39327 if (UTIL.isEmpty(staffName)) { 39328 staffName = _processForNonWizardPage(); 39329 } 39330 39331 $('#wiz5-staffName').text(staffName); 39332 39333 if (UTIL.isEmpty(staffName)) { 39334 $('#wiz5-staffName').css({ "background-color": "transparent" }); 39335 } 39336 } 39337 39338 function _initTallPopup() { 39339 if (innerHeight > 800) { 39340 var popupHeight = innerHeight - 100; 39341 $('#simplemodal-container').css({ "top": "40px", "height": popupHeight + "px", "max-height": "inherit" }); 39342 $('#wiz5-form-body').css({ "height": (popupHeight - 90) + 'px' }); 39343 } 39344 } 39345 function _initNarrowPopup(pop) { 39346 if (GLO.Info.isMobile()) { 39347 $('#simplemodal-container').css({ "width": (innerWidth * .98), "height": "", "max-height": "inherit" }); 39348 $('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important"); 39349 $('#wiz5-form-body').css({ "height": "inherit" }); 39350 $('#wiz5-popupButtons').css({ "position": "relative" }); 39351 //} else { 39352 // $('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 39353 } else if (innerWidth < 640) { 39354 pop.find('.hidePhone').addClass('hide'); 39355 } 39356 } 39357 function _initNonWizardPage() { 39358 if (WIZ.page !== undefined || WIZ.isWizard) { return; } 39359 39360 var jmodal = $('#simplemodal-container').css({ "padding": "0" }); 39361 39362 if (jmodal.width() > 800) { 39363 $.modal.update(null, 800); 39364 } 39365 } 39366 39367 function _openServicesDimensions(pop) { 39368 var h = 725; 39369 39370 if (GLO.Info.isMobile()) { 39371 pop.closest('#simplemodal-container').css({ "top": "10px", "padding": "6px" }); 39372 39373 /* 39374 if (GLO.Info.isLandscape()) { 39375 $.modal.update(h, 555); 39376 } else { 39377 $.modal.update(h, 360); //480 39378 } 39379 */ 39380 } 39381 39382 if (innerWidth > 980) { 39383 $.modal.update(h, 960); 39384 } else { 39385 $.modal.update(h, innerWidth - 20); 39386 } 39387 } 39388 39389 _constructor.staffServiceChecked = function(chkBox) { 39390 var tr = $(chkBox).parent().parent(); 39391 39392 if (tr.hasClass('wiz5-more-row')) { return; } 39393 39394 var svcRowNum = tr.attr('id').substring(8); 39395 var prows = tr.parent().find('tr#prow' + svcRowNum); 39396 39397 if ($(chkBox).is(':checked')) { 39398 tr.find('td').css('text-decoration', ''); //tr.css('text-decoration', ''); 39399 tr.css('opacity', ''); 39400 39401 if (prows.eq(2).hasClass('hide')) { 39402 if (!UTIL.isEmpty(prows.eq(0).find('.wiz5-default-time-val').text()) || !UTIL.isEmpty(prows.eq(1).find('.wiz5-default-time-val').text()) 39403 || !UTIL.isEmpty(prows.eq(0).find('input[type="number"]').text()) || !UTIL.isEmpty(prows.eq(1).find('input[type="number"]').text()) 39404 || !UTIL.isEmpty(prows.eq(1).find('.wiz5-max-clients').val())) { 39405 tr.find('.wiz5-more').click(); 39406 //prows.removeClass('hide'); 39407 } 39408 } 39409 } else { 39410 if (!prows.eq(0).hasClass('hide')) { 39411 tr.find('.wiz5-more').click(); 39412 //prows.addClass('hide'); 39413 } 39414 39415 tr.find('td').css('text-decoration', 'line-through'); //tr.css('text-decoration', 'line-through'); 39416 tr.css('opacity', '.5'); 39417 } 39418 } 39419 39420 _constructor.staffServiceCheckedAll = function(me) { 39421 me = $(me); 39422 39423 var isChecked = me.prop('checked');
39424 var cBoxes = me.closest('table').find('input:checkbox.wiz5-svc-enable'); 39425 39426 cBoxes.each(function() { 39427 var jbox = $(this) 39428 39429 if (isChecked && !jbox.prop('checked')) { 39430 jbox.prop('checked', true); 39431 Wiz5.staffServiceChecked(this); 39432 } else if (!isChecked && jbox.prop('checked')) { 39433 jbox.prop('checked', false); 39434 Wiz5.staffServiceChecked(this); 39435 } 39436 }); 39437 } 39438 39439 _constructor.saveStatus = function() { 39440 WIZ.popupSave(); 39441 } 39442 39443 _constructor.markUpdated = function(staffId, columnNumber, caption, data) { 39444 if (staffId === 'new') { 39445 var jtr = $(data).css({ "background-color": "lightpink" }); 39446 var jtbl = $('#wiz5-stafflist tbody').prepend(jtr); 39447 39448 //var rowpos = jtbl.find('tr:first').position(); 39449 //jtbl.scrollTop(rowpos.top); 39450 $('#wiz5-staffparent').scrollTop(0); 39451 } else { 39452 var upd = $('.wiz5-updated-cell:first').clone(); 39453 39454 if (UTIL.isEmpty(caption)) { caption = SA.Resource.Updated.toLowerCase(); } 39455 upd.text(caption); 39456 39457 $('#wiz5-stafflist').find('#trStaff' + staffId + ' td').eq(columnNumber).html(upd); 39458 39459 SA.Parent.processProfileUpdate(staffId, columnNumber); 39460 39461 if (columnNumber === 3) { 39462 var priceDiffCount = $(data).attr('price_diff_count_sr'); 39463 Wiz5.askServicePriceDiff(staffId, priceDiffCount); 39464 } 39465 } 39466 39467 if ($('#staff-profile-report-header').length > 0) { 39468 var tbl = $('#report-main').find('.tablesorter:visible') 39469 var tr = tbl.find('#trStaff' + staffId).find('.report-column-staff > a'); 39470 39471 if (tr.length === 1) { 39472 GLO.Popup.closeIfExist( $('#pop-success-refresh-ask').closest('.glopop') ); 39473 39474 var btnRefresh = '<span class="btnSearch" style="display: block; width: 100px; margin: auto; margin-bottom: 8px;"><a onclick="document.location.reload()">Refresh</a></span>'; 39475 var msg = '<div id="pop-success-refresh-ask" class="friendly-msg4" style="text-align: center; color: #4F81BD;"><p style="text-align: center;">Do you want to refresh the report?</p>' + btnRefresh + '</div>'; 39476 var h1 = tr.text() + ' Saved'; 39477 var jpop = $('#pop-success-wizard').closest('.glopop'); 39478 39479 if (jpop.length) { 39480 var htm = '<div style="margin-top: 12px;">' + msg + '</div>'; 39481 jpop.find('h1').html(h1); 39482 jpop.find('.msg').append(htm); 39483 } else { 39484 var htm = '<div id="pop-success-wizard-refresh">' + msg + '</div>'; 39485 GLO.Popup.Success.open(htm, h1, 9000); 39486 } 39487 39488 UI.highlight( $('#staff-profile-report-header .fa-refresh') ); 39489 } 39490 } 39491 } 39492 39493 _constructor.processingCellUpdate = function() { 39494 if (_staffId === 'new') { 39495 var jAddStaffBtn = $('#wiz5-AddProvider'); 39496 GLO.UI.Form.beginProcessing(jAddStaffBtn); 39497 } else { 39498 var ajax_load = "<img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' style='margin: 0;'/>"; 39499 $('#wiz5-stafflist').find('#trStaff' + _staffId + ' td').eq(_columnNumber).html(ajax_load); 39500 } 39501 } 39502 39503 _constructor.clickMyNotification = function(checkbox1, checkbox2) { 39504 checkbox1 = document.getElementById(checkbox1); 39505 checkbox2 = document.getElementById(checkbox2); 39506 39507 if (checkbox1.checked) { 39508 checkbox1.checked = false; 39509 } else { 39510 checkbox1.checked = true; 39511 } 39512 39513 if (checkbox2.checked) { 39514 checkbox2.checked = false; 39515 } else { 39516 checkbox2.checked = true; 39517 } 39518 } 39519 39520 _constructor.newProfile = function() { 39521 var pop = $('#wiz5-popup-newProfile'); 39522 39523 /* //CHANGE (low priority): 39524 For now I re-load this every time since the mask jquery pluggin throws an error if I re-open the same popup html. 39525 I'm pretty sure that I fixed this on the client portal so I just have to see how I fixed it. 39526 39527 UPDATE (Sep 20xx): I'm actually only loading wiz2 in 1 location on the page as the Wiz2 javascript object doesn't currently support multiple wiz2 objects on the page. 39528 So instead of the "Add Staff Member" button calling this function it calls editProfile('') 39529 */ 39530 39531 var loadUrl = GLO.Link.Object.Provider.WizardPart1 + "?page=5&popup=yes&sid=new&dt=" + UTIL.getDateString(); 39532 39533 pop.load(loadUrl, function() { 39534 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 39535 load_newProfile(); 39536 }); 39537 39538 /* 39539 if (pop.html() == '') { 39540 var loadUrl = GLO.Link.Object.Provider.WizardPart2 + "?page=4&popup=yes&sid=new"; //"/outglo/wizard/popups/4-1.htm"; 39541 pop.load(loadUrl, function() { load_newProfile(); }); 39542 } else { 39543 load_newProfile(pop); 39544 } 39545 */ 39546 } 39547 39548 function load_newProfile(pop) { 39549 /* 39550 if (pop == null) { var pop = $('#wiz5-popup-newProfile'); } 39551 var loadUrl = GLO.Link.Object.Provider.WizardPart2 + "?page=4&popup=yes&sid=new"; 39552 $('#wiz5-popup-newProfile').load(loadUrl); 39553 */ 39554 //if (_constructor.newProfileIsLoaded) { 39555 // pop.modal(); 39556 //} else { 39557 39558 //WIZ.modalAdjustHeight = 0; // = -110; // = 160; 39559 Wiz1.header = SA.Resource.AddStaffMember; 39560 //Wiz2.init(pop); 39561 39562 var jContainer = $('#wiz1-body'); 39563 var copyStaff = $('#staffCheck:checked'); //form#wiz5-form 39564 if (copyStaff.length == 1) { jContainer.find('#Copied_Staff_id').val(copyStaff.parent().parent().attr('id').substr(7)); } 39565 39566 //WIZ.openUserLogin(null, pop, false); 39567 //$.modal.update(450, 550); 39568 39569 _constructor.newProfileIsLoaded = true; 39570 WIZ.Popup.onSave = Wiz5.AddNewStaffRow;
39571 UI.setAccessKey('#wiz1-body', null, WIZ.popupSave); 39572 //} 39573 } 39574 39575 _constructor.AddNewStaffRow = function(dataFromAjax) { 39576 $('#wiz5-stafflist tbody').append(dataFromAjax); 39577 } 39578 39579 _constructor.editProfile = function(staffId, staffName, isOverride) { 39580 if (staffId === 'new' && SA.Parent.canLinkStaff() && !isOverride) { 39581 SA.Parent.openLinkStaffQuestion(); 39582 return; 39583 } 39584 39585 var loadUrl = GLO.Link.Object.Provider.WizardPart1 + "?page=4&popup=yes&sid=" + staffId + "&dt=" + UTIL.getDateString(); 39586 39587 //CHANGE (low priority): I have to unload the empty wiz2 for adding staff because currently the way UTIL.Validate and wizard.js work there can only be 1 popup loaded on the page at one time. 39588 //$('#wiz5-popup-newProfile').html(''); 39589 39590 var cancelLoad = false; 39591 39592 if (!UTIL.isEmpty(staffName)) { 39593 var processingMsg = SA.Resource.LookingUp + " " + staffName + "'s " + SA.Resource.Profile + "..."; 39594 } else { 39595 var processingMsg = ''; 39596 } 39597 39598 var popProcessing = GLO.Popup.Processing(processingMsg, function() { 39599 cancelLoad = true; //jqxhr.abort(); 39600 $.modal.close(); 39601 }); 39602 39603 var ojPopProcessing = popProcessing.getPopup(); 39604 ojPopProcessing.find('.btnOk a').text(SA.Resource.Cancel); 39605 39606 $("#wiz5-popupStaffProfile").load(loadUrl, function() { 39607 if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; } 39608 if (cancelLoad) { return; } 39609 popProcessing.close(); 39610 39611 var jpop = $('#wiz5-popupStaffProfile'); 39612 var isFirstAvailable = _initWiz1FirstAvailable(jpop); 39613 39614 if (staffId == 'new') { 39615 load_newProfile($("#wiz5-popupStaffProfile")); 39616 } else { 39617 _constructor.newProfileIsLoaded = false; 39618 WIZ.modalAdjustHeight = 160; 39619 WIZ.Popup.onSave = null; 39620 39621 if (!isFirstAvailable && SA.Parent.canLinkStaff() && innerWidth > 500) { 39622 var jbtns = $('#wiz1-popupNext').css({ "width": "100%" }); 39623 //jbtns.find('#wiz1-cancel').css({ "float": "none", "margin-left": "8px", "margin-right": "40px" }).find('>a').css({ "letter-spacing": "1px" }); 39624 //jbtns.find('#wiz1-Save').css({ "float": "none", "width": "80px", "margin": "auto", "margin-left": "40px" }).find('>a').css({ "letter-spacing": "1px" }); 39625 39626 if (!UTIL.isEmpty( $('#wiz1-form #Staff_Parent_id').val() )) { 39627 var btnLink = '<span id="btnLinkStaff" class="btnAdd" title="Link Staff with Another Location"> <a onclick="SA.Parent.openLinkStaff()">Staff Linked</a> </span>'; 39628 } else { 39629 var btnLink = '<span id="btnLinkStaff" class="btnAdd btnAction2" title="Link Staff with Another Location"> <a onclick="SA.Parent.openLinkStaff()">Link Staff</a> </span>'; 39630 } 39631 39632 jbtns.find('#wiz1-Save').after(btnLink); 39633 } 39634 } 39635 39636 WIZ.openUserLogin(staffId, $("#wiz5-popupStaffProfile"), false); //$('#wiz1-profilePhoto').addClass('hide'); 39637 39638 jpop.find('#wiz1-body').css({ "margin-top": "" }); 39639 jpop.find('#wiz1-cancel').removeClass('hide'); 39640 jpop.find('label').css({ "margin-bottom": "0" }); 39641 jpop.find(':text').css({ "margin-top": "4px" }); 39642 39643 if (GLO.Info.isMobile()) { 39644 if (innerWidth < 555) { 39645 $.modal.update( ($('#wiz1-body').height() + 120) , innerWidth - 10); 39646 } else { 39647 jpop.find('#wiz1-name').find('td').css({ "text-align": "center" }); 39648 jpop.find('#Email_vc').css({ "width": "420px", "letter-spacing": "1px" }); 39649 jpop.find('#mobile-phone-container2').css({ "display": "inline-block", "margin-left": "12px" }); 39650
39651 var tdUsername = jpop.find('#wiz1-username').find('td').css({ "text-align": "center" }); 39652 tdUsername.find('label').css({ "display": "inline-block", "width": "90px", "margin-right": "4px" }); 39653 tdUsername.find('#Username_vc').css({ "display": "inline-block" }); 39654 39655 jpop.find('#Mobile_Phone_vc, #Username_vc').css({ "letter-spacing": "1px" }); 39656 39657 $.modal.update( ($('#wiz1-body').height() + 50) , 550); 39658 } 39659 } else { 39660 $.modal.update( ($('#wiz1-body').height() + 120) , 550); 39661 } 39662 39663 if ($('#commission-by-staff-service').length > 0) { 39664 WIZ.Popup.onSave = function(data, staffName) { 39665 new GLO.Popup.Processing('<div><h1 class="friendly-msg4">Saving Profile</h1><div class="friendly-msg4">Updating Profile</div></div>'); 39666 setTimeout(function() { location.reload(); }, 3000); 39667 } 39668 } else { 39669 WIZ.Popup.onSave = function(data, staffName) { 39670 Wiz5.markUpdated(staffId, 1, staffName, data); 39671 } 39672 } 39673 39674 _columnNumber = 1; _staffId = staffId; 39675 var isnew = (staffId === 'new'); 39676 39677 var jModal = $('#simplemodal-container').css({ "padding": "0" }); 39678 jModal.prepend('<h1 id="pop-staff-profile-header">Staff Profile</h1>'); 39679 jModal.find('a.modalCloseImg').css({ "top": "4px", "right": "8px" }); 39680 jModal.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" }); 39681 39682 UTIL.Validate.saveButton = '#simplemodal-container .btnSave a'; 39683 jModal.find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved); 39684 39685 if (!WIZ.isWizard) { 39686 jModal.find('#Mobile_Phone_vc').removeClass('required'); 39687 39688 if (WIZ.page == 5 || GLO.Report.portalName == 'Staff Profiles') { 39689 jModal.find('#Last_Name_vc, #Username_vc, #Password_vc, #Password2_vc').removeClass('required'); 39690 } 39691 } 39692 39693 if (!isFirstAvailable) { 39694 _addMerchantOptions(jModal, staffId); 39695 _initStaff(jModal, isnew); 39696 } 39697 39698 jModal.find('#Email_vc').removeClass('required'); //toDo (Q2 20xx): add class 'suggest' --> if anyfields w/ suggest are empty popup a warning message ~ "Are you sure you want to save this without: {field(s)}?" 39699 _addDeleteStaffButton(jpop, staffId, staffName); 39700 Wiz1.init(); 39701 _initStaffColor(jModal); 39702 _initStaffGoldPackage(jModal); 39703 39704 if (!GLO.Info.isMobile()) { 39705 $.modal.update( ($('#wiz1-body').height() + 120) , 550); 39706 WIZ.addScrollBarsToSimpleModal(); 39707 } 39708 39709 setTimeout(function() { 39710 jModal.find('#First_Name_vc').focus(); 39711 }, 50); 39712 }); 39713 } 39714 function _initStaffColor(jmodal) { 39715 if (GLO.Info.isGold()) { 39716 var color = jmodal.find('#Color_Rgb_vc').val(); 39717 var jheader = jmodal.find('#pop-staff-profile-header'); 39718 var headerText = '<b>' + jheader.text() + '</b>'; 39719 39720 if (GLO.Info.roleType > 219) { 39721 var icon = '<span id="color-picker-image" class="sa-sprite" onclick="Wiz5.openStaffColorSelector()" title="click to change color"> </span>'; 39722 } else { 39723 var icon = ''; 39724 } 39725 39726 if (!UTIL.isEmpty(color)) { 39727 jheader.css({ "background-color": "rgb(" + color + ")" }); 39728 } 39729 39730 jheader.html(headerText + icon); 39731 } 39732 } 39733 function _initStaffGoldPackage(jmodal) { 39734 if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) { return; } 39735 39736 var yearRange = GLO.UI.getYearRange(false); 39737 39738 jmodal.find('#wiz1-license, #wiz1-hired').removeClass('hide'); 39739 jmodal.find("#License_Expire_dt").datepicker({ beforeShowDay: _constructor.setDatePickerDays, changeYear: true, yearRange: yearRange }); 39740 jmodal.find("#Hire_dt").datepicker({ beforeShowDay: _constructor.setDatePickerDays }); 39741 39742 if (GLO.Info.roleType < 200) { 39743 jmodal.find("#Hire_dt").prop('disabled', true); 39744 } 39745 } 39746 function _initStaff(jmodal, isnew) { 39747 if (!isnew) { 39748 jmodal.find('#First_Name_vc, #Last_Name_vc').css({ "text-transform": "none" }); 39749 } 39750 39751 jmodal.find('#wiz1-header-help').removeClass('hideX'); 39752 39753 if (GLO.Info.providerPackage === 4 || !GLO.Provider.isPaidAccount(true)) { 39754 var roleName = null, roleType = parseInt(jmodal.find('#Role_Type_cd').val()); 39755 var pop_height = jmodal.height() - 140; 39756 var staffLoginCount = UTIL.coalesceInt(jmodal.find('#wiz1-form > table').attr('login_count_sr'), 0); 39757
39758 jmodal.find('#row-birthday, #wiz1-license, #wiz1-hired').addClass('hide'); 39759 jmodal.find('#mobile-phone-container2').css({ "display": "none" }); 39760 39761 if (roleType > 229) { 39762 roleName = 'Admin'; 39763 } else if (roleType > 209) { 39764 roleName = 'Front Desk'; 39765 } else { 39766 if (isnew) { 39767 roleName = 'Add Staff'; 39768 39769 if (staffLoginCount < 2) { 39770 var minRole = UTIL.coalesceInt(jmodal.find('#wiz1-form').attr('min_role_cd'), 150); 39771 var labelRole = '<label for="Role_Type_cd" style="margin: 0; margin-right: 6px; font-weight: bold; color: #4F81BD;">Role</label>'; 39772 39773 var roleOption1 = '<option value="' + minRole + '" title="Normal staff">Normal</option>'; 39774 var roleOption2 = '<option value="200" title="Full access to all staff calendar; no access to reports">Limited Receptionist</option>'; 39775 var roleOption3 = '<option value="210" title="Access needed to manage business, limited access to sales and payment reports; cannot change advanced settings">Receptionist</option>'; 39776 39777 var ddCSS = 'width: 160px; padding-right: 0; letter-spacing: 1px; font-weight: bold; font-size: 16px; border-color: #4F81BD; color: #4F81BD;'; 39778 var ddRole = '<select name="Role_Type_cd" id="Role_Type_cd" onchange="Wiz1.changeNormalStaffRole(this)" style="' + ddCSS + '">' + roleOption1 + roleOption2 + roleOption3 + '</select>'; 39779 39780 var helpIcon = '<span class="helpIcon2 sa-sprite" onclick="SA.Help.Profile.openStaffRole(this)" style="margin-top: 1p
39780x;"></span>'; 39781 var htmRole = '<div style="position: relative; max-width: 240px; margin: auto; margin-top: 16px; margin-bottom: 8px;"> ' + labelRole + ddRole + helpIcon + '</div>'; 39782 jmodal.find('#wiz1-form').append(htmRole); 39783 jmodal.find('#wiz1-username').find('td').css({ "padding-bottom": "2px" }); 39784 39785 var jpass = jmodal.find('#wiz1-password'); 39786 jmodal.find('#wiz1-username').addClass('hide').prop('password_htm', jpass.outerHTML()); 39787 jpass.remove(); 39788 } 39789 } else if (staffLoginCount < 2) { 39790 roleName = 'Front Desk'; 39791 } 39792 39793 if (staffLoginCount > 1 && jmodal.find('#wiz1-username, #wiz1-password').length > 1) { 39794 jmodal.find('#wiz1-username, #wiz1-password').remove(); 39795 pop_height -= 100; 39796 } 39797 } 39798 39799 if (roleName !== null) { 39800 jmodal.find('h1').text(roleName); 39801 //jmodal.prepend('<h2 style="letter-spacing: 2px; border-radius: 0; border-top-left-radius: 4px; color: white;">' + roleName + '</h2>'); 39802 //pop_height += 30; 39803 //$('body.phone #simplemodal-container a.modalCloseImg').css({ "top": "4px" }); 39804 } 39805 39806 //$.modal.update(pop_height, null); //commented out because causes issue on phone (silver package) 39807 } 39808 } 39809 39810 function _addDeleteStaffButton(jpop, staffid, staffName) { 39811 if (GLO.Info.providerPackage == 1 || _constructor.roleType < 210 || GLO.Data.Staff.require_password_appointment_edit_fl || staffid === 'new') { return; } 39812 39813 var btn = '<a onclick="Wiz5.deleteStaffAsk(' + staffid + ', \'' + UTIL.replaceQuotesTitle(staffName) + '\')">Delete</a>'; 39814 var btnHtm = '<span class="btnDelete">' + btn + '</span>'; 39815 39816 var jbtns = jpop.find('#wiz1-popupNext').append(btnHtm); 39817 //jbtns.find('.btnCancel').css({ "margin-left": "2%" }).find('>a').css({ "letter-spacing": "2px", "font-size": "16px" }); 39818 //jbtns.find('.btnSave').css({ "width": "80px", "margin-right": "2%" }).find('>a').css({ "letter-spacing": "2px", "font-size": "16px" }); 39819 } 39820 39821 function _initWiz1FirstAvailable(jpop) { 39822 if (!UTIL.parseBool(jpop.find('#Is_First_Available_fl').val())) { return false; } 39823 39824 jpop.prepend('<h2 style="letter-spacing: 2px; border-radius: 0; border-top-left-radius: 4px; color: white;">First Available</h2>'); 39825 jpop.find('#Female_fl, #Middle_Initial_c, #row-otherPhone, #wiz1-username, #wiz1-password, #row-birthday, #wiz1-license, #wiz1-hired, #use-house-merchant-row').remove(); 39826 jpop.find('#wiz1-form table').css({ "margin-top": "0" }); 39827 jpop.find('#wiz1-body .widegap tr td').css({ "text-align": "center" }); 39828 jpop.find('input').css({ "letter-spacing": "1px" }); 39829 39830 return true; 39831 } 39832 39833 function _addStaffMerchantLabel(jmodal) { 39834 var checkbox = '<img class="check-mark" src="' + GLO.Data.cdnDirectory + 'image/icon/32px-Black-check.svg.png" style="height: 20px; margin-bottom: 6px; margin-right: 6px;">'; 39835 var snm = UTIL.htmlEncode2(jmodal.find('#First_Name_vc').val()); 39836 var htm = '<div id="use-house-merchant-row">' + checkbox + ' <label for="Use_House_Merchant_fl">' + snm + ' ' + SA.Resource.HasMerchantAccount + '</label> </div>'; 39837 39838 jmodal.css({ "max-height": "700px" }); 39839 jmodal.find('#wiz1-popupNext').before(htm); 39840 jmodal.height(jmodal.height() + 80); 39841 } 39842 39843 function _addMerchantOptions(jmodal, staffId) { 39844 var mtype = UTIL.coalesceInt(jmodal.find('#Merchant_Type_cd').val(), 0); 39845 39846 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 19) { return; } 39847 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) < 10) { return; } 39848 if (UTIL.coalesceInt(mtype, 0) > 49) { _addStaffMerchantLabel(jmodal); return; } 39849 39850 if (GLO.Info.roleType < 220) { 39851 if (mtype > 0 && mtype < 20) { 39852 var checkbox = '<img class="check-mark" src="' + GLO.Data.cdnDirectory + 'image/icon/32px-Black-check.svg.png" style="height: 20px; margin-bottom: 6px; margin-right: 6px;">'; 39853 } else if (GLO.Info.roleType > 209) { 39854 var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl"/>'; 39855 } else { 39856 return; 39857 } 39858 } else { 39859 if (mtype > 0 && mtype < 20) { 39860 var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl" checked="checked"/>'; 39861 } else { 39862 var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl"/>'; 39863 } 39864 } 39865 39866 var snm = UTIL.htmlEncode2(jmodal.find('#First_Name_vc').val() + ' ' + jmodal.find('#Last_Name_vc').val()); 39867 var helpHtm = '<div> <h1 style=\'letter-spacing: 1px;\'>
39867' + snm + ' ' + SA.Resource.CreditCardMerchantAccount + '</h1>' 39868 + '<div style=\'margin-left: 4px; margin-bottom: 16px; line-height: 200%; letter-spacing: 1px; text-align: left;\'>' 39869 + SA.Resource.ReceptionistsCanAddSomeoneToHouseAcct + ' <small>(' + SA.Resource.by_checking_this_box + ')</small><br/>' 39870 + SA.Resource.ManagerRequiredHouseAcct + ' <small>(' + SA.Resource.by_unchecking_box + ')</small><br/>' 39871 + SA.Resource.SetupMerchantAcct + ' <a href=\'https://www.scheduleanyone.com/hello/contact\' style=\'font-weight: bold;\'>' + SA.Resource.ContactUs.toLowerCase() + '</a> </div> </div>'; 39872 39873 var htmAddMerchant = _addNewMerchantButton(staffId, mtype); 39874 var help = '<span class="helpIcon2 sa-sprite" onclick="GLO.UI.openHelp(this)" alt_html="' + helpHtm + '" style="margin-left: 24px;">'; 39875 var htm = '<div id="use-house-merchant-row"> <div>' + checkbox + '<label for="Use_House_Merchant_fl">' + SA.Resource.UseHouseMerchantAccount + '</label>' + help + '</div>' + htmAddMerchant + '</div>'; 39876 39877 var popHeight = jmodal.height() + 90; 39878 if (!UTIL.isEmpty(htmAddMerchant)) { popHeight += 50; } 39879 39880 jmodal.css({ "max-height": "700px" }).find('#wiz1-popupNext').before(htm); 39881 jmodal.height(popHeight); 39882 } 39883 39884 function _addNewMerchantButton(staffId, mtype) { 39885 if (mtype > 49 || UTIL.isEmpty(staffId) || staffId == 'new') { 39886 return ''; 39887 } else if (GLO.Info.roleType > 209) { // || (GLO.Info.roleType > 159 && GLO.Info.StaffId == staffId) 39888 return '<div id="btnAddMerchant"> <span class="btnAdd btnAction1"><a onclick="Wiz5.addNewMerchantAccount()">' + SA.Resource.AddMerchantAccount + '</a></span> </div>'; 39889 } else { 39890 return ''; 39891 } 39892 } 39893 39894 _constructor.requestNewMerchant = function() { 39895 var jpop = $('#pop-staff-add-merchant').closest('.glopop'); 39896 var sname = jpop.find('h1').text().replace(': ' + SA.Resource.AddMerchantAccount + '', ''); 39897 var sid = jpop.find('#pop-staff-merchant-info').attr('staff_id'); 39898 39899 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 39900 var url = GLO.Link.Object.Provider.Ajax + "RequestMerchantAccount?staff_id=sid"; 39901 39902 $.ajax({ type: "POST", url: url, "cache": false, data: { "staff_id": sid } }) 39903 .success(function(data, textStatus, jqXHR) { 39904 GLO.UI.Form.resetProcessing(); 39905 39906 if (!UTIL.isEmpty(data)) { 39907 var jdata = $(data); 39908 39909 if (jdata.attr('error_fl') == '1') { 39910 new GLO.Popup.Error(jdata.attr('error_vc')); 39911 return; 39912 } 39913 } 39914 39915 GLO.Popup.close(jpop); 39916 $.modal.close(); 39917 39918 var cssStyle = 'style="margin-bottom: 12px; letter-spacing: 1px; line-height: 200%;"'; 39919 var htm = $('<div ' + cssStyle + '> ' + SA.Resource.WeWillContact + ' ' + sname + ' ' + SA.Resource.ToSetupMerchantAccount + '.<br/>' + SA.Resource.CallForQuestions + '</div>'); 39920 new GLO.Popup.Info(htm); 39921 }) 39922 .error(function(jqXHR, textStatus, errorThrown) { 39923 GLO.Popup.Error('Unable to clock in at this time. Please try again later.'); 39924 GLO.UI.Form.resetProcessing(); 39925 }); 39926 } 39927 39928 _constructor.saveNewMerchant = function() { 39929 var jpop = $('#pop-staff-add-merchant').closest('.glopop'); 39930 var sid = jpop.find('#pop-staff-merchant-info').attr('staff_id'); 39931 var tab = jpop.find('.tab-body:visible'); 39932 39933 if (tab.attr('id') == 'tab-body-add-cayan') { 39934 var mname = jpop.find('#new-merchant-name').val(); 39935 var mkey = jpop.find('#new-merchant-key').val(); 39936 var msite = jpop.find('#new-merchant-site').val(); 39937 39938 if (mname.length < 5) { 39939 new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantName, function() { $('#pop-staff-add-merchant').find('#new-merchant-name').focus(); }); 39940 return; 39941 } else if (mkey.length < 5) { 39942 new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantKey, function() { $('#pop-staff-add-merchant').find('#new-merchant-key').focus(); }); 39943 return; 39944 } else if (msite.length < 5) { 39945 new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantSiteId, function() { $('#pop-staff-add-merchant').find('#new-merchant-site').focus(); }); 39946 return; 39947 } 39948 39949 var jd = { "staff_id": sid, "merchant_name_vc": mname, "merchant_key_vc": mkey, "merchant_site_vc": msite }; 39950 } else { 39951 var mid = jpop.find('#new-merchant-id').val(); 39952 var user = jpop.find('#new-merchant-username').val(); 39953 var pass = jpop.find('#new-merchant-password').val(); 39954 39955 if (mid.length < 8) { 39956 GLO.Popup.Warning.open('Please Enter Merchant Id', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-id').focus(); }); 39957 return; 39958 } else if (user.length < 5) { 39959 GLO.Popup.Warning.open('Please Enter Merchant Username', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-username').focus(); }); 39960 return; 39961 } else if (user.length < 5) { 39962 GLO.Popup.Warning.open('Please Enter Merchant Password', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-password').focus(); }); 39963 return; 39964 } 39965 39966 var jd = { "staff_id": sid, "merchant_id_vc": mid, "user_id_vc": user, "password_vc": pass }; 39967 } 39968 39969 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 39970 var url = GLO.Link.Object.Provider.Ajax + "SaveMerchantAccount"; 39971
39972 $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 39973 .success(function(data, textStatus, jqXHR) { 39974 GLO.UI.Form.resetProcessing(); 39975 39976 if (!UTIL.isEmpty(data)) { 39977 var jdata = $(data); 39978 39979 if (jdata.attr('error_fl') == '1') { 39980 GLO.Popup.Error.open(jdata.attr('error_vc'), 'Add Merchant Error'); 39981 return; 39982 } 39983 } 39984 39985 GLO.Popup.close(jpop); 39986 GLO.Popup.Success.open(SA.Resource.MerchantAccountAdded, 'Merchant Insert Successful'); 39987 $.modal.close(); 39988 39989 if (WIZ.page === 5) { 39990 setTimeout(function() { $('#wiz5-stafflist').find('tr#trStaff' + sid).find('.wiz5-column-name').click() }, 900); 39991 } 39992 }) 39993 .error(function(jqXHR, textStatus, errorThrown) { 39994 GLO.Popup.Error.open('<div id="pop-error-add-merchant"><p>Unable to add merchant at this time</p><p>Please try again later</p></div>', 'Add Merchant Error'); 39995 GLO.UI.Form.resetProcessing(); 39996 }); 39997 } 39998 39999 _constructor.backToProfile = function() { 40000 GLO.Popup.close($('#pop-staff-add-merchant').closest('.glopop')); 40001 40002 $('#wiz1-body').closest('#simplemodal-container').removeClass('hide'); 40003 } 40004 40005 _constructor.addNewMerchantAccount = function() { 40006 var jfrm = $('#wiz1-body'); 40007 var sid = jfrm.find('#Staff_id').val(); 40008 var snm = jfrm.find('#First_Name_vc').val() + ' ' + jfrm.find('#Last_Name_vc').val(); 40009 40010 //jfrm.closest('#simplemodal-container').addClass('hide'); 40011 40012 var jpop = _getNewMerchantPop(sid, snm); 40013 jpop = new GLO.Popup.Custom(jpop, Wiz5.saveNewMerchant).getPopup().addClass('no-persist'); 40014 40015 jpop.find('.tab-control').find('li.active-tab > a').click(); 40016 40017 var jbtns = jpop.find('.pop-buttons').css({ "max-width": "400px" }); 40018 jbtns.find('.btnCancel>a').text('Back').click(Wiz5.backToProfile).css({ "letter-spacing": "1px" }); 40019 jbtns.find('.btnSave').css({ "position": "absolute", "right": "4px", "margin": "0", "letter-spacing": "1px" }); 40020 40021 if (innerWidth > 600) { 40022 jpop.find('#pop-staff-add-merchant').addClass('pop-this-wide'); 40023 } else if (innerWidth > 600) { 40024 jpop.find('#pop-staff-add-merchant').addClass('pop-this-narrow'); 40025 } 40026 } 40027 40028 function _getNewMerchantPop(sid, snm) { 40029 var houseMerchant = UserPortal.Price.Payment.getMerchantByPayTo('h'); 40030 var isIncludeCayan = UTIL.parseBool(GLO.Data.provider.mixed_vendor_merchant_fl || houseMerchant.co != 30); 40031 40032 /* if (innerWidth < 350) { 40033 var legend = SA.Resource.MerchantDetails; 40034 } else { //if (innerWidth < 400) { 40035 var legend = SA.Resource.YourMerchantDetails; 40036 //} else { 40037 // var legend = SA.Resource.YourMerchantDetailsFrom; 40038 } */ 40039 40040 if (isIncludeCayan) { 40041 var tab1 = '<li id="tab-add-clover-connect" class="active-tab"><a onclick="Wiz5.displayStatusTab(this, \'tab-body-add-clover-connect\')">Clover Connect</a></li>'; 40042 var tab2 = '<li id="tab-add-cayan"><a onclick="Wiz5.displayStatusTab(this, \'tab-body-add-cayan\')">Cayan</a></li>'; 40043 var tabs = '<div id="tabs-add-merchant" class="tab-control"><ul>' + tab1 + tab2 + '</ul></div>'; 40044 40045 var tabBody1 = _getCloverMerchantHtm(); 40046 var tabBody2 = _getCayanMerchantHtm(); 40047 var htmBody = tabs + tabBody1 + tabBody2; 40048 } else { 40049 var htmBody = _getCloverMerchantHtm(); 40050 } 40051 40052 var h1 = '<h1 style="letter-spacing: 1px;">' + snm + ': ' + SA.Resource.AddMerchantAccount + '</h1>'; 40053 var btnContact = '<span class="btnAdd btnAction2"><a onclick="Wiz5.requestNewMerchant()" style="0 4px">' + SA.Resource.RequestNewMerchantAccount + '</a></span>'; 40054 40055 var htm = '<div id="pop-staff-add-merchant">' + h1 + '<p>' + SA.Resource.IfNoMerchantAccount + btnContact + '</p>'; 40056 htm += '<div id="pop-staff-merchant-info" staff_id="' + sid + '"><div>'; //<h4>' + legend + '</h4> 40057 htm += htmBody + '</div>'; 40058 40059 return $(htm); 40060 } 40061 function _getCloverMerchantHtm() { 40062 var imgFiserv = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/merchant/fiserv-secure-message-merchant-credentials.png"/>'; 40063 var tabBody1 = '<div id="tab-body-add-clover-connect" class="tab-body">'; 40064 tabBody1 += '<p style="line-height: 1.4;">The Clover Connect merchant credentials come in an email from Fiserv with the <span class="narrow-text">email subject</span> <b>Production Credentials for...</b></p>'; 40065 tabBody1 += '<p style="text-align: center;">' + imgFiserv + '</p>'; 40066 40067 tabBody1 += '<p> <label for="new-merchant-id">' + SA.Resource.Merchant + ' Id' + '</label> <input type="text" id="new-merchant-id" maxlength="100"/> </p>'; 40068 tabBody1 += '<p> <label for="new-merchant-username">' + SA.Resource.Username + '</label> <input type="text" id="new-merchant-username" maxlength="100"/> </p>'; 40069 tabBody1 += '<p> <label for="new-merchant-password">' + SA.Resource.Password + '</label> <input type="text" id="new-merchant-password" maxlength="100"/> </p>'; 40070 tabBody1 += '</div>'; 40071 40072 return tabBody1; 40073 } 40074 function _getCayanMerchantHtm() { 40075 var tabBody2 = '<div id="tab-body-add-cayan" class="tab-body">'; 40076 tabBody2 += '<p style="line-height: 1.4;">You will receive your Cayan/TSYS merchant credentials in an email</p>'; 40077 40078 tabBody2 += '<p> <label for="new-merchant-name">' + SA.Resource.MerchantName + '</label> <input type="text" id="new-merchant-name" maxlength="100" style="width: 16em;"/> </p>'; 40079 tabBody2 += '<p> <label for="new-merchant-key">' + SA.Resource.MerchantKey + '</label> <input type="text" id="new-merchant-key" maxlength="100" style="width: 18em;"/> </p>'; 40080 tabBody2 += '<p> <label for="new-merchant-site">' + SA.Resource.MerchantSiteID + '</label> <input type="text" id="new-merchant-site" maxlength="100" style="width: 8em;"/> </p>'; 40081 tabBody2 += '</div>'; 40082 return tabBody2; 40083 } 40084 40085 function initServicesPopup() { 40086 //UI.init_Tooltip(".shadow-content2 h4 label, .shadow-content2 table tr td label", WIZ.toolTip_OnHover); //note: I don't think the tooltip is good to use on this page. 40087 /* 40088 $(".shadow-content2 > h4 > input").click(function() { 40089 if (this.checked) { 40090 $(this).parent().parent().find("table input:checkbox").each(function() { 40091 this.checked = true; 40092 }) 40093 } else { 40094 $(this).parent().parent().find("table input:checkbox").each(function() { 40095 this.checked = false; 40096 }) 40097 } 40098 }); 40099 */ 40100 40101 var j = $('#wiz5-form-body'); 40102 40103 var tabIndex = 1; 40104 j.find('.shadow-content2 input:text').each(function() { $(this).attr('tabindex', tabIndex++); }); 40105 //$('.shadow-content2 input:text').attr('tabindex', '0'); 40106 40107 j.find('.wiz5-more-row input[type="number"], .wiz5-svc-time').on('keyup', Wiz5.changeTimeLength); 40108 j.find('.wiz5-more-block-out-td :checkbox').on('change', Wiz5.changeBlockOut); 40109 } 40110 40111 _constructor.setClientAccess = function(event) { 40112 var jpop = $('#wiz5-popupStatus'); 40113 40114 if (jpop.length === 1) { 40115 var jClient_Access_cd = jpop.find('#wizcc-who-can-book-options input[type=radio]:checked'); 40116 } else { 40117 var jClient_Access_cd = $('#online-booking-access input[type=radio]:checked'); 40118 } 40119 40120 var clientAccess = jClient_Access_cd.val(); 40121 40122 if (clientAccess == 2 && !GLO.Provider.isPaidAccount(true)) { 40123 jClient_Access_cd = jpop.find('#Client_Access_cd1').prop('checked', true); 40124 40125 var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ExistingClientsRequiresUpgrade + '</h1>'; 40126 var msg1 = '<p>' + SA.Resource.MustUpgradeToAllowExisting + '</p>'; 40127 var msg2 = '<p class="info-link"> <a href="/help/existing-clients-only">' + SA.Resource.LearnHowExistingClientsWork + '</a> </p>'; 40128 var msg = '<div>' + h1 + '<div class="friendly-msg">' + msg1 + msg2 + '</div> </div>'; 40129 new GLO.Popup.Info(msg); 40130 } else if (GLO.Info.providerPackage != 4) { 40131 var popConfirm = jpop.find('#wiz5-cc-confirm-input-container'); 40132 var jcheckboxes = popConfirm.find(':checkbox').change(Wiz5.changeConfirmAppt); 40133 40134 if (event) { //= is click 40135 var subAccess = jpop.find('#Client_Sub_Access_cd').val(); 40136 _displayClientSubAccess(clientAccess, subAccess); 40137 } else if (clientAccess == 2 || clientAccess == 4) { //= is load. 40138 _setClientSubAccess(jpop, clientAccess, false); 40139 } 40140 } 40141 40142 var clientAccess_color = jClient_Access_cd.parent().find('label').css('color'); 40143 jpop.find('#online-booking-access legend').css('color', clientAccess_color); 40144 } 40145 40146 function _displayClientSubAccess(clientAccess, subAccess) { 40147 var isbiz = (GLO.Info.providerPackage !== 1); 40148 var jmodal = $('#simplemodal-container #wiz5-popupStatus'); 40149 var allowsOnlineBooking = UTIL.parseBool(jmodal.find('#Online_Booking_fl').val()); 40150 var allowsRequestAppt = UTIL.parseBool(jmodal.find('#Request_Appointment_fl').val()); 40151 var isForbid = (clientAccess == 3), isRequestOnly = (clientAccess == 4); 40152 40153 if (clientAccess == 2) { 40154 subAccess = UTIL.coalesceInt(subAccess, 220);
40155 var msg0 = '', popCSS = 'existing-client', h1 = 'Define Existing Client', header = 'Who do you consider an <b>Existing</b> client?'; 40156 } else if (isbiz && allowsRequestAppt && ( (allowsOnlineBooking && isForbid) || isRequestOnly) ) { 40157 subAccess = UTIL.coalesceInt(subAccess, 0); 40158 40159 var popCSS = 'request-appt', h1 = 'When Display Staff on Request Appointment Screen', header = 'When should this staff show as option when clients request appointments?'; 40160 var subAccessForAll = 0; 40161 40162 if (clientAccess == 3) { subAccessForAll = 10; } 40163 40164 var msg0 = _getClientSubAccessTextHtm(subAccessForAll, 'All Clients', 'Allows anyone to request an appointment', 'color: rgb(0,200,40);'); 40165 } else { 40166 return false; 40167 } 40168 40169 var msg1 = _getClientSubAccessText(clientAccess, 210, isbiz, true); 40170 var msg2 = _getClientSubAccessText(clientAccess, 220, isbiz, true); 40171 40172 if (isbiz) { 40173 var msg3 = _getClientSubAccessText(clientAccess, 230, isbiz, true); 40174 } else { 40175 var msg3 = ''; 40176 } 40177 40178 if (clientAccess == 3) { 40179 var msg4 = _getClientSubAccessText(clientAccess, 400, isbiz, true); 40180 } else { 40181 var msg4 = ''; 40182 } 40183 40184 var htm = '<div id="pop-client-sub-access" class="' + popCSS + '"> <h6>' + header + '</h6> <ul>' + msg0 + msg1 + msg2 + msg3 + msg4 + '</ul> </div>'; 40185 var jpop = GLO.Popup.Custom.openSimple(htm, h1, Wiz5.setClientSubAccess); 40186 jpop.find('.btnSave').remove(); 40187 40188 var cssCancel = { "position": "relative", "left": "inherit", "float": "none", "display": "block", "padding": "0", "letter-spacing": "2px", "width": "80px", "margin": "auto" }; 40189 jpop.find('.btnCancel').css(cssCancel).find('>a').text('Close'); 40190 40191 jpop.find('#Client_Sub_Access_cd' + subAccess).prop('checked', true); 40192 jpop.find('li').click(Wiz5.setClientSubAccess); 40193 } 40194 40195 _constructor.setClientSubAccess = function(event) { 40196 var jPopSubAccess = $('#pop-client-sub-access').closest('.glopop'); 40197 var jcurrentSub = jPopSubAccess.find(':radio[name="Client_Sub_Access_cd"]:checked'); 40198 var jrad = $(this).find(':radio[name="Client_Sub_Access_cd"]'); 40199 40200 if (jrad.length === 0) { 40201 jrad = jcurrentSub; 40202 } 40203 40204 var currentSubValue = jcurrentSub.val(); 40205 var newSubValue = jrad.val(); 40206 var text = jrad.closest('li').find('.sub-access-text').text(); 40207 var jPopAccess = $('#wiz5-popupStatus').closest('#simplemodal-container'); 40208 40209 jPopAccess.find('#wizcc-who-can-book-options').find(':radio[name="Client_Access_cd"]:checked').closest('tr').find('.quiet9').html(text); 40210 jPopAccess.find('#Client_Sub_Access_cd').val(newSubValue); 40211 40212 if (currentSubValue != newSubValue) { 40213 jPopAccess.find('.btnSave > a').css({ "border": "3px solid red" }); 40214 } 40215 40216 GLO.Popup.close(jPopSubAccess); 40217 } 40218 40219 function _setClientSubAccess(jpop, clientAccess, isForceReset) { 40220 var subAccess = UTIL.coalesceInt(jpop.find('#Client_Sub_Access_cd').val(), 0); 40221 var isbiz = (GLO.Info.providerPackage !== 1); 40222 40223 var jtext2 = jpop.find('#Client_Access_cd2').closest('tr').find('label span'); 40224 var jtext4 = jpop.find('#Client_Access_cd4').closest('tr').find('label span'); 40225 40226 if (!isForceReset && subAccess === 0) { return; } 40227 40228 var text2 = _getClientSubAccessText(2, subAccess, isbiz); 40229 var text4 = _getClientSubAccessText(4, subAccess, isbiz); 40230 40231 jtext2.html(text2); 40232 40233 if (clientAccess == 4) { 40234 jtext4.html(text4); 40235 } 40236 } 40237 40238 function _getClientSubAccessText(clientAccess, subAccess, isbiz, includeHtm) { 40239 if (subAccess === 210) { 40240 var title = 'Existing Account'; 40241 var css = 'color: rgb(255,170,0);'; 40242 40243 if (isbiz) { 40244 if (clientAccess == 2) { 40245 var text = 'Clients with existing account (created by your staff) can book online'; 40246 } else { 40247 var text = 'Clients with existing account (created by your staff) can request staff'; 40248 } 40249 } else { 40250 if (clientAccess == 2) { 40251 var text = 'Clients with existing account (created by me) can book online'; 40252 } else { 40253 var text = 'Clients with existing account (created by me) can request appointment'; 40254 } 40255 } 40256 } else if (subAccess === 230) { 40257 if (isbiz) { 40258 var title = 'Past Appointment with ' + UTIL.maxString(UserPortal.getStaffName($('#wiz5-popupStatus').find('#Staff_id').val()), 10, true); 40259 var css = 'color: rgb(255,120,0);'; 40260 40261 if (clientAccess == 2) { 40262 var text = 'Clients with a past appointment (with this staff) can book online'; 40263 } else { 40264 var text = 'Clients with a past appointment (with this staff) can request staff'; 40265 } 40266 40267 if (GLO.Info.roleType < 210) { 40268 text = text.replace('this staff', 'me'); 40269 } 40270 } else { 40271 return ''; //= is biz only setting 40272 } 40273 } else if (subAccess === 400 && clientAccess == 3) { 40274 if (isbiz) { 40275 var title = 'Forbid Request Appointment'; 40276 var text = 'Clients cannot request appointment with '; 40277 var css = 'color: rgb(255,20,0);'; 40278 40279 if (GLO.Info.roleType < 210) { 40280 text += 'me'; 40281 } else { 40282 text += UTIL.maxString(UserPortal.getStaffName($('#wiz5-popupStatus').find('#Staff_id').val()), 10, true); 40283 } 40284 } else { 40285 return ''; //= is biz only setting 40286 } 40287 } else { //subAccess === 220 || use-default 40288 var css = 'color: rgb(255,140,0);'; 40289 40290 if (isbiz) { 40291 var title = 'Past Appointment at ' + GLO.Data.provider.name; 40292 40293 if (clientAccess == 2) { 40294 var text = 'Clients with a past appointment (with any staff) can book online'; 40295 } else { 40296 var text = 'Cannot book online, but show up in Request Appointment staff drop down'; 40297 } 40298 } else { 40299 var title = 'Past Appointment'; 40300 40301 if (clientAccess == 2) { 40302 var text = 'Clients with a past appointment can book online'; 40303 } else { 40304 var text = 'Clients request appointment which you must approve'; 40305 } 40306 } 40307 } 40308 40309 if (includeHtm) { 40310 return _getClientSubAccessTextHtm(subAccess, title, text, css); 40311 } else { 40312 return text; 40313 } 40314 } 40315 40316 function _getClientSubAccessTextHtm(subAccess, title, text, css) { 40317 var id = 'Client_Sub_Access_cd' + subAccess; 40318 var label1 = '<label class="sub-access-title" for="' + id + '">' + title + '</label>'; 40319 var rdo = '<input type="radio" id="' + id + '" name="Client_Sub_Access_cd" value="' + subAccess + '"/>'; 40320 40321 return '<li style="' + css + '">' + rdo + label1 + '<label class="sub-access-text" for="' + id + '">
40321' + text + '</label></li>'; 40322 } 40323 40324 _constructor.changeConfirmAppt = function() { 40325 var pop = $('#wiz5-popupStatus'); 40326 var jClient_Access_cd = $('#online-booking-access input[type=radio]:checked').val(); 40327 40328 /* this is now allowed 40329 if (jClient_Access_cd == 3) { 40330 Wiz5.infoWhyConfirmationsDisabled(); 40331 this.checked = false; 40332 pop.find('label[for="' + this.id + '"]').css({ "text-decoration": "line-through" }); 40333 } 40334 */ 40335 } 40336 40337 _constructor.infoWhyConfirmationsDisabled = function() { 40338 if ( $('#pop-confirmation-disabled').length > 0) { return; } 40339 40340 40341 var msg = '<div id="pop-confirmation-disabled" style="margin: 10px; margin-top: 0; line-height: 200%; letter-spacing: 1px;">' + SA.Resource.WhenOnlineBookingIsForbidden + '<br/>' + SA.Resource.AutomaticConfirmationEmailsDisabled + '</div>'; 40342 new GLO.Popup.Info(msg); 40343 } 40344 40345 _constructor.openStaffQuickView = function(sid, event, isDisplayEditButton) { 40346 if (event) { 40347 if (event.altKey) { 40348 Wiz5.openServicesOffered(sid); 40349 return; 40350 } 40351 } 40352 40353 var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"}); 40354 var loadUrl = GLO.Link.WebsiteDomain + 'fragment/staff/quickview' + '?sid=' + sid + '&dt=' + UTIL.getDateString(); 40355 var pop = $('#pop-temp'); 40356 40357 if (isDisplayEditButton) { loadUrl += '&allowedit=1'; } 40358 40359 pop.html(throbber).load(loadUrl, function() { 40360 if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; } 40361 pop.find(".tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy }); 40362 40363 var svcRows = pop.find('#quick-view table.tablesorter tbody tr').length; 40364 var width = null, height = null; 40365 var jmodal = pop.closest('#simplemodal-container').css({ "padding": "0" }); 40366 jmodal.find('.simplemodal-data').css({ "padding": "0" }); 40367 40368 if (GLO.Info.isMobile()) { 40369 $('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important"); 40370 $('#simplemodal-container, #quick-view').css({ "height": "", "max-height": "inherit" }); 40371 $('#quick-view-buttons').css({ "position": "relative", "margin-top": "25px", "margin-bottom": "15px" }); 40372 40373 var btn = '<span class="btnAdd"> <a onclick="Wiz5.openServicesOffered(' + sid + ')" title="' + SA.Resource.AddClientToWaitingList + '">' + SA.Resource.Edit + '</a> </span>'; 40374 $('#quick-view-header-table tbody').append('<tr> <td colspan="2" style="padding-bottom: 10px;">' + btn + '</td> </tr>'); 40375 40376 GLO.Popup.resizeMobile(jmodal); 40377 if (svcRows > 6) { height = 200 + svcRows * 25; } 40378 } else { 40379 jmodal.css({ "max-height": "800px" }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 40380 40381 if (innerWidth < 720) { 40382 width = innerWidth - 20; 40383 } else if (innerWidth > 970) { 40384 width = 900; 40385 } else { 40386 width = 700; 40387 } 40388 40389 if (svcRows > 6) { height = 200 + svcRows * 25; } 40390 if (height > $(window).height()) { height = $(window).height() - 50; } 40391 } 40392 40393 if (height > $('#simplemodal-container').outerHeight()) { 40394 if ($('#quick-view').height() > height - 100) { 40395 $('#quick-view').height(height - 130); 40396 } 40397 40398 $.modal.update(height, width); 40399 } 40400 }); 40401 40402 if (innerWidth < 650) { 40403 var modalWidth = innerWidth; 40404 } else { 40405 var modalWidth = 650; 40406 } 40407 40408 pop.modal(); 40409 $.modal.update(400, modalWidth); 40410 } 40411 40412 _constructor.openStaffQuickViewAll = function() { 40413 document.location = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll?fullpage=1'; 40414 40415 //var throbber = $('.loadingDiv').clone().find('img').css({ "width": "150px", "height": "150px", "margin": "auto" }); 40416 //$('#pop-temp').html(throbber).modal(); 40417 } 40418 40419// _constructor.openStaffQuickViewAll_Popup = function() { 40420// var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"}); 40421// var loadUrl = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll'; 40422// var pop = $('#pop-temp'); 40423 40424// pop.html(throbber).load(loadUrl, function() { 40425// pop.find(".tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy }); 40426// pop.find('#quick-view th').css({ "padding-top": "20px" }); 40427// 40428// if (!GLO.Info.isMobile(false)) { $('#simplemodal-container').draggable({ "handle": "h2" }); } 40429// $.modal.update(800, 900); 40430// }); 40431// 40432// pop.modal(); 40433// $.modal.update(400, 600); 40434// } 40435
40436 _constructor.toggleProcessRows = function(btn) { 40437 btn = $(btn); 40438 var tr = btn.parent().parent(); 40439 40440 if (parseInt(tr.css('opacity')) < 1) { return; } 40441 40442 var svcRow = tr.attr('id').substr(8); 40443 tr.parent().find('tr#prow' + svcRow).toggleClass('hide'); 40444 40445 btn = btn.find('a'); 40446 40447 if (btn.text() === '+') { 40448 btn.text('-'); 40449 } else if (btn.text() === '-') { 40450 btn.text('+'); 40451 } else if (btn.text() === SA.Resource.More.toLowerCase() + '...') { 40452 btn.text('...' + SA.Resource.Less.toLowerCase()); 40453 } else { 40454 btn.text(SA.Resource.More.toLowerCase() + '...'); 40455 } 40456 } 40457 40458 _constructor.changeTimeLength = function(inputBox) { 40459 //Step I: Set Variables 40460 if (this === Wiz5) { 40461 var me = inputBox; 40462 } else { 40463 var me = $(this); 40464 } 40465 40466 if (me.hasClass('wiz5-svc-time')) { 40467 var svcRowId = me.attr('id').substring(4); 40468 var tbl = me.parent().parent().parent(); 40469 var svcTime = me.val(); 40470 } else { 40471 var tbl = me.parent().parent(); 40472 if (tbl.prop('tagName') !== 'TR') { tbl = tbl.parent(); } 40473 40474 var svcRowId = tbl.attr('id').substring(4); 40475 tbl = tbl.parent(); 40476 var svcTime = tbl.find('tr#wiz5-svc' + svcRowId + ' .wiz5-svc-time').val(); 40477 } 40478 40479 if (!UTIL.isNumber(svcTime)) { 40480 svcTime = parseInt(tbl.find('tr#wiz5-svc' + svcRowId + ' .wiz5-default-time-val').text()); 40481 } else { 40482 svcTime = parseInt(svcTime); 40483 } 40484 40485 var totalBlockTime = svcTime; 40486 var rows = tbl.find('tr#prow' + svcRowId); 40487 40488 //Step II: Get Processing Time 40489 var processTime = rows.eq(0).find('input[type="number"]').val(); 40490 if (!UTIL.isNumber(processTime)) { processTime = rows.eq(0).find('.wiz5-default-time-val').text(); } 40491 40492 if (UTIL.isNumber(processTime)) { 40493 processTime = parseInt(processTime); 40494 if (rows.eq(0).find(':checkbox').is(':checked')) { totalBlockTime += processTime; } 40495 } else { 40496 processTime = 0; 40497 } 40498 40499 //Step III: Get Finish Time 40500 var finishTime = rows.eq(1).find('input[type="number"]').val(); 40501 if (!UTIL.isNumber(finishTime)) { finishTime = rows.eq(1).find('.wiz5-default-time-val').text(); } 40502 40503 if (UTIL.isNumber(finishTime)) { 40504 finishTime = parseInt(finishTime); 40505 if (rows.eq(1).find(':checkbox').is(':checked')) { totalBlockTime += finishTime; } 40506 } else { 40507 finishTime = 0; 40508 } 40509 40510 //Step IV: Set Total Time 40511 var total = svcTime + processTime + finishTime; 40512 40513 if (total > 0) { 40514 total = total + ' ' + SA.Resource.Minutes.toLowerCase(); 40515 } else { 40516 total = ""; 40517 } 40518 40519 if (totalBlockTime > 0) { 40520 totalBlockTime = totalBlockTime + ' ' + SA.Resource.Minutes.toLowerCase(); 40521 } else { 40522 totalBlockTime = ""; 40523 } 40524 40525 rows.eq(2).find('.wiz5-total-processing').text(total); 40526 rows.eq(2).find('.wiz5-total-blocked-out').text(totalBlockTime); 40527 } 40528 40529 _constructor.changeBlockOut = function() { 40530 var input = $(this).closest('tr').find('input'); 40531 _constructor.changeTimeLength(input); 40532 } 40533 40534 _constructor.textWhenClientUnconfirms = function(checkbox) { 40535 if (!GLO.Info.isRequireGold(true)) { 40536 $(checkbox).prop('checked', false); 40537 return false; 40538 } 40539 } 40540 40541 _constructor.openHelpReputationManagement = function() { 40542 var h1 = 'How Reputation Management Works'; 40543 var msg1 = '<p>Text Appointment Survey to Clients after appointment</p>'; 40544 var msg2 = '<p>Encourage happy customers to leave great reviews on your social media, while un-happy customers notify you directly (through email) of their complaints</p>'; 40545 40546 var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'repman\', this, event, true)">Enable & Setup Reputation Management</a>'; 40547 var msg3 = '<div style="margin-bottom: 24px;">' + alink + '</div>'; 40548 40549 var htm = '<div>' + msg1 + msg2 + msg3 + '</div>'; 40550 var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-rep-mgmt'); 40551 var jpop = ojInfo.getPopup().addClass('pop-info2'); 40552 } 40553 _constructor.openHelpAllowUnConfirm = function() { 40554 var h1 = 'Allow Client to Un-Confirm Appointment'; 40555 var msg1 = '<p>You can allow your clients to un-confirm appointments from both the text reminder and email reminder</p>'; 40556 var msg2 = '<p>When a client un-confirms it does not delete the appointment, it adds a red vertical bar to the appointment on the calendar</p>'; 40557 40558 var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=appointment&id=faq-appt-unconfirm-question\', this, event, true)">More on Client Un-Confirms</a>'; 40559 var msg3 = '<div style="margin-bottom: 24px;">' + alink + '</div>'; 40560 40561 var htm = '<div>' + msg1 + msg2 + msg3 + '</div>'; 40562 var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-allow-unconfirm'); 40563 var jpop = ojInfo.getPopup().addClass('pop-info2'); 40564 } 40565 40566 _constructor.openHelpBookEvery = function(isIncludeLink, isRequestAppt) { 40567 var h1 = 'Time of Hour that Clients can Book Online'; 40568 var arrow = ' <i>➟</i></b> '; 40569 40570 var cssTop = 'margin-bottom: 12px; color: #666;'; 40571 40572 if (innerWidth > 600) { cssTop += 'margin-left: -32px;'; }
40573 if (innerWidth < 720) { cssTop += 'letter-spacing: 0;'; } 40574 40575 var msgTop = '<p style="' + cssTop + '">Determines times clients can book appointments (when you are available)</p>'; 40576 40577 var msg1 = '<p><b> 5 Minutes, on the hour' + arrow + '12:00, 12:05, 12:10, 12:15, 12:20, 12:25, ...</p>'; 40578 var msg2 = '<p><b>10 Minutes, on the hour' + arrow + '12:00, 12:10, 12:20, 12:30, ...</p>'; 40579 var msg3 = '<p><b>15 Minutes, on the hour' + arrow + '12:00, 12:15, 12:30, 12:45, 1:00, 1:15, ...</p>'; 40580 var msg4 = '<p><b>30 Minutes, on the hour' + arrow + '12:00, 12:30, 1:00, 1:30, ...</p>'; 40581 var msg5 = '<p><b>60 Minutes, on the hour' + arrow + '12:00, 1:00, 2:00, 3:00, ...</p>'; 40582 40583 if (UTIL.isEmpty(isIncludeLink)) { 40584 isIncludeLink = ($('#report-main.staff-profile-report').length === 0); 40585 } 40586 40587 if (isIncludeLink) { 40588 var urlMoreInfo = 'reports/StaffProfile#tab=report-client-config&highlight=report-column-online-on-the-hour'; 40589 var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlMoreInfo + '\', this, event, true)" title="View & Change Book on the Hour Restriction">View & Change</a>'; 40590 var msgLink = '<div style="margin-bottom: 24px;">' + alink + '</div>'; 40591 } else { 40592 var msgLink = ''; 40593 } 40594 40595 if (isRequestAppt) { 40596 var htmRequestAppt = '<p style="margin-top: 32px;">Setting this value to anything other than <b class="narrow-text">Any Time</b> restricts the time range allowed to only normal business hours</p>'; 40597 } else { 40598 var htmRequestAppt = ''; 40599 } 40600 40601 var htm = '<div>' + msgTop + msg1 + msg2 + msg3 + msg4 + msg5 + msgLink + htmRequestAppt + '</div>'; 40602 40603 var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-book-every'); 40604 var jpop = ojInfo.getPopup().addClass('pop-info2'); 40605 } 40606 40607 _constructor.openHelpNeighborOpenings = function() { 40608 var link = '<a onclick="GLO.Uri.gotoUri2(\'reports/StaffProfile?highlight=report-column-online-neighbor-only#tab=report-client-config\')">Neighbor Openings</a>'; 40609 var bNeighbor = '<b class="narrow-text">Neighbor Openings</b>'; 40610 var bOnHr = '<b class="narrow-text">On the Hour</b>'; 40611 var bArrow = '<b class="arrow-right">➜</b>'; 40612 40613 var msg1 = '<p>' + bNeighbor + bArrow + ' available time on the calendar that begin or end next to an already existing appointment</p>'; 40614 40615 var msg2 = '<p>Can Allow ' + bNeighbor + ' close to the day of the appointment to book time that does not match your ' + bOnHr + ' setting</p>'; 40616 var msg3 = '<p style="margin-top: 0; font-size: 80%;">for example: useful if only allow appointments on the hour, but have some services that take less than 60 minutes</p>'; 40617 40618 var msg4 = '<p>Can only allow neighbor appointments <span class="narrow-text">(when day already has 2 or more appointments)</span></p>'; 40619 var msg5 = '<p></p>'; 40620 40621 var htm = '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>'; 40622 var ojInfo = GLO.UI.openHelp2('Neighbor Openings', htm, 'pop-help-neighbor-openings'); 40623 var jpop = ojInfo.getPopup().addClass('pop-info2'); 40624 } 40625 40626 _constructor.askServicePriceDiff = function(staffid, priceDiffCount) { 40627 if (priceDiffCount > 0) { 40628 var htm = '<p>Update ' + UTIL.pluralLabel(priceDiffCount, 'upcoming appointment') + ' to the new price?</p>'; 40629 var fnYes = function() { Wiz5.updateNewServicePrice(staffid); }; 40630 40631 GLO.Popup.Confirm.open(htm, 'Update to New Price?', fnYes); 40632 } 40633 } 40634 40635 _constructor.updateNewServicePrice = function(staffid, sgid) { 40636 var url = GLO.Link.Object.Provider.Ajax + 'ScheduleUpdatePrice?staff=' + UTIL.cleanString(staffid) + '&sgid=' + UTIL.cleanString(sgid); 40637 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 40638 .success(function(data, textStatus, jqXHR) { 40639 40640 }) 40641 .error(function(jqXHR, textStatus, errorThrown) { 40642 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 40643 }); 40644 } 40645 40646 return _constructor; 40647})(); 40648 40649 40650var Wiz6 = (function() { 40651 function _conWiz6(name) { } 40652 40653 _conWiz6.init = function() { 40654 WIZ.init(6, '#wiz6-main'); 40655 _initWizButtons(); 40656 40657 $('#wiz-arrowRight').addClass('hide'); 40658 Wiz6.changeCardType(); 40659 _displaySuccessPopup(); 40660 _initNewCard(); 40661 _initWiz6Url(); 40662 } 40663 function _initWiz6Url() { 40664 var warning = UTIL.cleanString(GLO.Uri.url('warning'));
40665 40666 if (!UTIL.isEmpty(warning)) { 40667 GLO.Popup.Warning.open('<div id="pop-warn-wiz6">' + warning + '</div>', 'Card Not Updated'); 40668 } 40669 40670 GLO.Report.Other.initUrl(); 40671 } 40672 function _initNewCard() { 40673 var jexpire = $('#wiz6-main #upgrade-package-trial-expiration-days'); 40674 40675 if (jexpire.length == 0) { 40676 jexpire = $('#wiz6-main #upgrade-package-trial-expiration-date'); 40677 } 40678 40679 if (jexpire.length > 0) { 40680 var dtUpdate = $('#wiz6-main #Last_Update_dt').val(); 40681 var dtToday = new Date(new Date().toGloDate()); 40682 var trialExpiresInDays = $('#upgrade-package-trial-expiration-days').attr('trial_ends_in_days_sr'); 40683 40684 if (GLO.Data.provider.payment_progress_cd == 10) { 40685 //if (UTIL.isDate(dtUpdate) && UTIL.isToday(dtUpdate)) { 40686 if (trialExpiresInDays > 0) { 40687 var msg = '<div>Your trial expires in ' + UTIL.pluralLabel(trialExpiresInDays, 'day') + '</div>'; 40688 } else { 40689 var msg = '<div>Thank you for updating your card information</div>'; // <div>Your card will be processed tonight</div>'; 40690 } 40691 40692 jexpire.after('<div class="upgrade-package-trial-expire" style="margin-top: 20px;">' + msg + '</div>'); 40693 } 40694 } 40695 } 40696 40697 function _initWizButtons() { 40698 var jwizBtns = $('.wiz-buttons').removeClass('hide'); 40699 var jwiz6cc = $('#wiz6-creditcard'); 40700 40701 if (jwiz6cc.length > 0) { 40702 jwizBtns.css({ "position": "relative", "bottom": "inherit", "height": "60px", "margin-top": "32px", "margin-bottom": "80px", "padding-top": "12px", "padding-bottom": "16px" }); 40703 jwiz6cc.after(jwizBtns); 40704 } 40705 40706 if (!UTIL.isEmpty(jwiz6cc.find('#Card_Number_vc').val())) { 40707 var btnText = SA.Resource.UpdateCreditCard; 40708 } else if (GLO.Data.provider.signupDetail == 20) { 40709 var btnText = SA.Resource.Upgrade; 40710 } else { 40711 var btnText = SA.Resource.AddCreditCard; 40712 } 40713 40714 var pstatus = parseInt($.cookies.get('pstatus')); 40715 var cssJson = { "position": "relative", "right": "inherit", "margin-left": "0" }; 40716 40717 if (GLO.Provider.isPaidAccount()) { 40718 $('#wiz6-trial').removeClass('hide'); 40719 $('#Provider_Status_cd1').prop('checked', true); 40720 } else if (pstatus < 11) { // > 7, but not 11 (ie. trial or inactive) 40721 btnText = SA.Resource.SignUp; 40722 cssJson = { }; 40723 } 40724 40725 var btnNext = jwizBtns.find('#btnNext').css(cssJson).find('a').text(btnText).css({ "letter-spacing": "1px" }); 40726 40727 if (WIZ.isWizard) { 40728 jwizBtns.find('#btnPrev').removeClass('hide').css({ "margin-right": "90px" }); 40729 } else { 40730 btnNext.css({ "padding": "8px 16px 6px", "font-size": "20px" }); 40731 } 40732 } 40733 40734 function _displaySuccessPopup() { 40735 var upgrade = UTIL.cleanString(GLO.Uri.url('upgrade')).toLowerCase(); 40736 40737 if (upgrade === 'success') { 40738 var packageName = SA.Upgrade.getPackageName(GLO.Info.providerPackage); 40739 40740 if (GLO.Info.providerPackage == 2) { 40741 var h1 = SA.Resource.UpgradeSuccessful; 40742 var msg = SA.Resource.AccountSuccessfullyUpgraded + ' ' + packageName + ' ' + SA.Resource.Package; 40743 } else { 40744 var h1 = SA.Resource.PackageChanged; 40745 var msg = SA.Resource.AccountSuccessfullyChanged + ' ' + packageName + ' ' + SA.Resource.Package; 40746 } 40747 40748 //var fnReload = function() { location.reload(); } 40749 40750 var htm = '<div id="pop-success-apple-subscription"> <div class="friendly-msg2" style="padding-bottom: 8px;">' + msg + '</div></div>'; //<h1 class="friendly-msg2">' + h1 + '</h1> 40751 var jpop = GLO.Popup.Processing.open(htm, h1); //, fnReload //.getPopup().css({ "padding-bottom": "8px" }); 40752 //jpop.find('.pop-icon').attr('id', 'success-icon'); 40753 //setTimeout(fnReload, 9500); 40754 } 40755 } 40756 40757 _conWiz6.changeCardType = function () { 40758 var tmp = $('#Card_Type_cd').val(); 40759 40760 if (tmp == "3") { 40761 $("#Card_Number_vc").mask("cccc cccccc c9999"); 40762 $("#CCV_Code_vc").mask("bbbb"); 40763 $("#Card_Number_vc").focus(); 40764 } else { //if (tmp == "1" || tmp == "2" || tmp == "3") { 40765 $("#Card_Number_vc").mask("cccc cccc cccc 9999"); 40766 $("#CCV_Code_vc").mask("bbb"); 40767 $("#Card_Number_vc").focus(); 40768 } 40769 } 40770 40771 _conWiz6.signupClick = function (me) { 40772 me = $(me); 40773 40774 if ($.cookies.get('pstatus') == '11') { 40775 $('#btnNext').find('a').text(SA.Resource.Save); 40776 } else { 40777 if (me.attr('id') === 'Provider_Status_cd1') { 40778 $('#btnNext').find('a').text(SA.Resource.SignUp); 40779 $('#wiz6-main .reqlater').removeClass('reqlater').addClass('required'); 40780 $('#wiz6-creditcard').removeClass('hide2'); 40781 } else { 40782 $('#btnNext').find('a').text(SA.Resource.SignUp); 40783 $('#wiz6-main .required').removeClass('required').addClass('reqlater'); 40784 $('#Zip_vc').removeClass('required'); 40785 $('#wiz6-creditcard').addClass('hide2'); 40786 UTIL.Validate.resetForm(WIZ.pageContext); 40787 } 40788 } 40789 } 40790 40791 return _conWiz6; 40792})(); 40793 40794 40795SA.Profile = (function() { 40796 function _conProfile() { } 40797 40798 _conProfile.initTraveler = function() { 40799 GLO.Info.init(); 40800 var j = $('#traveler-edit.main-screen'); 40801 40802 //if (GLO.Provider.isManagerCheck('Travelers', j, true)) { 40803 j.find('input, select, textarea').change( function() { 40804 j.find('.btnSave a').addClass('unsaved-change'); 40805 }); 40806 40807 j.find(':text, textarea').keyup( function() { 40808 j.find('.btnSave a').addClass('unsaved-change'); 40809 }); 40810 //} 40811 } 40812 _conProfile.saveTraveler = function() { 40813 var url = GLO.Link.Page.Provider.Home + 'manage/traveler'; 40814 var j = $('#traveler-edit'); 40815 40816 var qr = j.find('#Traveler_QR_fl').prop('checked'); 40817 var noteFontSize = j.find('#Traveler_Note_Font_Size_sr').val(); 40818 var note = UTIL.htmlEncode(j.find('#Traveler_Note_vc').val());
40819 var jd = { "qr": qr, "note": note, "noteSize": noteFontSize }; 40820 40821 GLO.UI.Form.beginProcessing( j.find('.btnSave') ); 40822 40823 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 40824 .success(function (data, textStatus, jqXHR) { 40825 GLO.UI.Form.resetProcessing(); 40826 GLO.Popup.Success.open('Receipt Changes Saved', 'Edit Receipt'); 40827 40828 j.find('.btnSave a').removeClass('unsaved-change'); 40829 }) 40830 .error(function (jqXHR, textStatus, errorThrown) { 40831 GLO.UI.Form.resetProcessing(); 40832 //new GLO.Popup.Warning('Saving note processing taking longer than normal'); 40833 }); 40834 } 40835 40836 _conProfile.initReceipt = function(merchantIdString) { 40837 GLO.Info.init(); 40838 var j = $('#receipt-edit'); 40839 40840 //if (GLO.Provider.isManagerCheck('Receipt', j, true)) { 40841 j.find('input, select, textarea').change( function() { 40842 j.find('.btnSave a').addClass('unsaved-change'); 40843 }); 40844 //} 40845 40846 if (!UTIL.isEmpty(merchantIdString)) { 40847 var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print')); 40848 40849 if (isDisplayPrintOptions) { 40850 SA.POS.CCBolt.displayPrinterOptions('Clover'); 40851 } 40852 40853 SA.POS.CCBolt.listTerminalDetailsWithCallback(merchantIdString, function(json) { //GLO.Data.provider.merchants[0].idString 40854 SA.POS.CCBolt.loadPrinterSettings(json); 40855 }); 40856 } 40857 } 40858 _conProfile.saveReceipt = function() { 40859 var url = GLO.Link.Page.Provider.Home + 'manage/receipt'; 40860 var j = $('#receipt-edit'); 40861 40862 var rtype = j.find('#Auto_Receipt_cd').val(); 40863 var drawer = j.find('#Cash_Drawer_Setting_cd').val(); 40864 var space = j.find('#Receipt_White_Space_cd').val(); 40865 var layout = j.find('#Receipt_Layout_cd').val(); 40866 var lineItem = j.find('#Receipt_Line_Item_cd').val(); 40867 40868 var fontSize = j.find('#Receipt_Font_Size_sr').val(); 40869 var note = UTIL.htmlEncode(j.find('#Receipt_Note_vc').val()); 40870 var noTip = !j.find('#Receipt_Display_Tip_fl').prop('checked'); //Receipt_No_Tip_fl 40871 var hideLoyalty = j.find('#Display_Loyalty_On_Receipt_fl').length && !j.find('#Display_Loyalty_On_Receipt_fl').prop('checked'); 40872 var linkSetting = j.find('#Receipt_Link_cd').val(); 40873 40874 var jd = { "rtype": rtype, "drawer": drawer, "space": space, "layout": layout, "lines": lineItem 40875 , "fontsize": fontSize, "notip": noTip, "note": note, "hideLoyalty": hideLoyalty, "link": linkSetting }; 40876 40877 GLO.UI.Form.beginProcessing( j.find('.btnSave') ); 40878 40879 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 40880 .success(function (data, textStatus, jqXHR) { 40881 GLO.UI.Form.resetProcessing(); 40882 GLO.Popup.Success.open('Receipt Changes Saved', 'Edit Receipt'); 40883 40884 j.find('.btnSave a').removeClass('unsaved-change'); 40885 }) 40886 .error(function (jqXHR, textStatus, errorThrown) { 40887 GLO.UI.Form.resetProcessing(); 40888 //new GLO.Popup.Warning('Saving note processing taking longer than normal'); 40889 }); 40890 } 40891 40892 _conProfile.Reminder = (function() { 40893 function _conReminder() {}; 40894 var _isLoading = true; 40895 40896 _conReminder.init = function() { 40897 GLO.Info.init(); 40898 SA.TextEditor.init($('#appointment-policy-full .sa-text-editor'), 'Appointment Policy Summary'); 40899 SA.TextEditor.init($('#appointment-policy-full .sa-text-editor'), 'Full Appointment Policy'); 40900 40901 if (GLO.Info.roleType < 220) { 40902 var msg = 'To make changes logout and login as a manager or admin'; 40903 GLO.Popup.Warning.open(msg, 'Read-Only Mode'); 40904 40905 $('#customize-reminder').find('input').prop('disabled', true); 40906 } else { 40907 var j = $('#customize-reminder'); 40908 var btnSave = j.find('.btnSave'); 40909 40910 j.find(':radio, :checkbox, select').change(function() { UI.buttonDisplayChange(btnSave); }); 40911 j.find(':text, textarea, .sa-text-editor').keyup(function() { UI.buttonDisplayChange(btnSave); }); 40912 } 40913 40914 _conReminder.changeMessageGenerate(); 40915 _initUrlActions(); 40916 _isLoading = false; 40917 } 40918 40919 function _initUrlActions() { 40920 //var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 40921 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 40922 40923 if (!UTIL.isEmpty(highlight)) { 40924 var jhighlight = $('#' + highlight + ', .' + highlight); 40925 40926 if (jhighlight.length > 0) { 40927 UI.highlight(jhighlight, 800, 6400, true); 40928 } 40929 } 40930 } 40931 40932 _conReminder.changeMessageGenerate = function() { 40933 var j2 = $('#customize-reminder #customize-reminder-note2'); 40934 var gen2 = j2.find('input[type="radio"][name="Text2_Reminder_Generate_cd"]:checked').val(); 40935 var jnote2 = j2.find('#Text2_Reminder_Note_vc'); 40936 var orig = UTIL.cleanString(jnote2.attr('original_value')); 40937 var pname = GLO.Data.provider.name.replace('&', '&').replace('"', '"').replace(''', '"'); 40938 var defaultCustomNote = 'Hi {client-first-name}, this is ' + pname + '. We look forward to seeing you {appointment-day} at {appointment-time} for your appointment'; 40939 40940 if (gen2 == 20) { 40941 j2.addClass('generate-message-custom').removeClass('generate-message-default'); 40942 40943 if (!_isLoading) { 40944 jnote2.attr('original_value', jnote2.val()); 40945 jnote2.val( UTIL.coalesceString(orig, defaultCustomNote) ); 40946 } 40947 } else { 40948 if (!_isLoading) { 40949 jnote2.attr('original_value', jnote2.val()); 40950 jnote2.val(orig); 40951 } 40952 40953 j2.addClass('generate-message-default').removeClass('generate-message-custom'); 40954 } 40955 } 40956 40957 _conReminder.helpCustomMessage = function() { 40958 var ulstyle = 'text-align: left;', style = 'white-space: pre-wrap; line-height: 170%;'; 40959 var p = '<p style="margin-bottom: 12px;">'; 40960 40961 if (GLO.Info.isMobile()) { 40962 ulstyle = 'margin-left: -36px; margin-right: 0;'; 40963 style += ' padding-right: 8px;'; 40964 } 40965 40966 var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.HowMessageIsCreatedUsingAutofills + '</h1>' 40967 +'<div>' 40968 + '<div class="friendly-msg" style="' + style + '">'
40969 + p + 'You can change the message as desired. Some information in the message can be populated for you.</p>' 40970 + p + 'For example, <i><b>{client-name}</b></i> indicates that the client\'s name will be placed there in the message.</p>' 40971 + p + 'Text message can only be 160 characters so if longer message will be truncated.</p>' 40972 + p + 'Below are some other auto-fills:</p>' 40973 + '<ul style="' + ulstyle + '">' 40974 + '<li><i style="padding-right: 6px;"><b>{client-first-name}</b></i> Client First Name</li>' 40975 + '<li><i style="padding-right: 6px;"><b>{client-name}</b></i> Client Name</li>' 40976 + '<li><i style="padding-right: 6px;"><b>{business-name}</b></i> Business Name</li>' 40977 40978 + '<li><i style="padding-right: 6px;"><b>{staff-first-name}</b></i> Staff First Name</li>' 40979 + '<li><i style="padding-right: 6px;"><b>{staff-name}</b></i> Staff Name</li>' 40980 + '<li><i style="padding-right: 6px;"><b>{service-name}</b></i> Service Name</li>' 40981 40982 + '<li><i style="padding-right: 6px;"><b>{appointment-day}</b></i> Appointment day<span class="narrow-text">today, tomorrow, or actual day if further in future</span></li>' 40983 + '<li><i style="padding-right: 6px;"><b>{appointment-time}</b></i> Appointment time</li>' 40984 + '</ul>' 40985 + '</div>' 40986 + '<div style="margin-left: -32px; margin-top: 20px; margin-bottom: 24px;"> <i style="padding-right: 8px;">Have More Questions?</i> <a href="/contact">Contact Us</a></div>' 40987 + '</div>' 40988 + '</div>'); 40989 var oj = new GLO.Popup.Info(htm); 40990 40991 if (GLO.Info.isMobile()) { 40992 oj.getPopup().find('.msg').css({ "padding-right": "4px" }); 40993 } 40994 40995 return oj 40996 } 40997 40998 _conReminder.save = function() { 40999 var j = $('#customize-reminder'); 41000 var url = GLO.Link.WebsiteDomain + 'message/CustomizeReminder'; 41001 41002 var displayStaff = j.find('#customize-reminder-display-staff').find('input[name="display-staff"]:checked').val(); 41003 var note = UTIL.htmlEncode(j.find('#Text_Reminder_Note_vc').val()); 41004 var note2 = UTIL.htmlEncode(j.find('#Text2_Reminder_Note_vc').val()); 41005 var gen2 = j.find('input[type="radio"][name="Text2_Reminder_Generate_cd"]:checked').val(); 41006 var isDisplayDate = j.find('#Text_Reminder_Display_DateTime_fl').prop('checked'); 41007 var policyHeader = UTIL.htmlEncode(j.find('#Policy_Header_vc').val()); 41008 41009 var policyQuick = '', customHtmQuick = j.find('#appointment-policy-quick .sa-text-editor')[0].innerHTML; 41010 var policyFull = '', customHtmFull = j.find('#appointment-policy-full .sa-text-editor')[0].innerHTML; 41011 41012 if (!UTIL.isEmpty(customHtmQuick)) { 41013 policyQuick = UTIL.htmlEncode(DOMPurify.sanitize(customHtmQuick)); 41014 } 41015 if (!UTIL.isEmpty(customHtmFull)) { 41016 policyFull = UTIL.htmlEncode(DOMPurify.sanitize(customHtmFull)); 41017 } 41018
41019 var jd = { "note": note, "note2": note2, "displayStaff": displayStaff, "isDisplayDate": isDisplayDate, "generate2": gen2 41020 , "policyHeader": policyHeader, "policyQuick": policyQuick, "policyFull": policyFull }; 41021 41022 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 41023 41024 var jqxhr = $.ajax({ type: "POST", url: url, "data": jd, "cache": false }) 41025 .success(function(data, textStatus, jqXHR) { 41026 GLO.UI.Form.resetProcessing(null, true); 41027 var jd = $(data); 41028 var newSampleText = jd.find('#sample-text-reminder').outerHTML(); 41029 var jsample = j.find('#customize-reminder-sample'); 41030 41031 if (jd.hasClass('warning')) { 41032 //GLO.Popup.Warning.open(jd.outerHTML(), 'Unable to Save Changes'); 41033 var ojpop = new GLO.Popup.Custom(jd); 41034 var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score'); 41035 //var score = jd.find('h2 b').text(); 41036 41037 GLO.Popup.Custom.singleButton(jpop, 'Close'); 41038 ojpop.realign(); ojpop.realign(); 41039 } else if (jd.hasClass('is-success')) { 41040 if (gen2 > 0) { 41041 GLO.Popup.Success.open('Changes Saved, Loading Changes..', 'Save Successful'); 41042 41043 setTimeout(function() { location.reload(); }, 1500); 41044 } 41045 41046 jsample.find('.sample').html(newSampleText); 41047 UI.highlight(jsample, 200, 3600); 41048 41049 setTimeout(function() { 41050 jsample.removeClass('highlight-background-undo'); 41051 }, 4200); 41052 } 41053 }) 41054 .error(function(jqXHR, textStatus, errorThrown) { 41055 GLO.UI.Form.resetProcessing(); 41056 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41057 }); 41058 } 41059 41060 return _conReminder; 41061 })(); 41062 41063 return _conProfile; 41064})(); 41065 41066 41067SA.Profile.Language = (function() { 41068 function _conLang() { } 41069 41070 _conLang.openPopup = function() { 41071 var jpop = $('#pop-language-change'); 41072 41073 jpop = new GLO.Popup.Custom(jpop).getPopup(); 41074 var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" }); 41075 41076 jbtns.find('.btnSave').remove(); 41077 jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css( { "float": "none", "width": "60px", "margin": "inherit", "letter-spacing": "1px" }).find('a').text(SA.Resource.Close); 41078 } 41079 41080 _conLang.save = function(newLanguage, btn) { 41081 var icon = $('#select-language-icon'); 41082 GLO.UI.Form.beginProcessing(icon); 41083 41084 $(btn).fadeOut(2400, function() { 41085 var jpop = $('#pop-language-change'); 41086 var msg = '<div class="is-reloading">' + jpop.find('.pop-language-select').attr('loading') + '</div>'; 41087 41088 //jpop.find('.pop-language-select').remove(); 41089 jpop.find('div.friendly-msg2').html(msg); 41090 jpop.find('.is-reloading').fadeIn(2400); 41091 }); 41092 41093 var url = GLO.Link.WebsiteDomain + "provider/ajax/language?language=" + newLanguage; 41094 41095 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 41096 .success(function(data, textStatus, jqXHR) { 41097 location.reload(); 41098 //GLO.UI.Form.resetProcessing(); 41099 //var j = el.closest('#language-icons').find('.hide').removeClass('hide'); 41100 //$.cookies.set("language", language); 41101 }) 41102 .error(function(jqXHR, textStatus, errorThrown) { 41103 GLO.UI.Form.resetProcessing(); 41104 41105 var jpop = $('#pop-language-change').closest('.glopop'); 41106 GLO.Popup.close(jpop); 41107 41108 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); //GLO.Popup.Error('An error occurred. Unable to make save your changes at this time.'); 41109 }); 41110 } 41111 41112 return _conLang; 41113})(); 41114 41115 41116SA.Profile.Email = (function() { 41117 function _conProfileEmail(name) { } 41118 41119 _conProfileEmail.init = function() { 41120 $('#Email_Appt_Footer_vc, #From_Email_vc, #From_Email_Display_vc, .sa-text-editor').on('keyup', function() { 41121 $('#email-footer-container').find('.btnSave > a').css({ "border": "3px solid Red" }); 41122 }); 41123 41124 $('.wiz-buttons, #wiz-button-top-padding').remove(); 41125 41126 SA.TextEditor.init($('.sa-text-editor'), 'Email Footer'); 41127 //GLO.Info.displayHelloBarBack('Advanced Setup', '/provider/manage/advanced'); 41128 } 41129 41130 function _fromIsValid(email) { 41131 var msg = null; 41132 email = email.toLowerCase(); 41133 41134 if (!UTIL.Validate.email(email)) { 41135 _displayFromInvalidPopup(SA.Resource.PleaseEnterValidEmail); 41136 return false; 41137 } 41138 41139 if (email.indexOf('@yahoo') !== -1) { 41140 msg = 'Cannot Use Yahoo Email Address'; 41141 } else if (email.indexOf('@hotmail') !== -1) { 41142 msg = 'Cannot Use Hotmail Email Address'; 41143 } else if (email.indexOf('@live') !== -1) { 41144 msg = 'Cannot Use Microsoft Live Email Address'; 41145 } else if (email.indexOf('@outlook') !== -1) { 41146 msg = 'Cannot Use Outlook Email Address'; 41147 } else if (email.indexOf('@apple') !== -1) { 41148 msg = 'Cannot Use Apple Email Address'; 41149 } else if (email.indexOf('@aol') !== -1) { 41150 msg = 'Cannot Use Aol Email Address'; 41151 } else if (email.indexOf('@mail') !== -1 || email.indexOf('@gmx') !== -1) { 41152 msg = 'Cannot Use GMX Email Address'; 41153 } else if (email.indexOf('@facebook') !== -1 || email.indexOf('@gmx') !== -1) { 41154 msg = 'Cannot Use Facebook Email Address'; 41155 } else if (email.indexOf('@gmail') !== -1 || email.indexOf('@gmx') !== -1) { 41156 msg = 'Cannot Use Gmail Email Address'; 41157 } 41158 41159 if (msg !== null) { 41160 var h4style = 'margin-left: -44px; letter-spacing: 1px; font-size: 16px;'; 41161 var p = '<p style="min-width: 260px; margin-top: 16px; line-height: 180%;">'; 41162 var p3 = ' does many things to ensure deliverability, so we suggest keeping the default from email address the same and instead change the <b class="narrow-text">From Display Name</b>'; 41163 41164 var htm = '<div style="margin-bottom: 12px; padding-bottom: 16px;"> <h4 style="' + h4style + '">' + msg + '</h4>' 41165 + p + SA.Resource.EmailSetup1 + '</p>' 41166 + p + SA.Resource.EmailSetup2 + '</p>'
41167 + p + GLO.Info.getScheduleAnyoneHtm() + p3 + '</p>' 41168 + '</div>'; 41169 41170 $('#From_Email_vc').val('[email protected]'); 41171 41172 _displayFromInvalidPopup(htm); 41173 return false; 41174 } else { 41175 return true; 41176 } 41177 } 41178 41179 function _displayFromInvalidPopup(msg) { 41180 var htm = $('<div>' + msg + '</div>'); 41181 return new GLO.Popup.Warning(htm, function() { 41182 $('#From_Email_vc').focus(); 41183 }); 41184 } 41185 41186 _conProfileEmail.fromHelp = function() { 41187 var style = 'white-space: pre-wrap; line-height: 170%;'; 41188 var p = '<p style="margin-bottom: 12px; line-height: 1.3;">'; 41189 var p2 = '<p style="margin-top: 24px; line-height: 1.3;">'; 41190 41191 var msgAutomatedEmails = 'automated emails <span class="narrow-text">(like confirmations, reminders, receipts, follow-ups, etc)</span>'; 41192 var hrefGoogleRequirements = 'https://support.google.com/a/answer/81126?visit_id=638569182043216159-3939602876&rd=1#zippy=%2Crequirements-for-all-senders'; 41193 var aGoogleRequirements = '<a href="' + hrefGoogleRequirements + '" style="font-family: Arial; font-stretch: condensed;">https://support.google.com/a/answer/81126</a>'; 41194 var bArrow = '<b class="html-arrow"></b>'; 41195 41196 var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.SendEmailsFromYourDomain + '</h1>' 41197 +'<div style="margin-bottom: 20px;">' 41198 + '<div class="friendly-msg" style="' + style + '">' 41199 + p + SA.Resource.SendEmailsFromYourDomainHelp1 + '</p>' 41200 + p + SA.Resource.SendEmailsFromYourDomainHelp2 + '</p>' 41201 + p + SA.Resource.SendEmailsFromYourDomainHelp3 + '</p>' 41202 41203 + p2 + 'Many of the major email apps (like Yahoo and Gmail) have been requiring more security settings from the domain sending the emails' + '</p>' 41204 + p + 'If you send ' + msgAutomatedEmails + ' from your own domain then you might not have these DNS settings on your domain which could reduce deliverability' + '</p>' 41205 41206 + p + GLO.Info.getScheduleAnyoneHtm() + ' is continuously evolving with the changing standards and requirements. ' 41207 + 'If clients are having issues receiving emails, then we suggest not using your custom email address ' 41208 + 'and instead use the <b class="narrow-text">From Email Display Name</b> feature; ' 41209 + 'this way even though the emails are sent from <span class="narrow-text">[email protected]</span> ' + bArrow 41210 + ' your clients will see your <b class="narrow-text">From Email Display Name</b></p>' 41211 41212 + p2 + 'If you want to continue sending emails from your domain then here are Google\'s requirements for sending to gmail addresses: ' + aGoogleRequirements + '</p>' 41213 + '</div>' 41214 + '<div style="margin-top: 20px;"> <i style="padding-right: 8px;">' + SA.Resource.HaveMoreQuestions + '?</i> <a href="/contact">' + SA.Resource.ContactUs + '</a></div>' 41215 + '</div>' 41216 + '</div>'); 41217 return new GLO.Popup.Info(htm); 41218 } 41219 41220 _conProfileEmail.fromDisplayNameHelp = function() { 41221 var style = 'white-space: pre-wrap; line-height: 170%;'; 41222 var p = '<p style="margin-bottom: 12px;">'; 41223 41224 var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">From Email Display Name</h1>' 41225 +'<div>' 41226 + '<div class="friendly-msg" style="' + style + '">' 41227 + p + 'When ' + GLO.Info.getScheduleAnyoneHtm() + ' sends emails to your clients the from email address will use this <b>Display Name</b></p>' 41228 + '</div>' 41229 + '</div>' 41230 + '</div>'); 41231 return new GLO.Popup.Info(htm); 41232 } 41233 41234 _conProfileEmail.saveEmailApptFooter = function() { 41235 var j = $('#email-attributes'); 41236 var jsave = j.find('.btnSave'); 41237 var efrom = UTIL.cleanString(j.find('#From_Email_vc').val()); 41238 var efromDisplay = UTIL.cleanString(j.find('#From_Email_Display_vc').val()); 41239 41240 if (efrom !== '') { 41241 if ( !_fromIsValid(efrom)) { return; } 41242 } 41243 41244 var efooter = ''; //UTIL.htmlEncode(j.find('#Email_Appt_Footer_vc').val()); 41245 var customHtm = j.find('.sa-text-editor')[0].innerHTML; 41246 41247 if (!UTIL.isEmpty(customHtm)) { 41248 efooter = UTIL.htmlEncode(DOMPurify.sanitize(customHtm)); 41249 } 41250 41251 var url = GLO.Link.Page.Provider.WebTemplate + 'SaveEmailTemplate'; 41252 GLO.UI.Form.beginProcessing(jsave); 41253
41254 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "Email_Appt_Footer_vc": efooter, "From_Email_vc": efrom, "From_Email_Display_vc": efromDisplay } }) 41255 .success(function(data, textStatus, jqXHR) { 41256 GLO.UI.Form.resetProcessing(); 41257 $('.btnSave:visible a').css({ "border": "3px solid transparent" }); 41258 41259 new GLO.Popup.Success(SA.Resource.ChangesSaved); 41260 }) 41261 .error(function(jqXHR, textStatus, errorThrown) { 41262 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41263 }); 41264 } 41265 41266 return _conProfileEmail; 41267})(); 41268 41269 41270SA.Note = (function() { //= Client Note History 41271 function _conNote(name) { } 41272 41273 _conNote.init = function() { 41274 $('#note-header').find('textarea').on('keyup', SA.Note.changeNote); 41275 41276 var h2 = $('#note-history').find('h2'); 41277 var cname = '<span>' + h2.find('span').text() + '</span>'; 41278 41279 //if (innerWidth > 600) { cname += ' <i>' + SA.Resource.Notes + '</i>'; } 41280 h2.html(cname + ClientProfile.getDropIcon()); 41281 ClientProfile.clearUnlockPassword(); 41282 41283 $('#note-history').find('.client-image img').on('click', UserPortal.StaffNote.openImage); 41284 _initNoteLinks(); 41285 } 41286 41287 function _initNoteLinks() { 41288 var jhistory = $('#note-history'); 41289 var jclientNote = jhistory.find('#Other_Note_vc'); 41290 var japptNotes = jhistory.find('.note-staff-only'); 41291 41292 var clientNote = $.trim(jclientNote.val()); 41293 41294 const urlPattern = /(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\/[^\s]*)?/gi; 41295 const urls = clientNote.match(urlPattern); 41296 41297 if (urls && urls.length > 0) { 41298 for (var i = urls.length; i > 0; i--) { 41299 var maxWidth = (jhistory.width() - 40); 41300 var onClick = 'SA.App.openLinkInBrowser(\'' + urls[i-1] + '\', this, event, true)'; 41301 var htmLink = '<div class="client-note-link"><a onclick="' + onClick + '" style="max-width: ' + maxWidth + 'px;">' + urls[i-1] + '</a></div>'; 41302 41303 jclientNote.after(htmLink); 41304 } 41305 } 41306 41307 for (var c = 0; c < japptNotes.length; c++) { 41308 var note = japptNotes.eq(c).text(); 41309 const urls = note.match(urlPattern); 41310 41311 if (urls && urls.length > 0) { 41312 for (var i = urls.length; i > 0; i--) { 41313 var onClick = 'SA.App.openLinkInBrowser(\'' + urls[i-1] + '\', this, event, true)'; 41314 var htmLink = '<div class="client-note-link"><a onclick="' + onClick + '">' + urls[i-1] + '</a></div>'; 41315 41316 note = note.replace(urls[i-1], htmLink); 41317 } 41318 41319 japptNotes.eq(c).html(note); 41320 } 41321 } 41322 } 41323 41324 _conNote.openHelp = function() { 41325 var jpop = $('#pop-note-history-help'); 41326 var jpop = new GLO.Popup.Custom(jpop).getPopup() 41327 41328 var jbtns = jpop.find('.pop-buttons'); 41329 jbtns.find('.btnSave').remove(); 41330 jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').find('a').text('Close'); 41331 } 41332 41333 _conNote.changeNote = function() { 41334 var div = $(this).parent().addClass('edit-note'); 41335 div.find('.btnSave > a').css({ "border": "3px solid red" }); 41336 } 41337 41338 _conNote.open = function(cid, useCurrentModal, smid) { 41339 var url = location.protocol + '//' + location.host + '/provider/NoteHistory?clientId=' + cid; 41340 41341 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 41342 .success(function(data, textStatus, jqXHR) { 41343 if (ClientProfile.isFullPageProfile()) { 41344 UI.closeAllPopups(); 41345 var jcontainer = $('.shadow-content0').html(data); 41346 } else if (useCurrentModal) { 41347 var throbber = $('.loading-client-quick-view').remove(); 41348 var jcontainer = $('#simplemodal-container'); 41349 41350 if (jcontainer.length === 1) { 41351 jcontainer.find('> .simplemodal-wrap').html(data); 41352 } else if (throbber.length === 1) { 41353 $('.shadow-content0').html(data); 41354 } 41355 } 41356 41357 _conNote.postOpen(smid); 41358 }) 41359 .error(function(jqXHR, textStatus, errorThrown) { 41360 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41361 }); 41362 } 41363 41364 _conNote.postOpen = function(smid) { 41365 if (innerWidth > 780) { //if (!GLO.Info.isMobile()) { $.modal.update(620, 670); } 41366 $.modal.update(600, 760); 41367 } else {
41368 $('#simplemodal-container').css({ "width": "inherit" }); 41369 $.modal.update(600, null); 41370 } 41371 41372 var pop = $('#simplemodal-container').css({ "padding": "0", "background": "" }); 41373 pop.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 41374 pop.find('.simplemodal-data').css({ "padding": "0" }); 41375 41376 if (pop.width() < 760 && innerWidth > 780) { 41377 $.modal.update(600, 760); 41378 } else if (pop.width() < 700 && innerWidth > 720) { 41379 $.modal.update(600, 700); 41380 } else if (pop.width() < 600 && innerWidth > 620) { 41381 $.modal.update(600, 600); 41382 } 41383 41384 ClientProfile.openNoteHistoryCompleted(smid); 41385 } 41386 41387 _conNote.save = function(btn) { 41388 var cid = $('#note-history').find('h2').attr('client_id'); 41389 var jsave = $(btn); 41390 var div = jsave.closest('.edit-note'); 41391 var jtext = div.find('textarea'); 41392 var note = UTIL.htmlEncode(jtext.val()); 41393 41394 if (jtext.attr('id').toLowerCase() === 'important_note_vc') { 41395 var noteType = 1; 41396 } else if (jtext.attr('id').toLowerCase() === 'other_note_vc') { 41397 var noteType = 2; 41398 } 41399 41400 var url = location.protocol + '//' + location.host + '/provider/NoteClient?clientId=' + cid + '¬eType=' + noteType; 41401 GLO.UI.Form.beginProcessing(jsave.parent()); 41402 41403 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "note": note } }) 41404 .success(function(data, textStatus, jqXHR) { 41405 GLO.UI.Form.resetProcessing(); 41406 jsave.find('a').css({ "border": "3px solid transparent" }); 41407 div.removeClass('edit-note'); 41408 //new GLO.Popup.Success('Note Saved'); 41409 }) 41410 .error(function(jqXHR, textStatus, errorThrown) { 41411 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41412 }); 41413 } 41414 41415 return _conNote; 41416})(); 41417 41418 41419SA.Upgrade = (function() { 41420 function _conUpgrade() { } 41421 41422 _conUpgrade.initReadOnly = function(label, jcontainer, requiredPackage) { //requiredPackage = 'gold' | 'silver' | null 41423 GLO.Info.init(); 41424 var isPaidAccount = GLO.Provider.isPaidAccount(true); 41425 41426 if ((isPaidAccount || UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 100) < 80) && GLO.Info.providerPackage != 1) { return false; } 41427 41428 var url = 'hello/pricing'; 41429 var apaid = '<a onclick="GLO.Uri.gotoUri(\'/' + url + '\', this)" style="border-bottom: none;">'; 41430 var msgcss = '', requiredPackage2 = requiredPackage; 41431 41432 if (innerWidth > 600) { msgcss += 'text-align: center;'; } 41433 if (innerWidth > 800) { msgcss += 'font-size: larger;'; } 41434 41435 if (!isPaidAccount) { 41436 if (UTIL.isEmpty(requiredPackage)) { 41437 requiredPackage = 'paid account'; 41438 requiredPackage2 = 'packages'; 41439 } 41440 } else { 41441 if (UTIL.isEmpty(requiredPackage)) { 41442 requiredPackage = 'gold package'; 41443 requiredPackage2 = 'gold package'; 41444 } else if (requiredPackage.toLower().indexOf('package') === -1) { 41445 requiredPackage += ' package'; 41446 } 41447 41448 url += '?tab=' + $.trim(requiredPackage).toLowerCase().replace('package', ''); 41449 } 41450 41451 var msg1 = '<div>' + label.substring(0,1).toUpperCase() + label.substring(1) + ' requires a ' + requiredPackage + ' to setup and use</div>'; 41452 var msg2 = '<div style="min-width: 300px; margin-top: 12px; margin-bottom: 8px; font-weight: bold;">' + apaid + 'Press here to checkout our ' + requiredPackage2 + '</a></div>'; 41453 var msg = '<div style="' + msgcss + '">' + msg1 + msg2 + '</div>'; 41454 41455 var btnCSS = 'position: absolute; left: 8px; text-transform: capitalize; font-family: Georgia;'; 41456 var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'' + url + '\', this)">View ' + requiredPackage2 + '</a> </span>'; 41457 41458 var h1 = '<b style="font-size: larger;">Read Only Mode</b>'; 41459 var jpop = GLO.Provider.Advanced.Help.open(h1, msg); 41460 41461 if (btn) { 41462 var jbtns = jpop.find('.pop-buttons').css({ "position": "relative" }); 41463 jbtns.prepend(btn); 41464 jbtns.find('.btnCancel').addClass('btnClick').css({ "position": "absolute", "right": "8px", "width": "64px", "font-size": "100%" });
41465 } 41466 41467 if (jcontainer) { 41468 _addReadOnlyOverlay(jcontainer, msg); 41469 } 41470 41471 return true; 41472 } 41473 41474 function _addReadOnlyOverlay(jcontainer, message) { 41475 var msg = '<div class="block-msg">' + message + '</div>'; 41476 var htmUpgrade = '<div class="block-container">' + msg + '</div>'; 41477 41478 var jmsg = jcontainer.css({ "opacity": ".4" }); 41479 jmsg.parent().css({ "position": "relative" }).prepend(htmUpgrade); 41480 } 41481 41482 _conUpgrade.gotoUpgradePackage = function(btn, reason, helloback) { 41483 if (btn) { 41484 btn = $(btn).parent(); 41485 GLO.UI.Form.beginProcessing(btn); 41486 } 41487 41488 var ojProcessing = new GLO.Popup.Processing(SA.Resource.LoadingUpgradePage + '...'); 41489 41490 setTimeout(function() { 41491 var url = GLO.Link.WebsiteDomain + 'provider/profile/6?'; 41492 if (!UTIL.isEmpty(reason)) { url += 'reason=' + reason; } 41493 if (helloback) { url += '&helloback=' + helloback; } 41494 41495 if (false && GLO.Info.isIosApp && GLO.Data.provider.signup == 50 && GLO.Info.providerPackage !== 1) { 41496 SA.App.openLinkInBrowser(url); 41497 41498 setTimeout(function() { 41499 GLO.Popup.close(ojProcessing); 41500 }, 2500); 41501 } else { 41502 document.location = url; 41503 } 41504 }, 150); 41505 41506 /* 41507 var msg = 'Contact your Schedule Anyone customer service rep to setup this feature or email us at <a href="mailto:[email protected]">[email protected]</a>'; 41508 msg = '<div style="margin-bottom: 8px; padding: 12px 8px; letter-spacing: 1px; line-height: 200%;">' + msg + '</div>'; 41509 new GLO.Popup.Info(msg); 41510 */ 41511 } 41512 41513 _conUpgrade.getPackageName = function(packageType) { 41514 if (packageType == 1) { 41515 return SA.Resource.Individual; 41516 } else if (packageType == 4) { 41517 return SA.Resource.BusinessBasic; 41518 } else if (packageType == 2) { 41519 return SA.Resource.BusinessPremium; 41520 } else if (packageType == 10) { 41521 return SA.Resource.Retail; 41522 } else { 41523 return ''; 41524 } 41525 } 41526 41527 _conUpgrade.getPackagePriceNumber = function(packageType) { 41528 if (packageType == 1) { 41529 return 9.99; 41530 } else if (packageType != 2) { 41531 return 39.99; 41532 } else { 41533 return null; 41534 } 41535 } 41536 41537 function _getPackagePrice(packageType) { 41538 if (packageType == 1) { 41539 return '<span class="package-price">$9.<i>99</i></span>'; 41540 } else if (packageType == 4) { 41541 return '<span class="package-price">$39<i>.99</i></span>'; 41542 } else if (packageType == 2) { 41543 return '$25 + $5 ' + SA.Resource.PerStaff.toLowerCase(); 41544 } else if (packageType == 10) { 41545 return '<span class="package-price">$39.<i>99</i></span>'; 41546 } else { 41547 return ''; 41548 } 41549 } 41550 41551 _conUpgrade.businessToPersonal = function(packageName, packagePrice) { 41552 var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ConfirmChangePackage + '</h1>'; 41553 var msg1 = '<div>' + SA.Resource.ChangeToThe + ' ' + packageName + ' ' + SA.Resource.Package.toLowerCase() + '?</div>'; 41554 var msg2 = '<div style="margin-top: 12px;">' + SA.Resource.NewMonthlyPrice + ' ' + packagePrice + '</div>'; 41555 var htm = $('<div id="pop-confirm-downgrade">' + h1 + '<div class="friendly-msg2" style="padding-left: 8px; padding-bottom: 12px;">' + msg1 + msg2 + '</div> </div>'); 41556 41557 var oj = new GLO.Popup.Custom(htm, SA.Upgrade.businessToPersonal2); 41558 var jpop = oj.getPopup().addClass('no-persist'); 41559 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); //.css({ "height": "40px", "text-align": "center" }); 41560 jbtns.find('a').css({ "outline": "none", "webkit-appearance": "none" }); 41561 jbtns.find('.btnSave > a').text(' Go ').css({ "letter-spacing": "2px" }); 41562 } 41563 41564 _conUpgrade.businessToPersonal2 = function() { 41565 var jpop = $('#pop-confirm-downgrade').closest('.glopop'); 41566 GLO.Popup.close(jpop); 41567 41568 var jbtn = $('#wiz5-UpgradePersonalToBusiness'); 41569 if (jbtn.length) { GLO.UI.Form.beginProcessing(jbtn); } 41570 41571 if ( $('#wiz6-creditcard').length > 0 ) {
41572 SA.Upgrade.save(1); 41573 return; 41574 } 41575 } 41576 41577 _conUpgrade.personalToBusiness = function() { 41578 var htm = $('<div id="pop-default-role-type" style="text-align: center;"> <h2 class="friendly-msg2">My Staff Is Primarily</h2> <ul>' 41579 + '<li>' 41580 + '<input type="radio" id="staff-role-independent" name="Default_Role_Type_cd" value="170"/>' 41581 + '<label for="staff-role-independent">Independent Contractors</label>' 41582 + '</li>' 41583 + '<li>' 41584 + '<input type="radio" id="staff-role-commission" name="Default_Role_Type_cd" value="150" checked="checked"/>' 41585 + '<label for="staff-role-commission">Commission</label>' 41586 + '</li>' 41587 + '<li>' 41588 + '<input type="radio" id="staff-role-employees" name="Default_Role_Type_cd" value="140"/>' 41589 + '<label for="staff-role-employees">Employees</label>' 41590 + '</li>' 41591 + '</ul></div>'); 41592 41593 var oj = new GLO.Popup.Custom(htm, SA.Upgrade.personalToBusiness2); 41594 var jpop = oj.getPopup().addClass('no-persist'); 41595 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); //.css({ "height": "40px", "text-align": "center" }); 41596 jbtns.find('a').css({ "outline": "none", "webkit-appearance": "none" }); 41597 jbtns.find('.btnSave > a').text(' Go ').css({ "letter-spacing": "2px" }); 41598 } 41599 41600 _conUpgrade.personalToBusiness2 = function() { 41601 var jpop = $('#pop-default-role-type').closest('.glopop'); 41602 var rt = jpop.find('input[name="Default_Role_Type_cd"]:checked').val(); 41603 GLO.Popup.close(jpop); 41604 41605 if ( $('#wiz6-creditcard').length > 0 ) { 41606 SA.Upgrade.saveConfirm(null, 4, rt); 41607 return; 41608 } 41609 41610 var url = GLO.Link.Object.Provider.Ajax + "UpdatePersonalToBusiness?DefaultRoleType=" + rt; 41611 var jbtn = $('#wiz5-UpgradePersonalToBusiness'); 41612 GLO.UI.Form.beginProcessing(jbtn); 41613 41614 //Upgrading to multi-user account... 41615 //Adding Staff... 41616 41617 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: {} }) 41618 .success(function(data, textStatus, jqXHR) { 41619 GLO.UI.Form.resetProcessing(); 41620 41621 if (data) { 41622 var jpop = new GLO.Popup.Info(data, function() { 41623 var jbtn = $('#wiz5-UpgradePersonalToBusiness'); 41624 GLO.UI.Form.beginProcessing(jbtn); 41625 new GLO.Popup.Info('Loading New Mult-User Account...'); 41626 41627 setTimeout(function() { 41628 var refreshUrl = document.location.href; 41629 document.location = refreshUrl; //location.reload(true); 41630 }, 900); 41631 }).getPopup(); 41632 41633 if (innerWidth < 400 || GLO.Info.isMobile()) { 41634 jpop.find('.msg').css({ "padding-left": "6px", "padding-right": "4px", "background-color": "rgb(189, 229, 248)" }); 41635 } 41636 } 41637 }) 41638 .error(function(jqXHR, textStatus, errorThrown) { 41639 //GLO.Popup.Error('An error occurred. Unable to make save your changes at this time.'); 41640 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41641 }); 41642 } 41643 41644 function _navigateToPackageProfile(newPackage, packageName) { 41645 var jpop = $('#pop-navigate-to-upgrade'); 41646 var jsonCSS = { "padding": "12px 4px 12px 8px", "letter-spacing": "2px", "line-height": "180%", "text-align": "center", "color": "white" }; 41647 41648 jpop.find('#pop-note').html('Navigating to package change profile page...').css(jsonCSS); 41649 jpop.bsModal(); 41650 41651 setTimeout(function() { 41652 document.location = GLO.Link.WebsiteDomain + 'provider/profile/6?package=display'; 41653 }, 400); 41654 } 41655 41656 function _ccIsPopulated(newPackage, packageName) { 41657 var j = $('#wiz6-creditcard'); 41658 var fieldId, missingField = null; 41659 41660 if (j.length === 0) { 41661 _navigateToPackageProfile(newPackage, packageName); 41662 return false; 41663 } 41664 41665 if (UTIL.isEmpty(j.find('#Card_Type_cd').val())) { 41666 missingField = SA.Resource.CardType; 41667 fieldId = 'Card_Type_cd'; 41668 } else if (UTIL.isEmpty(j.find('#Card_Number_vc').val())) { 41669 missingField = SA.Resource.CardNumber; 41670 fieldId = 'Card_Number_vc'; 41671 } else if (UTIL.isEmpty(j.find('#Expiration_Month_sr').val())) { 41672 missingField = SA.Resource.ExpirationMonth; 41673 fieldId = 'Expiration_Month_sr'; 41674 } else if (UTIL.isEmpty(j.find('#Expiration_Year_sr').val())) { 41675 missingField = SA.Resource.ExpirationYear; 41676 fieldId = 'Expiration_Year_sr'; 41677 } 41678 41679 if (missingField !== null) { 41680 var msg = '<div> <h1>' + SA.Resource.PleaseEnterCreditCard + '</h1> <div>' + SA.Resource.PleaseEnterThe + ' ' + missingField + '</div> </div>'; 41681 var fn = function() { $('#wiz6-creditcard').find('#' + fieldId).focus(); }; 41682 41683 var jpop = new GLO.Popup.Warning(msg, fn); 41684 return false; 41685 } else { 41686 return true; 41687 } 41688 } 41689
41690 _conUpgrade.saveConfirm = function(btn, newPackage, Default_Role_Type_cd) { 41691 var packageName = _conUpgrade.getPackageName(newPackage); 41692 var packagePrice = _getPackagePrice(newPackage); 41693 41694 if (GLO.Info.isIosApp) { 41695 SA.App.buySubscriptionStart(newPackage); 41696 41697 if (btn) { 41698 GLO.UI.Form.beginProcessing( $(btn).parent() ); 41699 setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 8000); 41700 } 41701 41702 return; 41703 } else if (!_ccIsPopulated(newPackage, packageName)) { 41704 return; 41705 } else if (newPackage == 4 && UTIL.isEmpty(Default_Role_Type_cd)) { 41706 return SA.Upgrade.personalToBusiness(); 41707 } else if (newPackage == 1 && GLO.Info.providerPackage != 1) { 41708 return SA.Upgrade.businessToPersonal(packageName, packagePrice); 41709 } 41710 41711 var fnCancel = function() { 41712 SA.Upgrade.log(newPackage, 'ignore'); 41713 }; 41714 41715 var msgCSS = 'friendly-msg2'; 41716 41717 if (GLO.Info.isMobile()) { msgCSS = 'friendly-msg'; } 41718 41719 var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ConfirmUpgradeAccount + '</h1>'; 41720 var msg1 = '<div>' + SA.Resource.UpgradeToThe + ' ' + packageName + ' ' + SA.Resource.Package.toLowerCase() + '?</div>'; 41721 var msg2 = '<div style="margin-top: 12px;">' + SA.Resource.NewMonthlyPrice + ' ' + packagePrice + '</div>'; 41722 41723 var jexpire = $('#upgrade-package-trial-expiration-days'); 41724 41725 if (jexpire.length) { 41726 jexpire.find('span').css({ "color": "inherit" }); 41727 msg2 += '<div style="margin-left: -20px; margin-bottom: 20px; font-size: 12px; font-weight: bold;">After Your ' + jexpire.html().replace('*', '') + '</div>'; 41728 } 41729 41730 var htm = '<div id="pop-confirm-upgrade">' + h1 + '<div class="' + msgCSS + '">' + msg1 + msg2 + '</div> </div>'; 41731 41732 var jpop = new GLO.Popup.Confirm(htm, function() { 41733 SA.Upgrade.save(newPackage, null, Default_Role_Type_cd); 41734 }, fnCancel).getPopup(); 41735 41736 jpop.find('.modalClose, .btnCancel > a').click(fnCancel); 41737 41738 GLO.UI.Form.beginProcessing( $(btn).parent() ); 41739 setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 4000); 41740 } 41741 41742 _conUpgrade.save = function(newPackage, jsonReceiptObj, Default_Role_Type_cd) { 41743 41744 //dont process receipt if no provider 41745 if (GLO.Data === undefined || GLO.Data.provider === undefined) { return; } 41746 41747 var url = GLO.Link.Object.Provider.Ajax + "UpgradePackage"; 41748 var ojProcessing, jbtn = $('#upgrade-package').find('.btnUpgrade'); 41749 // var contentType = ''; 41750 if (jsonReceiptObj !== undefined && jsonReceiptObj !== null && jsonReceiptObj.constructor == Object) { 41751 var jd = {}; 41752 jd.package_cd = newPackage; 41753 jd.default_role_type_cd = Default_Role_Type_cd; 41754 jd.receipt_vc = JSON.stringify(jsonReceiptObj); 41755 // contentType = 'application/json'; 41756 url = GLO.Link.Object.Provider.Ajax + "UpgradePackage"; 41757 GLO.Log.insertSimple('Package type from iOS Subscription before UpgradePackage call', newPackage, 'high'); 41758 } else { 41759 var jd = { "package_cd": newPackage, "default_role_type_cd": Default_Role_Type_cd, "receipt_vc": '' }; 41760 } 41761 41762 _addCCtoJson(jd); 41763 41764 if (UTIL.isEmptyObject(jbtn)) { $('.btnUpgrade'); } 41765 41766 if (!UTIL.isEmptyObject(jbtn)) { 41767 GLO.UI.Form.beginProcessing(jbtn); 41768 } else { 41769 var ojProcessing = new GLO.Popup.Processing('Processing Subscription...'); 41770 } 41771 41772 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd}) 41773 .success(function(data, textStatus, jqXHR) { 41774 //GLO.UI.Form.resetProcessing(); 41775 var packageName = _conUpgrade.getPackageName(newPackage); 41776 var payIntermediary = UTIL.coalesceInt($('#Payment_Intermediary_cd').val(), 0); 41777 var url = GLO.Link.WebsiteDomain + 'provider/manage/UpgradePackageSuccess' 41778 41779 //data will be empty string if its just a receipt update without package change 41780 if (data.length > 2) { 41781 new GLO.Popup.Success(SA.Resource.UpgradedTo + ' ' + packageName + ' ' + SA.Resource.Package + '!', 9000); 41782 41783 if (!_conUpgrade.displayMultipleSubscriptionWarning(payIntermediary, url)) { 41784 setTimeout(function() { 41785 document.location = url; 41786 }, 1500); 41787 } 41788 } 41789 }) 41790 .error(function(jqXHR, textStatus, errorThrown) { 41791 //GLO.Popup.Error('An error occurred. Unable to make save your changes at this time.'); 41792 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41793 }); 41794 } 41795 41796 _conUpgrade.displayMultipleSubscriptionWarning = function(payIntermediary, url) { 41797 if (payIntermediary < 10 || payIntermediary > 49) { return false; } 41798 41799 var fn = function() { document.location = url; }
41800 var appleLink = '<a href="https://support.apple.com/en-us/HT202039">'; 41801 var div = '<div style="padding-bottom: 16px;">'; 41802 41803 var msg = div + 'You have signed up for multiple subscriptions with Schedule Anyone using this iTunes account</div>' 41804 + div + 'You can review your iTunes subscriptions, on your iPhone/iPad by going to ' + appleLink + 'Settings > iTunes & the App Store > View Apple ID</a></div>' 41805 + div + 'Here are the full instructions: ' + appleLink + 'support.apple.com</a></div>' 41806 + div + 'Please <a onclick="GLO.Log.openContactSAPopup()">Contact Schedule Anyone</a> if you have any questions</div>'; 41807 41808 var h1 = '<h1 class="friendly-msg4">Verify Schedule Anyone Subscriptions with Apple</h1>'; 41809 var htm = '<div id="pop-warn-multi-subscription">' + h1 + '<div class="friendly-msg4" style="text-align: left; font-size: 14px;">' + msg + '</div> </div>'; 41810 41811 var jpop = new GLO.Popup.Warning(htm, fn).getPopup().css({ "padding-bottom": "8px" }); 41812 var jmsg = jpop.find('.msg').css({ "padding-top": "0", "padding-bottom": "0", "padding-right": "8px" }); 41813 var jdiv1 = jmsg.find('.friendly-msg4 > div:first').css({ "margin-left": "-36px" }); 41814 41815 jpop.find('.pop-icon').css({ "top": "42%" }); 41816 41817 if (innerWidth > 800) { jdiv1.css({ "text-align": "center" }); } 41818 41819 return true; 41820 } 41821 41822 function _addCCtoJson(jd) { 41823 if (GLO.Info.isIosApp) { return; } 41824 41825 var j = $('#wiz6-creditcard'); 41826 41827 jd.card_type_cd = j.find('#Card_Type_cd').val(); 41828 jd.card_number_vc = j.find('#Card_Number_vc').val(); 41829 jd.expiration_month_sr = j.find('#Expiration_Month_sr').val(); 41830 jd.expiration_year_sr = j.find('#Expiration_Year_sr').val(); 41831 } 41832 41833 _conUpgrade.iosInit = function(newPackage) { 41834 var url = GLO.Link.Object.Provider.Ajax + "IosSubscriptionBegin"; 41835 var jd = { "package_cd": newPackage }; 41836 41837 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 41838 .success(function(data, textStatus, jqXHR) { 41839 41840 }) 41841 .error(function(jqXHR, textStatus, errorThrown) { 41842 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41843 }); 41844 } 41845 41846 _conUpgrade.iosFailed = function(newPackage, reason, jsonReceipt) { 41847 var url = GLO.Link.Object.Provider.Ajax + "IosSubscriptionFailed"; 41848 41849 if (!UTIL.isEmpty(jsonReceipt)) { 41850 var jd = jsonReceipt; 41851 jd.receipt_vc = JSON.stringify(jsonReceipt); 41852 jd.package_cd = newPackage; 41853 } else { 41854 var jd = { "package_cd": newPackage }; 41855 } 41856 41857 jd.reason_vc = UTIL.cleanString(reason); 41858 41859 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 41860 .success(function(data, textStatus, jqXHR) { 41861 var msg = SA.Resource.UpgradeTo + ' ' + SA.Upgrade.getPackageName(newPackage) + ' ' + SA.Resource.Failed; 41862 new GLO.Popup.Warning(msg); 41863 GLO.UI.Form.resetProcessing(); 41864 }) 41865 .error(function(jqXHR, textStatus, errorThrown) { 41866 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41867 }); 41868 } 41869 41870 _conUpgrade.log = function(newPackage, action) { 41871 var url = GLO.Link.Object.Provider.Ajax + "UpgradePackageLog?package=" + newPackage + '&action=' + action; 41872 41873 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 41874 .success(function(data, textStatus, jqXHR) { 41875 }) 41876 .error(function(jqXHR, textStatus, errorThrown) { 41877 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 41878 }); 41879 } 41880 41881 return _conUpgrade; 41882})(); 41883 41884SA.ClientServer = (function() { 41885 41886 const _printerLocalApiBase = 'http://localhost:5152/api/Printer/'; 41887 const _pathGetHello = 'hello'; 41888 const _pathGetPrinters = 'getprinters'; 41889 const _pathPostOpenDrawer = 'opendrawer?printerName='; 41890 function _cClientServer() { } 41891 41892 _cClientServer.checkApiStatus = async function() { 41893 41894 try { 41895 var apiEndpoint = _printerLocalApiBase + _pathGetHello;
41896 const response = await fetch(apiEndpoint , { 41897 method: 'GET', 41898 headers: { 41899 'Content-Type': 'application/text' 41900 } 41901 }); 41902 41903 if (response.ok) { 41904 console.log(`SA ClientServer API is running. Status: ${response.status}`); 41905 const data = await response.text(); 41906 console.log(`SA ClientServer API response. Data: ${data}`); 41907 return true; 41908 } else { 41909 GLO.Log.insertSimple('SA ClientServer API returned an error status: ' + response.status, 'SA.ClientServer.checkApiStatus', 'warning'); 41910 console.log(`SA ClientServer API returned an error status. Status: ${response.status}`); 41911 return false; 41912 } 41913 } 41914 catch (error) { 41915 GLO.Log.insertSimple('SA ClientServer API is not reachable due to a network error: ' + error.message, 'SA.ClientServer.checkApiStatus', 'warning'); 41916 console.error('SA ClientServer API is not reachable due to a network error:', error.message); 41917 return false; 41918 } 41919 } 41920 41921 _cClientServer.getLocalPrinters = async function() { 41922 try { 41923 var apiEndpoint = _printerLocalApiBase + _pathGetPrinters; 41924 const response = await fetch(apiEndpoint , { 41925 method: 'GET', 41926 headers: { 41927 'Content-Type': 'application/json' 41928 } 41929 }); 41930 41931 if (response.ok) { 41932 console.log(`SA ClientServer API is running. Status: ${response.status}`); 41933 const data = await response.json(); 41934 console.log(`SA ClientServer API response. Data: ${data}`); 41935 return data; 41936 } 41937 else { 41938 console.log(`SA ClientServer API returned an error status. Status: ${response.status}`); 41939 return []; 41940 } 41941 } 41942 catch (error) { 41943 console.error('SA ClientServer API is not reachable due to a network error:', error.message); 41944 return []; 41945 } 41946 } 41947 41948 _cClientServer.postOpenDrawer = async function(printerName) { 41949 try { 41950 const formData = new FormData(); 41951 formData.append('printerName',printerName); 41952 var apiEndpoint = _printerLocalApiBase + _pathPostOpenDrawer + printerName; 41953 const response = await fetch(apiEndpoint , { 41954 method: 'POST', 41955 headers: { 41956 'Accept': 'application/json' 41957 } 41958 }); 41959 41960 if (response.ok) { 41961 console.log(`SA ClientServer API is running. Status: ${response.status}`); 41962 const data = await response.text(); 41963 console.log(`SA ClientServer API response. Data: ${data}`); 41964 return data; 41965 } 41966 else { 41967 console.log(`SA ClientServer API returned an error status. Status: ${response.status}`); 41968 return []; 41969 } 41970 } 41971 catch (error) { 41972 console.error('SA ClientServer API is not reachable due to a network error:', error.message); 41973 return []; 41974 } 41975 } 41976 41977 _cClientServer.getReceiptPrinterFromCookie = function() { 41978 var name = '_sa_receiptprinter' + "="; 41979 var decodedCookie = decodeURIComponent(document.cookie); 41980 var ca = decodedCookie.split(';'); 41981 for(var i = 0; i <ca.length; i++) { 41982 var c = ca[i]; 41983 while (c.charAt(0) == ' ') { 41984 c = c.substring(1); 41985 } 41986 if (c.indexOf(name) == 0) { 41987 return c.substring(name.length, c.length); 41988 } 41989 } 41990 return ""; 41991 } 41992 41993 return _cClientServer; 41994})(); 41995 41996SA.Profile.OnlineBooking = (function() { 41997 var _autoSaveOnlineBkgTimeout, _autoSaveOnlineBkgInProgress = false, _isNoteChange = false, _isRequireDepositChange = false; 41998 41999 function _conOnlineBkg() { } 42000 42001 _conOnlineBkg.init = function() { 42002 var tbl = $('#config-client-pay-online #service-group-list'); 42003 UI.initTableSorter(tbl); 42004 tbl.find('th:first-child').click(); 42005 42006 var tr = tbl.find('tr'); 42007 42008 for (var i=0; i < tr.length; i++) { 42009 var row = tr.eq(i); 42010 _displayAmount(row); 42011 } 42012 42013 tr.find('.client_pay_type_sr').keyup(SA.Profile.OnlineBooking.changeRequiredAmount); 42014 42015 if ($('#warn-no-merchant-account').length > 0) { 42016 _displayNoMerchantPopup(); 42017 } 42018 42019 $('#config-client-payment-group-booking').find('input').keyup(SA.Profile.OnlineBooking.changeRequiredAmount) 42020 42021 _iniUrl(); 42022 } 42023 function _iniUrl() { 42024 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 42025 42026 if (!UTIL.isEmpty(highlight)) { 42027 var jhigh = $('#' + highlight); 42028 42029 if (jhigh.length) { 42030 UI.highlight(jhigh, 100, 9500, true); 42031 } 42032 } 42033 } 42034 42035 function _displayNoMerchantPopup() { 42036 var msg = 'To Require Payment, Deposit, and/or Card on File with Online Booking'; 42037 var btnAddMerchant = '<span class="btnAdd">
42037<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></span>'; 42038 var htm = '<div id="warn-no-merchant-account">' + msg + ' ' + btnAddMerchant + '</div>'; 42039 } 42040 42041 _conOnlineBkg.requestAddMerchant = function() { 42042 var url = GLO.Link.Page.Provider.Home + 'manage/RequestAddMerchant'; 42043 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 42044 .success(function (data, textStatus, jqXHR) { 42045 var h1 = 'Add Merchant Account'; 42046 var htm = '<div id="pop-request-merchant">We will give you a call within 24 hours to answer all your questions and help you setup a merchant account</div>'; 42047 42048 GLO.Popup.Success.open(htm, h1); 42049 }) 42050 .error(function (jqXHR, textStatus, errorThrown) { 42051 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 42052 }); 42053 } 42054 42055 function _displayAmount(row) { 42056 var cptype = UTIL.coalesceInt(row.find('.client_pay_type_cd').val(), 0); 42057 42058 if (cptype > 0 && cptype < 50) { 42059 if (cptype === 1 || cptype === 11 || cptype === 30 || cptype === 31) { 42060 row.find('.dollar-sign').addClass('not-displayed'); 42061 row.find('.percent-sign').removeClass('not-displayed'); 42062 } else if (cptype === 2 || cptype === 12) { 42063 row.find('.percent-sign').addClass('not-displayed'); 42064 row.find('.dollar-sign').removeClass('not-displayed'); 42065 } 42066 42067 row.find('.client-pay-type-amount').removeClass('not-displayed'); 42068 } else { 42069 row.find('.client-pay-type-amount').addClass('not-displayed'); 42070 } 42071 } 42072 42073 _conOnlineBkg.changeRequiredAmount = function() { 42074 var jthis = $(this); 42075 var id = jthis.attr('id'); 42076 var tr = jthis.closest('tr') 42077 var jamt = tr.find('.client_pay_type_sr'); 42078 42079 if (this.value != jamt.attr('original_amount_sr')) { 42080 _isRequireDepositChange = (id == 'Client_Pay_Require_Deposit_mn' || id == 'Client_Pay_Require_Deposit_pct'); 42081 _beginSave(tr); 42082 } 42083 } 42084 42085 _conOnlineBkg.changeType = function(element) { 42086 var row = $(element).closest('tr'); 42087 _displayAmount(row); 42088 _beginSave(row); 42089 } 42090 42091 _conOnlineBkg.changeNote = function(element) { 42092 $(element).addClass('has-change'); 42093 _isNoteChange = true; 42094 _beginSave(); 42095 } 42096 42097 function _beginSave(tr) { 42098 if (tr && tr.length) { 42099 tr.addClass('has-change'); 42100 } 42101 42102 clearTimeout(_autoSaveOnlineBkgTimeout); 42103 _autoSaveOnlineBkgTimeout = setTimeout(SA.Profile.OnlineBooking.saveConfig, 2400); 42104 } 42105 42106 _conOnlineBkg.saveAllowPayFullAmount = function(checkbox) { 42107 var url = url = GLO.Link.Page.Provider.Home + 'manage/ClientPayAllowFullPayment?isAllow=' + checkbox.checked; 42108 42109 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 42110 .success(function (data, textStatus, jqXHR) { 42111 GLO.Popup.Success.open('Allow Client to Pay Full Amount when Booking Online = ' + checkbox.checked, 'Change Saved'); 42112 }) 42113 .error(function (jqXHR, textStatus, errorThrown) { 42114 var test = 123; 42115 }); 42116 } 42117 _conOnlineBkg.saveConfig = function() { 42118 if (_autoSaveOnlineBkgInProgress) { 42119 _autoSaveOnlineBkgTimeout = setTimeout(SA.Profile.OnlineBooking.saveConfig, 2400); 42120 return; 42121 } 42122 42123 var j = $('#config-client-pay-online'); 42124 var tr = j.find('#service-group-list tr.has-change'); 42125 42126 if (!_isNoteChange && !_isRequireDepositChange && tr.length === 0) { return; } 42127 _autoSaveOnlineBkgInProgress = true; 42128 42129 tr.removeClass('has-change').addClass('processing-change'); 42130 var xml = '', note = '', url = GLO.Link.Page.Provider.Home + 'manage/ClientPayOnlineUpdate'; 42131 42132 for (var i=0; i < tr.length; i++) { 42133 var amt = '', row = tr.eq(i); 42134 var sgid = row.attr('service_group_id'); 42135 var cptype = row.find('.client_pay_type_cd').val(); 42136 var jamt = row.find('.client_pay_type_sr'); 42137 42138 if (cptype > 0 && cptype < 90) { amt = jamt.val(); } 42139 42140 jamt.attr('original_amount_sr', jamt.val()); 42141 42142 xml += '<li service_group_id="' + sgid + '" client_pay_type_cd="' + cptype + '" client_pay_type_sr="' + amt + '"/>'; 42143 } 42144 42145 if (_isNoteChange) {
42146 var jnote = j.find('#Client_Pay_Note_vc').removeClass('has-change').addClass('processing-change'); 42147 note = UTIL.htmlEncode(jnote.val()); 42148 } 42149 42150 xml = UTIL.htmlEncode('<ul>' + xml + '</ul>'); 42151 //GLO.UI.Form.beginProcessing( j.find('.btnSave') ); 42152 42153 var requireDepositAmount = $.trim(j.find('#Client_Pay_Require_Deposit_mn').val()).replace(',', ''); 42154 var requireDepositPercent = j.find('#Client_Pay_Require_Deposit_pct').val(); 42155 42156 var jd = { "input_xml": xml, "client_pay_note_vc": note, "is_note_update_fl": _isNoteChange 42157 , "client_pay_require_deposit_mn": requireDepositAmount, "client_pay_require_deposit_pct": requireDepositPercent }; 42158 42159 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 42160 .success(function (data, textStatus, jqXHR) { 42161 tr.removeClass('processing-change'); 42162 $('#Client_Pay_Note_vc.processing-change').removeClass('processing-change'); 42163 42164 _isNoteChange = _isRequireDepositChange = _autoSaveOnlineBkgInProgress = false; 42165 new GLO.Popup.Success('Changes Saved'); 42166 }) 42167 .error(function (jqXHR, textStatus, errorThrown) { 42168 tr.removeClass('processing-change').addClass('has-change'); 42169 _autoSaveOnlineBkgInProgress = false; 42170 }); 42171 } 42172 42173 return _conOnlineBkg; 42174})(); 42175 42176 42177SA.Profile.Payment = (function() { 42178 function _cProfilePayment() { } 42179 var _jpopSetupTax; 42180 var _jpopSetupTipPercents; 42181 var _jpopSetupConfirmationText; 42182 42183 _cProfilePayment.openEditTax = function() { 42184 if (UTIL.isEmpty(_jpopSetupTax)) { 42185 _jpopSetupTax = $('#pop-tax-setup').outerHTML(); 42186 $('#pop-tax-setup').remove(); 42187 } 42188 42189 var jpop = GLO.Popup.Custom.openSimple(_jpopSetupTax, 'Tax Rate', SA.Profile.Payment.saveEditTax); 42190 42191 } 42192 _cProfilePayment.saveEditTax = function() { 42193 var url = GLO.Link.Page.Provider.Home + 'manage/SaveTax'; 42194 var jpop = $('#pop-tax-setup').closest('.glopop'); 42195 var ptax = jpop.find('#Inventory_Tax_Rate_pct').val(), stax = jpop.find('#Service_Tax_Rate_pct').val(), isTaxTip = jpop.find('#Tax_Tips_fl').prop('checked'); 42196 var jd = { "inventory_tax_rate_pct": ptax, "service_tax_rate_pct": stax, "tax_tips_fl": isTaxTip }; 42197 42198 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 42199 42200 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 42201 .success(function (data, textStatus, jqXHR) { 42202 var jhtm = $(_jpopSetupTax); //= update popup html. 42203 jhtm.find('#Inventory_Tax_Rate_pct').attr('value', ptax) 42204 jhtm.find('#Service_Tax_Rate_pct').attr('value', stax) 42205 42206 if (isTaxTip) { 42207 jhtm.find('#Tax_Tips_fl').attr('checked', 'checked'); 42208 } else { 42209 jhtm.find('#Tax_Tips_fl').removeAttr('checked'); 42210 } 42211 42212 _jpopSetupTax = jhtm.outerHTML(); 42213 42214 GLO.serviceTax = UTIL.coalesceFloat(stax); 42215 GLO.hasTaxOnTips = isTaxTip; 42216 42217 GLO.Popup.close(jpop); 42218 GLO.Popup.Success.open('Tax Rates Saved', 'Changes Saved'); 42219 }) 42220 .error(function (jqXHR, textStatus, errorThrown) { 42221 GLO.UI.Form.resetProcessing(); 42222 GLO.Popup.close(jpop); 42223 }); 42224 } 42225 42226 _cProfilePayment.changeDeviceCardReader = function(element, event) { 42227 //var expireDate = new Date(); 42228 //expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 5)); 42229 //$.cookies.set('card_reader', element.value, { "expiresAt": expireDate }); 42230 UTIL.setCookie('card_reader', element.value); 42231 } 42232 _cProfilePayment.changeDeviceCardAddress = function(element, event) { 42233 //var expireDate = new Date(); 42234 //expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 5)); 42235 //$.cookies.set('card_reader_address', element.value, { "expiresAt": expireDate }); 42236 UTIL.setCookie('card_reader_address', element.value); 42237 } 42238 _cProfilePayment.displayMerchantAccountRequired = function(msg) { 42239 var btn = '<span class="btnAdd" style="position: absolute; left: 0; margin-top: 2px;">
42239<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></span>'; 42240 var htm = '<p style="margin-bottom: 16px;">' + msg + '</p>'; 42241 42242 var jpop = GLO.Popup.Warning.open(htm, 'Merchant Account Required').getPopup().attr('id', 'pop-warn-change-auto-receipt'); 42243 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 42244 42245 jbtns.prepend(btn); 42246 jbtns.find('.btnOk > a').text('Close').css({ "display": "block" }); 42247 } 42248 _cProfilePayment.changeNonCCPayment = function(element, event) { 42249 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 42250 42251 if (mt > 79) { 42252 var msg = 'To Automate Receipts Must Setup Merchant Account in ' + GLO.Info.getScheduleAnyoneHtm(); 42253 _cProfilePayment.displayMerchantAccountRequired(msg); 42254 element.value = 0; //= reset to 'Do Nothing' 42255 } 42256 } 42257 _cProfilePayment.changeAutoReceipt = function(element, event) { 42258 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99); 42259 42260 if (mt > 79) { 42261 var msg = 'To Automate Credit Card Receipts Must Setup Merchant Account to Process Credit Cards in ' + GLO.Info.getScheduleAnyoneHtm(); 42262 _cProfilePayment.displayMerchantAccountRequired(msg); 42263 42264 element.value = 3; //= reset to 'Print Receipt' 42265 } else if (element.value == 2) { 42266 var msg = 'Text Receipts cost 1 cent per message'; 42267 GLO.Popup.Info.open(msg, 'Text Receipt'); 42268 } 42269 42270 GLO.Provider.Advanced.saveField(element, event); 42271 } 42272 42273 _cProfilePayment.changeDeviceTipConfig = function() { 42274 var j = $('#bolt-tip-percent-setup'); 42275 42276 if (j.find('#Enable_Bolt_Tip_fl').prop('checked')) { 42277 $('#tipConfigFieldset').prop('disabled',false); 42278 $('#tipPercentsFieldset').prop('disabled',false); 42279 $('#tipCalculationFieldset').prop('disabled',false); 42280 $('#Tip_Percent_1').val('15'); 42281 $('#Tip_Percent_2').val('20'); 42282 $('#Tip_Percent_3').val('25'); 42283 } else { 42284 $('#tipConfigFieldset').prop('disabled',true); 42285 $('#tipPercentsFieldset').prop('disabled',true); 42286 $('#tipCalculationFieldset').prop('disabled',true); 42287 } 42288 } 42289 42290 _cProfilePayment.changeDeviceGetConfirmationConfig = function() { 42291 var j = $('#bolt-get-confirmation-setup'); 42292 42293 if (j.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked')) { 42294 42295 $('#getConfirmationFieldset').prop('disabled',false); 42296 42297 } else { 42298 $('#getConfirmationFieldset').prop('disabled',true); 42299 42300 } 42301 } 42302 42303 _cProfilePayment.openTipPercentConfig = function(mId) { 42304 if (UTIL.isEmpty(_jpopSetupTipPercents)) { 42305 _jpopSetupTipPercents = $('#bolt-tip-percent-setup').outerHTML(); 42306 $('#bolt-tip-percent-setup').remove(); 42307 } 42308 42309 var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetTipPercents/' + mId; 42310 var fnYes = function () { return SA.Profile.Payment.saveTipPercents(mId); }; 42311 42312 var ojpop = GLO.Popup.Custom.openSimple(_jpopSetupTipPercents, 'Tip Setup', fnYes, null, true); 42313 ojpop.getPopup().find('#Split_Tip_cd').val(GLO.Data.provider.split_tip_cd); 42314 42315 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 42316 .success(function(data, textStatus, jqXHR) { 42317 window.onbeforeunload = null; 42318 // GLO.UI.Form.resetProcessing(); 42319 var jsonMR = JSON.stringify(data); 42320 42321 if (data.TipEnabled) { 42322 $('#Enable_Bolt_Tip_fl').attr('checked','checked'); 42323 $('#Tip_Percent_1').val(data.Tip1Percent); 42324 $('#Tip_Percent_2').val(data.Tip2Percent); 42325 $('#Tip_Percent_3').val(data.Tip3Percent); 42326 42327 if (data.TipMode == 0) { 42328 //percent 42329 $('#tip-by-amount').removeAttr('checked'); 42330 $('#tip-by-percent').attr('checked','checked'); 42331 $('#tipPercentsFieldset').removeClass('hide'); 42332 } else { 42333 //amount 42334 $('#tip-by-amount').attr('checked','checked'); 42335 $('#tip-by-percent').removeAttr('checked'); 42336 $('#tipPercentsFieldset').addClass('hide'); 42337 } 42338 42339 if (data.UseListPrice) { 42340 $('#Enable_Bolt_Tip_On_List_Price_fl').attr('checked','checked'); 42341 } 42342 } 42343 42344 ojpop.realign(); 42345 }) 42346 .error(function(jqXHR, textStatus, errorThrown) { 42347 GLO.UI.Form.resetProcessing();
42348 new GLO.Popup.Error('Unable to get Tip Settings for device', 'Changes Not Saved'); 42349 }); 42350 } 42351 42352 42353 _cProfilePayment.openBoltGetConfirmationConfig = function(mId) { 42354 if (UTIL.isEmpty(_jpopSetupConfirmationText)) { 42355 _jpopSetupConfirmationText = $('#bolt-get-confirmation-setup').outerHTML(); 42356 $('#bolt-get-confirmation-setup').remove(); 42357 } 42358 42359 var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetConfirmationSettings/' + mId; 42360 42361 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 42362 .success(function(data, textStatus, jqXHR) { 42363 window.onbeforeunload = null; 42364 // GLO.UI.Form.resetProcessing(); 42365 var jsonMR = JSON.stringify(data); 42366 if (data.GetConfirmationEnabled) { 42367 $('#Enable_Bolt_Get_Confirmation_fl').attr('checked','checked'); 42368 $('#Get_Confirmation_Text_vc').val(data.ConfirmationPromptText); 42369 $('#Get_Confirmation_Text_vc').keyup(); 42370 42371 } 42372 }) 42373 .error(function(jqXHR, textStatus, errorThrown) { 42374 GLO.UI.Form.resetProcessing(); 42375 new GLO.Popup.Error('Unable to get Confirmation Settings for device'); 42376 }); 42377 42378 var jpop = GLO.Popup.Custom.openSimple(_jpopSetupConfirmationText, 'Ask Client a question on Clover', function () { return SA.Profile.Payment.saveGetConfirmationText(mId); }); 42379 42380 //character count display for clover confirmation text 42381 $('#Get_Confirmation_Text_vc').keyup(function() { 42382 42383 var characterCount = $(this).val().length, 42384 current = $('#current'), 42385 maximum = $('#maximum'), 42386 theCount = $('#the-count'); 42387 42388 current.text(characterCount); 42389 42390 //scrolling needed after 241 characters on mini 42391 if (characterCount >= 241) { 42392 maximum.css('color', '#8f0001'); 42393 current.css('color', '#8f0001'); 42394 theCount.css('font-weight','bold'); 42395 } else { 42396 current.css('color', '#666'); 42397 maximum.css('color','#666'); 42398 theCount.css('font-weight','normal'); 42399 } 42400 42401 var initVal = $(this).val(); 42402 outputVal = initVal.replace(/[^ \+-_\*\$(\r\n|\r|\n)0-9a-zA-Z\?]/g,""); 42403 if (initVal != outputVal) { 42404 $(this).val(outputVal); 42405 } 42406 }); 42407 42408 $('#Get_Confirmation_Text_vc').blur(function() { 42409 var initVal = $(this).val(); 42410 outputVal = initVal.replace(/[^ \+-_\*\$(\r\n|\r|\n)0-9a-zA-Z\?]/g,""); 42411 if (initVal != outputVal) { 42412 $(this).val(outputVal); 42413 } 42414 }); 42415 42416 } 42417 42418 _cProfilePayment.openHelpConnectDevice = function() { 42419 var urlHelp = 'https://ScheduleAnyone.notion.site/Clover-Troubleshooting-Connection-Issue-2a0dbd7c625041b4bdca966bd6934720'; 42420 var aHelp = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlHelp + '\', this, event, true)">Troubleshoot Connection Issue</a>'; 42421 var checkbox = '<b class="checkmark-icon" title="checkbox"></b>'; 42422 42423 var msg1 = '<p>Indicates the Clover <i class="narrow-text">(or other payment device)</i> is connected to the Fiserv payment network</p>'; 42424 var msg2 = '<p style="letter-spacing: 0;">If there is no ' + checkbox + ' then the Clover needs to be <b class="narrow-text">Activated</b> or there is a <b class="narrow-text">Connection Issue</b></p>'; 42425 var msg3 = '<p>Go here to ' + aHelp + '</p>'; 42426 var msg4 = '<p> </p>'; 42427 42428 var htm = '<div id="pop-help-connect-pay-device" style="padding-left: 12px; padding-right: 6px; ">' + msg1 + msg2 + msg3 + msg4 + '</div>'; 42429 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Is Payment Device Connected?', null, null, true); 42430 var jpop = ojpop.getPopup(); 42431 42432 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 42433 GLO.Popup.Custom.singleButton(jpop); 42434 ojpop.realign(); 42435 } 42436 42437 _cProfilePayment.openHelpTipAmount = function() { 42438 var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;'; 42439 var msg1 = '<p style="' + css1 + '">Clover can be setup to show client tip options by <b class="narrow-text">Percent</b> or <b class="narrow-text">Dollar Amount</b></p>'; 42440 var pctCustom = '<i class="narrow-text">(client still has option to enter dollar amount by pressing <b class="narrow-text">Custom Tip</b> button)</i>'; 42441 42442 var hPct = '<h3>Percentage</h3>'; 42443 var msgPct = '<p> Clover device displays easy percent tip buttons' + pctCustom + '</p>'; 42444 var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-percent.png" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42445 42446 var hDollar = '<h3>Dollar Amount</h3>'; 42447 var msgDollar = '<p>Clover device prompts client to enter dollar amount</p>'; 42448 var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-dollar-amount.png" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42449 42450 var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>'; 42451 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Tip By Percent or Dollar Amount', null, null, true); 42452 var jpop = ojpop.getPopup(); 42453 42454 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 42455 GLO.Popup.Custom.singleButton(jpop); 42456 ojpop.realign(); 42457 42458 if (GLO.Info.isMobile(true)) { 42459 setTimeout(function() { ojpop.realign(); }, 900); 42460 } else { 42461 jpop.css({ "top": "40px" }); 42462 } 42463 } 42464 42465 _cProfilePayment.openHelpTipCalculation = function() { 42466 var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;'; 42467 var label = '<b class="narrow-text">Ticket Service Price Only</b>' 42468 var arrow = '<b class="arrow-right">➜</b>'; 42469 42470 var msg1 = '<p style="' + css1 + '">Enabling tip calculation based on ' + label + ' displays tip percent suggestions based on only the service price, does not include: ' 42471 + 'any products and is before discounts and add-on fees are applied (if any)</p>'; 42472 var msg2 = '<p>We suggest enabling this setting, if you run many discounts or promotions ' + arrow + ' this helps staff increase their tip income!</p>'; 42473 42474 var pctCustom = '<i class="narrow-text">(enable this setting if you run a lot of discounts or promotions)</i>'; 42475 42476 var hTicket = '<h4>Example ticket with discounts, taxes and fees</h4>'; 42477 var msgTicket = '<p>See Clover tip suggestions below without and with ticket enabled.</p>'; 42478 var imgTicket = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-calculation-ticket.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42479 42480 var hPct = '<h3>Tip Calculation with ' + label + ' <b>NOT</b> Enabled</h3>'; 42481 var msgPct = '<p> Clover tip suggestions are based on amount after discounts, gift cards, etc. resulting in lower tip amount</p>'; 42482 var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-suggestions-with-ticket-list-price-disabled.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42483 42484 var hDollar = '<h3>With ' + label + ' <b>Enabled</b></h3>'; 42485 var msgDollar = '<p>Clover tip suggestions are based on original ticket amount resulting in higher tip amount</p>'; 42486 var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-suggestions-with-ticket-list-price-en
42486abled.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42487 42488 var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hTicket + msgTicket + imgTicket + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>'; 42489 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Tip Suggestions on Clover', null, null, true); 42490 var jpop = ojpop.getPopup(); 42491 42492 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 42493 GLO.Popup.Custom.singleButton(jpop); 42494 ojpop.realign(); 42495 42496 if (GLO.Info.isMobile(true)) { 42497 setTimeout(function() { ojpop.realign(); }, 900); 42498 } else { 42499 jpop.css({ "top": "40px" }); 42500 } 42501 } 42502 42503 _cProfilePayment.openHelpSplitTip = function() { 42504 var msg1 = '<p style="margin: 0; margin-top: 8px; text-align: center;">By default, set how to Split Tip on Ticket between Staff</p>'; 42505 var msg2 = '<p class="narrow-text" style="text-align: center;">(the tip on any ticket can be changed as needed)</p>'; 42506 42507 var list = '', jSplitOptions = $('#split-tip-options #Split_Tip_cd').find('option'); 42508 42509 for (var i=0; i < jSplitOptions.length; i++) { 42510 var label = '<h5>' + jSplitOptions.eq(i).text().replace('(default)', 'Default') + '</h5>'; 42511 //var description = '<p style="margin-bottom: 8px;">' + jSplitOptions.eq(i).attr('title').replace(' | ', '<br/>') + '</p>'; 42512 var title = jSplitOptions.eq(i).attr('title') 42513 var description = GLO.Report.CellSummary.getCellDescription(title); 42514 42515 list += '<li>' + label + description + '</li>'; 42516 } 42517 42518 list = '<ul>' + list + '</ul>'; 42519 var disclaimer = _getSplitTipDisclaimer(); 42520 var htm = '<div id="pop-help-tip-split">' + msg1 + msg2 + list + disclaimer + '</div>'; 42521 var ojpop = GLO.Popup.Custom.openSimple(htm, 'How Split Tip on Ticket Between Staff', null, null, true); 42522 var jpop = ojpop.getPopup(); 42523 42524 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 42525 GLO.Popup.Custom.singleButton(jpop); 42526 } 42527 function _getSplitTipDisclaimer() { 42528 if (GLO.Data.provider.merchants && GLO.Data.provider.merchants.length > 1) { 42529 return '<div id="pop-help-tip-split-disclaimer" class="narrow-text" style="font-style: italic;">' 42530 + '<p><b>Split Tip = "evenly"</b>, is not supported on tickets with multiple merchant accounts (when the client tips on the Clover device)</p>' 42531 + '<p>For these tickets the tip will be split by <b>Total Price</b> (default) or <b>Service Price</b></p>' 42532 + '</div>'; 42533 } 42534 42535 return ''; 42536 } 42537 42538 _cProfilePayment.saveTipPercents = function(mId) { 42539 var url = GLO.Link.WebsiteDomain + 'api/Bolt/SaveTipPercents/' + mId; 42540 var jpop = $('#bolt-tip-percent-setup').closest('.glopop'); 42541 var tip1 = jpop.find('#Tip_Percent_1').val(), tip2 = jpop.find('#Tip_Percent_2').val(), tip3 = jpop.find('#Tip_Percent_3').val(); 42542 var enableTipOnDevice = jpop.find('#Enable_Bolt_Tip_fl').prop('checked'); 42543 var tipMode = jpop.find("input[name='tip-config']:checked").val(); 42544 var splitTip = jpop.find('#Split_Tip_cd').val(); 42545 var useListPriceForTipCalc = jpop.find('#Enable_Bolt_Tip_On_List_Price_fl').prop('checked'); 42546 42547 var jd = { "deviceTipSettings": {"tipEnabled": enableTipOnDevice, "tipMode": tipMode, "tip1percent": tip1, "tip2percent": tip2, "tip3percent": tip3, "splitTip": splitTip, "useListPrice": useListPriceForTipCalc }}; 42548 42549 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 42550 42551 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 42552 .success(function (data, textStatus, jqXHR) { 42553 if ($(data).hasClass('error')) { 42554 GLO.UI.Form.resetProcessing(); 42555 GLO.Popup.Warning.open(data, 'Unable to Save'); 42556 } else { 42557 GLO.Popup.close(jpop); 42558 GLO.Popup.Success.open('Clover Tip Settings Updated', 'Changes Saved'); 42559 GLO.Data.provider.split_tip_cd = splitTip; 42560 } 42561 }) 42562 .error(function (jqXHR, textStatus, errorThrown) { 42563 GLO.UI.Form.resetProcessing(); 42564 GLO.Popup.close(jpop); 42565 }); 42566 } 42567 42568 _cProfilePayment.saveGetConfirmationText = function(mId) { 42569 var url = GLO.Link.WebsiteDomain + 'api/Bolt/SaveGetConfirmationText/' + mId; 42570 var jpop = $('#bolt-get-confirmation-setup').closest('.glopop'); 42571 var getConfirmationText = jpop.find('#Get_Confirmation_Text_vc').val(); 42572 var enableGetConfirmationOnDevice = jpop.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked'); 42573 42574 42575 var jd = { "deviceConfirmationSettings": {"getConfirmationEnabled": enableGetConfirmationOnDevice, "confirmationPromptText": getConfirmationText }}; 42576 42577 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 42578
42579 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 42580 .success(function (data, textStatus, jqXHR) { 42581 if ($(data).hasClass('error')) { 42582 GLO.UI.Form.resetProcessing(); 42583 GLO.Popup.Warning.open(data, 'Unable to Save Text'); 42584 } else { 42585 GLO.Popup.close(jpop); 42586 GLO.Popup.Success.open('Clover Settings Updated', 'Changes Saved'); 42587 } 42588 }) 42589 .error(function (jqXHR, textStatus, errorThrown) { 42590 GLO.UI.Form.resetProcessing(); 42591 GLO.Popup.close(jpop); 42592 }); 42593 } 42594 42595 _cProfilePayment.LogConfirmationToApptUpdateLog = function(scheduleMultiId) { 42596 var url = GLO.Link.WebsiteDomain + 'schedule/SaveConfirmationToApptUpdates?smid=' + scheduleMultiId; 42597 // var jpop = $('#bolt-get-confirmation-setup').closest('.glopop'); 42598 // var getConfirmationText = jpop.find('#Get_Confirmation_Text_vc').val(); 42599 // var enableGetConfirmationOnDevice = jpop.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked'); 42600 42601 // GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 42602 42603 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: null }) 42604 .success(function (data, textStatus, jqXHR) { 42605 if ($(data).hasClass('error')) { 42606 GLO.UI.Form.resetProcessing(); 42607 GLO.Popup.Warning.open(data, 'Unable to Save Confirmation to Appointment Updates'); 42608 } else { 42609 // GLO.Popup.close(jpop); 42610 GLO.Popup.Success.open('Appointment Updated', 'Changes Saved'); 42611 } 42612 }) 42613 .error(function (jqXHR, textStatus, errorThrown) { 42614 GLO.UI.Form.resetProcessing(); 42615 // GLO.Popup.close(jpop); 42616 }); 42617 } 42618 42619 42620 _cProfilePayment.openHelpCloverConfirmation = function() { 42621 var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;'; 42622 var msg1 = '<p style="' + css1 + '">Clover can be setup to ask client to confirm a <b class="narrow-text">Question</b> or a <b class="narrow-text">Policy</b></p>'; 42623 var pctCustom = '<i class="narrow-text">(if client does not confirm message payment will be canceled.)</i>'; 42624 42625 var hPct = '<h3>Question or Message on Clover</h3>'; 42626 var msgPct = '<p> Clover can display a question or message like policy text and require client to confirm it.' + pctCustom + '</p>'; 42627 var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/read-confirmation.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42628 42629 var hDollar = '<h3>Client Confirmation</h3>'; 42630 var msgDollar = '<p>Client confirmation gets recorded in the appointment update history.</p>'; 42631 var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/confirmation-log.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>'; 42632 42633 var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>'; 42634 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Ask a question on Clover', null, null, true); 42635 var jpop = ojpop.getPopup(); 42636 42637 jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" }); 42638 GLO.Popup.Custom.singleButton(jpop); 42639 ojpop.realign(); 42640 42641 if (GLO.Info.isMobile(true)) { 42642 setTimeout(function() { ojpop.realign(); }, 900); 42643 } else { 42644 jpop.css({ "top": "40px" }); 42645 } 42646 } 42647 42648 return _cProfilePayment; 42649})(); 42650 42651SA.Profile.Referral = (function() { 42652 function _cProfileReferral() { } 42653 var _jpopNewReferralForm; 42654 42655 _cProfileReferral.openSubmitNewReferral = function() { 42656 if (UTIL.isEmpty(_jpopNewReferralForm)) { 42657 _jpopNewReferralForm = $('#new-referral-form').outerHTML(); 42658 $('#new-referral-form').remove(); 42659 } 42660 42661 var jpop = GLO.Popup.Custom.openSimple(_jpopNewReferralForm, 'Submit New Referral', function () { return SA.Profile.Referral.saveReferral(); }); 42662 //phone mask for referral phone 42663 UI.phoneMask(jpop.find('#Referral_Phone_vc')); 42664 } 42665 42666 _cProfileReferral.saveReferral = function() { 42667 var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveReferral'; 42668 var jpop = $('#new-referral-form').closest('.glopop'); 42669 //fields 42670 var fname = jpop.find('#Referral_First_Name_vc').val(); 42671 var lname = jpop.find('#Referral_Last_Name_vc').val();
42672 var bizname = jpop.find('#Referral_Business_Name_vc').val(); 42673 var bizsize = jpop.find('#Referral_Business_Size_vc').val(); 42674 var email = UTIL.coalesceString(jpop.find('#Referral_Email_vc').val(),''); 42675 var phone = jpop.find('#Referral_Phone_vc').val(); 42676 var address = UTIL.coalesceString(jpop.find('#Referral_Street_vc').val(),''); 42677 var city = jpop.find('#Referral_City_vc').val(); 42678 var state = $('#Referral_State_cc').val(); 42679 var zip = jpop.find('#Referral_Zip_vc').val(); 42680 var notes = UTIL.coalesceString(jpop.find('#Notes_vc').val(),''); 42681 42682 42683 var jd = { "newReferral": {"FirstName": fname, "LastName": lname, "BusinessName": bizname, 42684 "BusinessSize": bizsize, "Email": email, "Phone": phone, "Address": address, 42685 "City": city, "State": state, "PostalCode": zip, "Notes": notes 42686 }}; 42687 42688 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 42689 42690 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 42691 .success(function (data, textStatus, jqXHR) { 42692 if (data && Object.keys(data).length > 0) { 42693 if (data.status != 'success') { 42694 GLO.UI.Form.resetProcessing(); 42695 GLO.Popup.Warning.open(data.message, 'Unable to Save New Referral. Please try again. Email [email protected]'); 42696 } 42697 else { 42698 GLO.Popup.close(jpop); 42699 GLO.Popup.Success.open('Thank you for your referral', 'New Referral Submitted'); 42700 SA.Profile.Referral.getReferrals(); 42701 } 42702 42703 } else { 42704 GLO.UI.Form.resetProcessing(); 42705 GLO.Popup.Warning.open(data, 'Unable to Save New Referral. Please try again. Email [email protected]'); 42706 } 42707 }) 42708 .error(function (jqXHR, textStatus, errorThrown) { 42709 GLO.UI.Form.resetProcessing(); 42710 GLO.Popup.close(jpop); 42711 }); 42712 } 42713 42714 _cProfileReferral.getReferrals = function() { 42715 42716 var uri = GLO.Link.WebsiteDomain + 'provider/manage/getreferrals'; 42717 42718 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 42719 .done(function(data, textStatus, jqXHR) { 42720 window.onbeforeunload = null; 42721 if(data!=null && data!== '') { 42722 //if data has status property then there was an issue 42723 if (Object.hasOwnProperty('status')) { 42724 if (data.status == 'fail') { 42725 new GLO.Popup.Error('Could not get the referrals - ' + data.message); 42726 } 42727 else { 42728 new GLO.Popup.Error('Could not get the referrals'); 42729 } 42730 } 42731 42732 var referrals = data; 42733 if (referrals.length > 0) { 42734 generateReferralsList(referrals); 42735 } 42736 else { 42737 generateReferralsListEmptyState(); 42738 } 42739 42740 } else { 42741 new GLO.Popup.Error('Could not get the referrals'); 42742 } 42743 }) 42744 .fail(function(jqXHR, textStatus, errorThrown) { 42745 GLO.UI.Form.resetProcessing(); 42746 new GLO.Popup.Error('Could not get the referrals'); 42747 }); 42748 } 42749 42750 _cProfileReferral.shareReferralLinkEmail = function() { 42751 //not implemented 42752 } 42753 42754 _cProfileReferral.shareReferralLinkSms = function() { 42755 var url = GLO.Link.WebsiteDomain + 'message/sharereferralsms'; 42756 42757 var jpop = $('#send-referral-container'); 42758 var jsave = jpop.find('.btnSave'); 42759 GLO.UI.Form.beginProcessing(jsave); 42760 42761 var referralName = UTIL.cleanString(jpop.find('#Send_Referral_Name_vc').val()); 42762 var referralPhone = UTIL.cleanString(jpop.find('#Send_Referral_Phone_vc').val().replace(/\D/g, '')); 42763 42764 if (0 < referralPhone.length && referralPhone.length < 10) { 42765 GLO.Popup.Warning.open(data.message, 'Invalid Phone'); 42766 event.preventDefault(); 42767 return; 42768 } 42769 42770 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { referralShare: { "Name": referralName, "Phone": referralPhone } } }) 42771 .success(function(data, textStatus, jqXHR) { 42772 42773 if (data && Object.keys(data).length > 0) { 42774 if (data.status != 'success') { 42775 GLO.UI.Form.resetProcessing(); 42776 GLO.Popup.Warning.open(data.message, 'Send Referral Error'); 42777 } 42778 else { 42779 GLO.UI.Form.resetProcessing();
42780 GLO.Popup.Success.open('Thank you for spreading the word about us', 'Invitation Sent'); 42781 // SA.Profile.Referral.getReferralShares(); //future 42782 } 42783 42784 } else { 42785 GLO.UI.Form.resetProcessing(); 42786 GLO.Popup.Warning.open(data.message, 'Send Referral Error'); 42787 } 42788 }) 42789 .error(function(jqXHR, textStatus, errorThrown) { 42790 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 42791 }); 42792 } 42793 42794 42795 var generateReferralsList = function(json) { 42796 var deviceCount = 0; 42797 42798 //clear all the rows 42799 $('#referral-table-body').empty(); 42800 42801 if (UTIL.isJson(json)) { //typeof json.length !== 'undefined' 42802 // $('#pax-column-header').addClass('hide'); 42803 $('#referral-column-header').removeClass('hide'); 42804 42805 var referrals = json; 42806 42807 42808 for (var i = 0; i < referrals.length; i++) { //Append each row to html table 42809 42810 var tr = $('<tr/>'); 42811 tr.append('<td class="referral-column-name">' + referrals[i].BusinessName + '</td>'); 42812 tr.append('<td class="referral-column-signup-date">' + ( referrals[i].SignupDateTime == null ? '' : referrals[i].SignupDateTime )+ '</td>'); 42813 tr.append('<td class="referral-column-payout">' + ( referrals[i].NextPayoutDateTime == null ? '' : referrals[i].NextPayoutDateTime ) + '</td>'); 42814 tr.append('<td class="referral-column-bonus">' + ( referrals[i].BonusPayoutDateTime == null ? '' : referrals[i].BonusPayoutDateTime ) + '</td>'); 42815 tr.append('<td class="referral-column-status">' + referrals[i].Status + '</td>'); 42816 $('table#ReferralList').append(tr); 42817 42818 } 42819 42820 42821 UI.initTableSorter($('#report-main table.tablesorter')); 42822 } 42823 42824 } 42825 42826 var generateReferralsListEmptyState = function() { 42827 var tr = $('<tr/>'); 42828 tr.append('<td class="referral-empty-state" colspan="5">' + 'No referrals yet. Click "Submit a Referral" above to submit a referral.' + '</td>'); 42829 $('table#ReferralList').append(tr); 42830 } 42831 42832 42833 42834 return _cProfileReferral; 42835})(); 42836 42837 42838GLO.MyAppts = (function() { 42839 function _constructor(name) { } 42840 _constructor.currentTab = 1; 42841 _constructor.MAX_TAB = 4; 42842 _constructor.isActivityView = false; 42843 42844 _constructor.init = function() { 42845 _constructor.isActivityView = true; 42846 GLO.Info.init(); 42847 42848 //Step I: Setup Tabs 42849 UI.initTableSorter( $('#myAppointments-updates table') ); //= Recent Activity. 42850 UI.initTableSorter( $('#myAppointments-upcoming table') ); //= Upcoming. 42851 GLO.WaitList.init(); 42852 UI.initTableSorter( $('#myOtherEdits table') ); //= Other Edits. 42853 42854 //Step II: Setup Search on each tab 42855 GLO.MyAppts.initSearch('#myAppointments-updates', 7, 0, true); 42856 GLO.MyAppts.initSearch('#myAppointments-upcoming', 0, 7); 42857 GLO.MyAppts.initSearch('#myOtherEdits', 7, 0, true); 42858 42859 //Step III: Display Tabs 42860 $('#displayProfile-Client').addClass('hide'); 42861 $('#searchResults-Client').parent().addClass('hide'); 42862 $('#staff-portal-header').removeClass('hide'); 42863 42864 var initTab = GLO.Uri.url('tab'); 42865 42866 if (!UTIL.isEmpty(initTab)) { 42867 initTab = initTab.toLowerCase(); 42868 42869 if (initTab === 'recent' || initTab == 1) { 42870 initTab = 1; 42871 } else if (initTab === 'upcoming' || initTab == 2) { 42872 initTab = 2; 42873 } else if (initTab === 'other' || initTab == 3) { 42874 initTab = 3; 42875 } else if (initTab === 'wait' || initTab == 4) { 42876 initTab = 4; 42877 42878 if (UTIL.parseBool(GLO.Uri.url('add'))) { 42879 $('#waiting-list-buttons').find('.btnAdd > a').click(); 42880 } 42881 } 42882 } else { 42883 initTab = GLO.MyAppts.currentTab; 42884 } 42885 42886 var mustSearch = GLO.MyAppts.goToTab(initTab, true); 42887 42888 //Step IV: Setup header buttons, Tab/HelpIcon Titles, search f
42888ilter 42889 _addAllToFilter(); 42890 _setupHeader(); 42891 _setTitle(); 42892 42893 $('.appt-list-search:visible').find('.btnSearch > a:visible').click(); //_initUrlAction(mustSearch); 42894 $('#hd-waiting-list').remove(); 42895 GLO.Report.enableFullPageCheck(); 42896 42897 //Step V: Shortcut Keys 42898 $(document).keydown(function(event) { 42899 if (event.ctrlKey) { 42900 switch (event.which) { 42901 case 37: //left arrow key. 42902 GLO.MyAppts.goToTab(--GLO.MyAppts.currentTab); 42903 break; 42904 case 39: //right arrow key. 42905 GLO.MyAppts.goToTab(++GLO.MyAppts.currentTab); 42906 break; 42907 } 42908 } 42909 }); 42910 42911 $(window).bind('keypress', function(event) { 42912 if (event.ctrlKey) { 42913 switch (event.which) { 42914 case 37: //left arrow key. 42915 case 39: //right arrow key. 42916 event.preventDefault(); 42917 } 42918 } 42919 }); 42920 } 42921 42922 function _addAllToFilter() { 42923 if (GLO.Info.isMobile() && GLO.Info.roleType > 199) { 42924 var jfilter = $('#staff-filter'); 42925 42926 if (jfilter.find('option').length > 1) { 42927 var jfirst = jfilter.find('option:first'); 42928 42929 if (UTIL.isEmpty(jfirst.val())) { 42930 jfirst.text(' All').attr('value', 'all'); 42931 } else { 42932 jfilter.prepend('<option value="all"> ALL</option>'); 42933 jfirst = jfilter.find('option:first'); 42934 } 42935 42936 var sfilter = GLO.Uri.url('sfilter'); 42937 var isNotInFilter = (jfilter.find('option[value="' + sfilter + '"]').length === 0); //= can happen when receptionist not assigned to any services. 42938 42939 if (UTIL.coalesce(sfilter, 'all') == 'all' || isNotInFilter) { 42940 jfirst.prop('selected', true); 42941 42942 if (UTIL.coalesce(sfilter, 'all') != 'all') { 42943 GLO.Report.setStaffFilter('all'); 42944 } 42945 } 42946 } 42947 } 42948 } 42949 42950 function _initUrlAction(mustSearch) { 42951 var begin = UTIL.coalesce(GLO.Uri.hash('begin'), GLO.Uri.hash('start')); 42952 var end = GLO.Uri.hash('end'); 42953 var beginEdit = UTIL.coalesce(GLO.Uri.hash('beginEdit'), GLO.Uri.hash('startEdit')); 42954 var endEdit = GLO.Uri.hash('endEdit'); 42955 42956 var cid = GLO.Uri.hash('cid'); 42957 var client = GLO.Uri.hash('client'); 42958 var isBookedByClient = UTIL.parseBool(GLO.Uri.hash('BookedByClient')); 42959 var service = UTIL.cleanString(GLO.Uri.hash('service')).toLowerCase(); 42960 var hasFilter = false; 42961 var jfilter = $('.appt-list-search:visible'); 42962 42963 if (UTIL.isDate(begin)) { 42964 hasFilter = true; 42965 jfilter.find('.Begin_dt').val(begin); 42966 } 42967 42968 if (UTIL.isDate(end)) { 42969 hasFilter = true; 42970 jfilter.find('.End_dt').val(end); 42971 } 42972 42973 if (jfilter.closest('.activity-view-panel').attr('id') == 'myAppointments-updates') { 42974 if (UTIL.isDate(beginEdit)) { 42975 hasFilter = true; 42976 jfilter.find('.Edit_Begin_dt').val(beginEdit); 42977 } 42978 42979 if (UTIL.isDate(endEdit)) { 42980 hasFilter = true; 42981 jfilter.find('.Edit_End_dt').val(endEdit); 42982 } 42983 } 42984 42985 if (!UTIL.isEmpty(cid)) { 42986 hasFilter = true; 42987 var jclient = jfilter.find('.search-Client_id'); 42988 42989 jclient.attr('autoId', cid); 42990 jclient.val(client); 42991 } 42992 42993 if (!UTIL.isEmpty(service)) { 42994 hasFilter = true; 42995 jfilter.find('.Service_Filter').val(service); 42996 } 42997 42998 if (isBookedByClient) { 42999 jfilter.find('.Update_By_Client_fl').prop('checked', true); 43000 } 43001 43002 if (hasFilter) { 43003 jfilter.find('.btnSearch > a:visible').click(); 43004 UI.highlight(jfilter, 800, 6400, true); 43005 } else if (mustSearch) { 43006 jfilter.find('.btnSearch > a:visible').click(); 43007 } 43008 } 43009 43010 function _setupHeader() { 43011 var jHeaderBtns = $('#apptPortal-cal-btns'); 43012 UI.addButtonEffects( jHeaderBtns.find('#calAll-button') ); 43013 jHeaderBtns.find('#calList-button').addClass('ui-state-active'); 43014 43015 UI.addButtonEffects( jHeaderBtns.find('.fc-button-month') ); 43016 UI.addButtonEffects( jHeaderBtns.find('.fc-button-agendaWeek') ); 43017 UI.addButtonEffects( jHeaderBtns.find('.fc-button-agendaDay') ); 43018 43019 if (GLO.Info.isMobile(true)) { 43020 setTimeout( function() { //so overrides style set on _providerLayout.cshtml. 43021 $('#apptPortal-cal-btns').css({ "font-size": "116%" });
43022 //$('#bd').css({ "margin-top": "15px" }); 43023 }, 400); 43024 43025 $('.hasDatepicker').click(function() { 43026 $(this).blur(); 43027 }); 43028 43029 $('.ui-datepicker-next, .ui-datepicker-prev').on('mouseup', function() { 43030 $(document.activeElement).blur(); 43031 }); 43032 43033 //if ($('#hd-mobile').length === 0) { 43034 // $('#easySearch_text').css({ "width": "18.1em" }); //.attr('title', 'Client search by name or phone'); 43035 //} 43036 } else { 43037 //$('#easySearch_text').css({ "width": "17.25em" }); 43038 //$('#easySearch_text').css({ "width": "17em" }); //.attr('title', 'Client search by name or phone'); 43039 } 43040 43041 if ($('#inactiveStaffBar:visible').length > 0 && $('#staffFilter:visible').length > 0) { 43042 var top = 25; 43043 if ( $('.hello-bar-container').length > 0) { top = 50; } 43044 43045 $('#inactiveStaffBar:visible').css({ "top": (top + "px") }); 43046 $('#doc3').css({ "margin-top": (top + 25 + "px") }); 43047 } else if ($('#staffFilter:visible').length > 0) { 43048 var top = 30; 43049 if ( $('.hello-bar-container').length > 0) { top = 58; } 43050 43051 $('#doc3').css({ "margin-top": (top + "px") }); 43052 } 43053 } 43054 43055 function _setTitle() { 43056 GLO.Info.init(); 43057 var sfilter = GLO.Uri.query('sfilter'); 43058 var stitle; 43059 43060 if (UTIL.isEmpty(sfilter)) { 43061 if (GLO.Info.providerPackage == 1) { 43062 stitle = SA.Resource.My.toLowerCase(); 43063 } else if (GLO.Info.roleType > 209) { 43064 stitle = SA.Resource.AnyStaffMembers.toLowerCase(); 43065 } else { 43066 stitle = SA.Resource.My.toLowerCase(); 43067 } 43068 } else if (sfilter.toLowerCase() === 'all') { 43069 stitle = SA.Resource.AnyStaffMembers.toLowerCase(); 43070 } else if (sfilter.indexOf(",") === -1) { 43071 if (sfilter == GLO.Info.getStaffId()) { 43072 stitle = SA.Resource.My.toLowerCase(); 43073 } else { 43074 stitle = $('#sfilter-hello-bar-label').text() 43075 43076 if (UTIL.isEmpty(stitle)) { stitle = $('#staff-filter').find('option:selected').text(); } 43077 43078 stitle += "'s"; 43079 } 43080 } else { 43081 stitle = SA.Resource.SpecifiedStaffMembers.toLowerCase(); 43082 } 43083 43084 var u = stitle.substring(0, 1).toUpperCase() + stitle.substring(1); 43085 43086 if (GLO.Info.roleType > 209) { 43087 var descEdit = SA.Resource.DescendingEdit; 43088 var descRecent = SA.Resource.DescendingRecent; 43089 var descUpcoming = SA.Resource.DescendingUpcoming; 43090 } else { 43091 var descEdit = SA.Resource.DescendingEdit2; 43092 var descRecent = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments; 43093 var descUpcoming = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments; 43094 } 43095 43096 var jtabs = $('#staff-portal-header'); 43097 var jhelpicons = $('.helpIcon2'); 43098 43099 var titleRecent = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments; 43100 jtabs.find("#sfilter-tab-recent").attr("title", titleRecent); 43101 jhelpicons.eq(0).attr('title', titleRecent).attr('alt', descRecent); 43102 43103 var titleUpcoming = u + ' ' + SA.Resource.UpcomingAppointments; 43104 jtabs.find("#sfilter-tab-upcoming").attr("title", titleUpcoming); 43105 jhelpicons.eq(1).attr('title', titleUpcoming).attr('alt', descUpcoming); 43106 43107 var titleEdit = SA.Resource.MyEditsTo + ' ' + stitle + ' ' + SA.Resource.Appointments; 43108 jtabs.find("#sfilter-tab-other-edits").attr("title", titleEdit); 43109 jhelpicons.eq(2).attr('title', titleEdit).attr('alt', descEdit); 43110 43111 var titleWaiting = u + ' ' + SA.Resource.ClientWaitingList.toLowerCase(); 43112 jtabs.find("#sfilter-tab-waiting-list").attr("title", titleWaiting); 43113 jhelpicons.eq(3).attr('title', titleWaiting).attr('alt', titleWaiting); 43114 } 43115 43116 _constructor.removeRecentRow = function(jTR) { 43117 var url = GLO.Link.Object.AppointmentAjax + 'UpdateSimple'; 43118 var dbXml = UTIL.htmlEncode('<tr schedule_id="' + jTR.attr('id').substr(1) + '" update_status_cd="2" input_type_cd="10"/>'); 43119
43120 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { xml: dbXml } }) 43121 .success(function(data, textStatus, jqXHR) { }) 43122 .error(function(jqXHR, textStatus, errorThrown) { }); 43123 } 43124 43125 _constructor.search = function(btn) { 43126 btn = $(btn); 43127 var jSheet = btn.closest('.appt-list-sheet'); 43128 var jResult = jSheet.find('.appt-list-result'); 43129 var jTabBodyId = jSheet.parent().attr('id'); 43130 43131 if (jResult.find('.must-load-data').length === 0) { 43132 jResult.html(''); 43133 } 43134 43135 if (jTabBodyId === 'myAppointments-updates') { 43136 var listType = '1'; 43137 } else if (jTabBodyId === 'myAppointments-upcoming') { 43138 var listType = '2'; 43139 } else if (jTabBodyId === 'myOtherEdits') { 43140 var listType = '3'; 43141 } 43142 43143 var begin = jSheet.find('.Begin_dt').val(); 43144 var end = jSheet.find('.End_dt').val(); 43145 var beginEdit = jSheet.find('.Edit_Begin_dt').val(); 43146 var endEdit = jSheet.find('.Edit_End_dt').val(); 43147 43148 var jclient = jSheet.find('.search-Client_id'); 43149 var cid = '', bookingNumber = $.trim(jSheet.find('.Booking_nr').val()); 43150 var isEditByClient = jSheet.find('.Update_By_Client_fl').prop('checked'); 43151 43152 if (!UTIL.isEmpty(jclient.val())) { //= if client search text box is empty don't include (in case they did search with client, then cleared client name box). 43153 cid = UTIL.cleanString(jclient.attr('autoId')); 43154 } 43155 43156 if (new Date(begin).getTime() > new Date(end).getTime() ) { 43157 new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>'); 43158 return; 43159 } 43160 43161 var rows = UTIL.coalesceString(jSheet.find('.activity-row-count').val(), GLO.Uri.url('rows')); 43162 var searchData = '<tr client_id="' + cid + '" start_dt="' + begin + '" end_dt="' + end + '" edit_start_dt="' + beginEdit + '" edit_end_dt="' + endEdit 43163 + '" booking_vc="' + bookingNumber + '" rows="' + rows + '" list_type_cd="' + listType 43164 + '" staff_id="' + GLO.Uri.query('sfilter') + '" service_filter="' + jSheet.find('.Service_Filter').val() + '" update_by_client_fl="' + isEditByClient + '"/>'; 43165 43166 var dbXml = UTIL.htmlEncode(searchData); 43167 var url = GLO.Link.Object.Provider.ApptList; 43168 GLO.UI.Form.beginProcessing(btn.parent()); 43169 43170 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { xml: dbXml } }) 43171 .success(function(data, textStatus, jqXHR) { 43172 GLO.UI.Form.resetProcessing(); 43173 43174 var jd = $(data); 43175 var jno = jd.find('.noResults'); 43176 43177 if (jno.length > 0) { 43178 jResult.html(jno.outerHTML()).removeClass('hide'); 43179 } else { 43180 jResult.html(jd.find('.tablesorter')).removeClass('hide'); 43181 UI.initTableSorter( $('#' + jSheet.parent().attr('id') + ' table') ); 43182 } 43183 43184 _finishLoadActivityViewData(jResult); 43185 }) 43186 .error(function(jqXHR, textStatus, errorThrown) { 43187 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 43188 }); 43189 } 43190 43191 function _finishLoadActivityViewData(jResult) { 43192 var colSpan = jResult.find('table thead th:visible').length; 43193 jResult.find('table tr.infoRow th').attr('colspan', colSpan); 43194 } 43195 43196 _constructor.goToTab = function(tab, isInit) { 43197 if (tab > _constructor.MAX_TAB) { 43198 tab = 1; 43199 } else if (tab < 1) { 43200 tab = _constructor.MAX_TAB; 43201 } 43202 43203 $('#myAppointments-upcoming').addClass('hide'); 43204 $('#myAppointments-updates').addClass('hide'); 43205 $('#myAppointments-wait').addClass('hide'); 43206 $('#myOtherEdits').addClass('hide'); 43207 43208 if (tab === 1) { 43209 var jvw = $('#myAppointments-updates').removeClass('hide'); 43210 } else if (tab === 2) { 43211 var jvw = $('#myAppointments-upcoming').removeClass('hide'); 43212 } else if (tab === 3) { 43213 var jvw = $('#myOtherEdits').removeClass('hide'); 43214 } else if (tab === 4) { 43215 var jvw = $('#myAppointments-wait'); 43216 var jwaitPop = jvw.closest('.glopop'); 43217 43218 if (jwaitPop.length === 1) { jvw = jwaitPop; } 43219 43220 var h2 = jvw.find('h2'); 43221 43222 if (h2.length === 1) { 43223 jvw.find('#waiting-list-container').css({ "clear": "both" }); 43224 h2.remove(); 43225 jvw.find('#waiting-list-th-note').css({ "width": "500px" }); 43226 //jvw.prepend( jvw.find('#waiting-list-buttons').css({ "padding-top": "20px", "padding-bottom": "50px", "margin-left": "100px" }) ); 43227 } 43228 43229 jvw.removeClass('hide'); 43230 } 43231 43232 var backColor = $('.shadow-content0').css('backgroundColor'); 43233 var oj = $('#staff-portal-header table tr td span b'); 43234 43235 oj.each(function() { 43236 $(this).parent().parent().removeClass('staff-tab').css('backgroundColor', ''); 43237 }); 43238 43239 _constructor.currentTab = tab; 43240 if (tab == 4 && GLO.Info.providerPackage === 1) { tab = 3; } 43241 43242 oj = oj.eq(tab - 1).parent().parent(); 43243 oj.addClass('staff-tab'); 43244 oj.css('backgroundColor', backColor); 43245 43246 if (jvw.find('.must-load-data').length > 0) { 43247 jvw.find('.must-load-data').addClass('loading-data'); //.removeClass('must-load-data'); 43248 43249 if (isInit) { 43250 return true; 43251 } else { 43252 jvw.find('.btnSearch').find('a').click(); 43253 } 43254 } 43255 43256 _changeTabSetHashUriKey(tab); 43257 return false; 43258 } 43259 43260 function _changeTabSetHashUriKey(tab) { 43261 if (!UTIL.isEmpty(GLO.Uri.query('tab'))) { return; } 43262 43263 GLO.Uri.hash('tab', tab); 43264 } 43265 43266 _constructor.initSearch = function(selector, ibegin, iend, maxIsToday) { 43267 var j = $(selector); 43268 var jclient = j.find('.search-Client_id'); 43269 43270 Search.init(selector + ' .search-Client_id', GLO.Link.Object.Provider.UserSearch); 43271 UI.initAutoComplete(jclient, GLO.Link.Object.Provider.UserSearch);
43272 UI.setAccessKey(selector, GLO.MyAppts.search); 43273 43274 var start = GLO.Uri.url('start'), end = GLO.Uri.url('end'); 43275 var startEdit = GLO.Uri.url('startEdit'), endEdit = GLO.Uri.url('endEdit'); 43276 43277 var svc = UTIL.coalesceString(GLO.Uri.url('servicefilter'), GLO.Uri.url('service')); 43278 var clientId = GLO.Uri.url('clientid'), clientName = GLO.Uri.url('clientname'); 43279 var isBookedByClient = UTIL.parseBool(GLO.Uri.url('BookedByClient')) || UTIL.parseBool(GLO.Uri.url('isclient')); 43280 43281 if (UTIL.isNumber(clientId) && !UTIL.isEmpty(clientName)) { 43282 jclient.attr('autoId', clientId).val(clientName); 43283 } 43284 43285 if (UTIL.isDate(start)) { 43286 var Begin_dt = new Date(start); 43287 } else { 43288 var Begin_dt = new Date(); 43289 Begin_dt.setDate(Begin_dt.getDate() - ibegin); 43290 } 43291 43292 if (UTIL.isDate(end)) { 43293 var End_dt = new Date(end); 43294 } else { 43295 var End_dt = new Date(); 43296 End_dt.setDate(End_dt.getDate() + iend); 43297 } 43298 43299 var jStart = j.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 43300 , numberOfMonths: UI.getDatepickerMonths(1480) }); 43301 var jEnd = j.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 43302 , numberOfMonths: UI.getDatepickerMonths(1080) }); 43303 43304 var jStartEdit = j.find('.Edit_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 43305 , numberOfMonths: UI.getDatepickerMonths(1480), maxDate: 0 }); 43306 var jEndEdit = j.find('.Edit_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 43307 , numberOfMonths: UI.getDatepickerMonths(1080), maxDate: 0 }); 43308 43309 if (selector != '#myAppointments-updates' || UTIL.isDate(start)) { 43310 jStart.val(Begin_dt.toGloDate()); 43311 } 43312 if (selector != '#myAppointments-updates' || UTIL.isDate(end)) { 43313 jEnd.val(End_dt.toGloDate()); 43314 } 43315 43316 if (jStartEdit.length && UTIL.isDate(startEdit)) { 43317 jStartEdit.val(new Date(startEdit).toGloDate()); 43318 } 43319 if (jEndEdit.length && UTIL.isDate(endEdit)) { 43320 jEndEdit.val(new Date(endEdit).toGloDate()); 43321 } 43322 43323 if (maxIsToday) { 43324 var jEditBegin = j.find('.Edit_Begin_dt'); 43325 43326 if (jEditBegin.length) { 43327 j.find('.Edit_Begin_dt').datepicker('option', 'maxDate', 0); 43328 j.find('.Edit_End_dt').datepicker('option', 'maxDate', 0); 43329 } else { 43330 j.find('.Begin_dt').datepicker('option', 'maxDate', 0); 43331 j.find('.End_dt').datepicker('option', 'maxDate', 0); 43332 } 43333 } 43334 //$(selector + ' .Begin_dt').value = (Begin_dt.getMonth() + 1) + '/' + Begin_dt.getDate() + '/' + Begin_dt.getFullYear(); 43335 //$(selector + ' .End_dt').value = (End_dt.getMonth() + 1) + '/' + End_dt.getDate() + '/' + End_dt.getFullYear(); 43336 43337 if (!UTIL.isEmpty(svc)) { 43338 j.find('.Service_Filter').val(svc); 43339 } 43340 43341 if (isBookedByClient) { 43342 j.find('.Update_By_Client_fl').prop('checked', true); 43343 } 43344 } 43345 43346 _constructor.openHelp = function(event, thisIcon) { 43347 thisIcon = $(thisIcon); 43348 var desc = '<p>' + thisIcon.attr('alt') + '</p>'; //var desc = $('.staff-tab').attr('title'); 43349 var tabBody = thisIcon.closest('.appt-list-sheet').parent(); 43350 var tabBodyId = tabBody.attr('id'); 43351 43352 if (tabBodyId === 'myAppointments-updates') { 43353 var bYellow = '<b class="narrow-text" style="padding: 2px 4px; white-space: nowrap; background-color: Yellow;">'; 43354 var bGreen = '<b class="narrow-text" style="padding: 2px 4px; white-space: nowrap; background-color: GreenYellow;">'; 43355 43356 tabBody.find('.lastUpdateDate, .recent-activity-last-edit').addClass('help-list-view-column-highlight'); 43357 tabBody.find('.apptListDate, .recent-activity-appointment-start').addClass('help-list-view-column-highlight2'); 43358 43359 desc += '<p style="margin-top: 24px;">' + bYellow + 'Last Edit</b> date range that appointments have been ' + bYellow + SA.Resource.LastUpdated.toLowerCase() + '</b></p>'; 43360 desc += '<p style="margin-bottom: 24px;">' + bGreen + 'Appointment</b> date range of ' + bGreen + 'appointment start date</b></p>'; 43361 } else if (tabBodyId === 'myOtherEdits') { 43362 tabBody.find('.lastUpdateDate').addClass('help-list-view-column-highlight'); 43363 desc += '<p>' + SA.Resource.LookForAppts + ' <b style="background-color: Yellow; padding: 2px 5px;">' + SA.Resource.LastUpdated.toLowerCase() + '</b> ' + SA.Resource.WithinThatRange + '</p>'; 43364 } else if (tabBodyId === 'myAppointments-upcoming') { 43365 tabBody.find('.apptListDate').addClass('help-list-view-column-highlight'); 43366 desc += '<p>' + SA.Resource.DateLookFor + ' <b style="background-color: Yellow; padding: 2px 5px;">' + SA.Resource.when_the_appointment_occurs + '</p>'; 43367 } 43368 43369 var rptName = $('#list-view-tabs').find('.staff-tab').text().substring(2); 43370 var rptNameCss = 'padding: 4px; letter-spacing: 2px; font-size: larger; border-bottom-left-radius: 0; border-bottom-right-radius: 0; color: white;'; 43371 43372 var htm = '<div id="pop-list-view-help">' + desc + '</div>'; 43373 var ojInfo = new GLO.Popup.Info(htm, GLO.MyAppts.closeHelp).getPopup(); 43374 43375 ojInfo.prepend('<h1 style="' + rptNameCss + '">' + rptName + ' Report</h1>'); 43376 ojInfo.find('#pop-list-view-help') 43377 .append('<p style="margin-top: 20px;">Click the last updated column to see a list of all the changes made to an appointment</p>') 43378 .append('<p style="margin-top: 20px; padding-bottom: 12px;">You can search for updates to a specific client\'s appointments by entering their name below, changing the dates as desired, and pressing search</p>'); 43379 } 43380 43381 _constructor.closeHelp = function() { 43382 $('.help-list-view-column-highlight').removeClass('help-list-view-column-highlight'); 43383 $('.help-list-view-column-highlight2').removeClass('help-list-view-column-highlight2'); 43384 } 43385 43386 _constructor.displayEditReason = function(event, reason) { 43387 if (event.target.tagName.toUpperCase() !== 'A') { 43388 GLO.Popup.Info("<h1 style='color: White; margin-top: -18px; margin-bottom: 15px;'>" + SA.Resource.CancellationReason + "</h1><div style='margin-bottom: -10px;'>" + reason + "</div>"); 43389 } 43390 } 43391 43392 _constructor.openHistory = function(event, thisTD) { 43393 var me = $(thisTD); 43394 GLO.UI.Form.beginProcessing(me); 43395 43396 var tr = me.closest('tr'); 43397 var sutype = tr.attr('sutype'); 43398 var apptid = tr.attr('id'); 43399 var scid = tr.attr('schedule_client_id'); 43400 var day = tr.attr('appt_dt'); 43401 var staffId = tr.attr('staff_id'); 43402 43403 _constructor.openHistory2(apptid, scid, sutype, day, staffId); 43404 } 43405 43406 _constructor.openHistory2 = function(apptid, scid, sutype, day, staffId) { 43407 var url = null; 43408 43409 if (UTIL.isNumber(sutype)) { 43410 sutype = parseInt(sutype); 43411 43412 if (sutype > 99 && sutype < 120) { 43413 apptid = null; 43414 url = GLO.Link.Page.Provider.Home + 'schedule/history/' + UTIL.replaceAll(day, '/', '-') + '?sutype=' + sutype + '&staff=' + staffId;
43415 } 43416 } 43417 43418 if (apptid !== null) { 43419 url = GLO.Link.Page.Provider.Home + 'appointment/history/' + apptid; 43420 43421 if (!UTIL.isEmpty(scid)) { 43422 url += '?scid=' + scid; 43423 } 43424 } 43425 43426 if (UTIL.isEmpty(url)) { 43427 GLO.Popup.Warning.open('Unable to Lookup History', 'History Not Found'); 43428 return; 43429 } 43430 43431 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 43432 .success(function(data, textStatus, jqXHR) { 43433 GLO.UI.Form.resetProcessing(); 43434 43435 var h1 = "<h1 id='appointment-history-header'>" + SA.Resource.AppointmentEditHistory + "</h1>"; 43436 var htm = $(data).prepend(h1); 43437 43438 var oj = new GLO.Popup.Custom(htm); 43439 var jpop = oj.getPopup().addClass('wide-popup').css({ "background-color": "white" }); 43440 43441 var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" }); 43442 jbtns.find('.btnCancel').remove(); 43443 jbtns.find('.btnSave').removeClass('btnSave').addClass('btnOk').find('a').text('Ok').css({ "padding": "7px 20px" }).focus(); 43444 43445 oj.realign(); 43446 $('#ba-EditAppointment').find('#imgThrobber').remove(); 43447 43448 var jtbl = jpop.find('.tablesorter'); 43449 GLO.Report.CellSummary.initReport(jtbl, true); 43450 }) 43451 .error(function(jqXHR, textStatus, errorThrown) { 43452 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 43453 }); 43454 } 43455 43456 _constructor.undeleteAppt = function(smid, scheduleId, dtDeleteDay) { 43457 if (GLO.Info.roleType < 220) { 43458 var msg = '<p style="letter-spacing: 1px;">Manager or Admin required to un-delete appointment?</p>'; 43459 var htm = '<div id="pop-warn-undelete-appt">' + msg + '</div>'; 43460 43461 GLO.Popup.Confirm.open(htm, 'Permission Warning'); 43462 return; 43463 } 43464 43465 var msg = '<p style="letter-spacing: 1px;">Are you sure you want to un-delete this appointment?</p>'; 43466 var htm = '<div id="pop-confirm-undelete-appt">' + msg + '</div>'; 43467 var fnYes = function() { GLO.MyAppts.undeleteApptConfirmed(smid, scheduleId, dtDeleteDay); }; 43468 43469 GLO.Popup.Confirm.open(htm, 'Confirm Appointment Un-Delete', fnYes); 43470 } 43471 _constructor.undeleteApptConfirmed = function(smid, scheduleId, dtDeleteDay) { 43472 var url = GLO.Link.WebsiteDomain + 'schedule/UnDeleteAppointment?smid=' + smid + '&scheduleId=' + scheduleId; 43473 var jpop = $('.glopop #apptHistory-container').closest('.glopop'); //= must do this way because opening popup does not remove popup html from original body 43474 var jbtn = jpop.find('#btnUndoDelete'); 43475 43476 if (UTIL.isEmpty(scheduleId)) { 43477 url += '&cutoff=' + dtDeleteDay; 43478 } 43479 43480 GLO.UI.Form.beginProcessing(jbtn); 43481 43482 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 43483 .success(function(data, textStatus, jqXHR) { 43484 //GLO.UI.Form.resetProcessing(); 43485 GLO.Popup.closeIfExist(jpop); 43486 GLO.Popup.Success.open('Appointment Successfully Un-Deleted', 'Appointment Un-Deleted'); 43487 43488 _constructor.refresh(); 43489 }) 43490 .error(function(jqXHR, textStatus, errorThrown) { 43491 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 43492 }); 43493 } 43494 _constructor.refresh = function(delay) { 43495 if (UTIL.parseBool(GLO.Uri.url('norefresh'))) { 43496 return; 43497 } 43498 43499 var jbtn = $('#staffPortal-main').find('.btnSearch:visible > a'); 43500 43501 if (jbtn.length) { 43502 jbtn.click(); 43503 } else { 43504 var delay = UTIL.coalesceInt(delay, 5500); 43505 43506 setTimeout(function() { 43507 location.reload(); 43508 }, delay); 43509 } 43510 } 43511 43512 _constructor.helpRecentActivity = function() { 43513 var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> '; 43514 var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>'; 43515 var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>'; 43516 43517 var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">'; 43518 var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .6;">'; 43519 var li = '<li style="margin-bottom: 6px; line-height: 1;">'; 43520 43521 var msg1a = p1 + bFilter + '</p>'; 43522 var list1a = li + '<b class="narrow-text" style="color: #4F81BD;">Appointment</b> Begin / End Date filters on the ' + bStart + '</li>'; 43523 var list1b = li + '<b class="narrow-text" style="color: #4F81BD;">Last Edit</b> Begin / End Date filters when the appointment was ' + bLastUpdated + '</li>'; 43524 //var msg1b = p1b + 'On all other screens Begin / End Date filters by the ticket date <i class="narrow-text">(i.e. ' + bStart + ')</i></p>'; 43525 var msg1 = msg1a + '<ul>
43525' + list1a + list1b + '</ul>'; 43526 43527 var msg2a = p1 + bSort + 'On <b class="narrow-text">Recent Activity</b> the sort is the appointment ' + bLastUpdated + ' column</p>'; 43528 var msg2b = p1b + 'press column header <b>Date</b> to sort by ' + bStart + '</p>'; 43529 43530 var htm = '<div id="pop-help-recent-activity">' + msg1 + msg2a + msg2b + '</div>'; 43531 var header = 'Most Recent Appointment Create/Update/Delete'; 43532 GLO.Popup.Info.openSimple(htm, header); 43533 } 43534 _constructor.helpUpcomingList = function() { 43535 var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> '; 43536 var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>'; 43537 var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>'; 43538 43539 var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">'; 43540 var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .8;">'; 43541 43542 var msg1a = p1 + bFilter + 'Begin / End Date filters on the ' + bStart + '</p>'; 43543 var msg1b = p1b + 'To filter based on when ticket ' + bLastUpdated + ' use <b>Recent Activity</b> tab</p>'; 43544 43545 var msg2a = p1 + bSort + 'Default sort uses the ' + bStart + '</p>'; 43546 var msg2b = p1b + 'press column header <b>Update</b> to sort by last updated date</p>'; 43547 43548 var htm = '<div id="pop-help-recent-activity">' + msg1a + msg1b + msg2a + msg2b + '</div>'; 43549 var header = 'Appointment List'; 43550 GLO.Popup.Info.openSimple(htm, header); 43551 } 43552 _constructor.helpMyEdits = function() { 43553 var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> '; 43554 var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>'; 43555 var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>'; 43556 var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">'; 43557 var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .6;">'; 43558 43559 var msg1a = p1 + bFilter + 'Begin / End Date filters on ' + bLastUpdated + '</p>'; 43560 //var msg1b = p1b + 'To filter based on when ticket ' + bStart + ' use <b>Recent Activity</b> tab</p>'; 43561 43562 var msg2a = p1 + bSort + 'Default sort is by ' + bLastUpdated + ' column</p>'; 43563 var msg2b = p1b + 'press column header <b>Date</b> to sort by ' + bStart + '</p>'; 43564 43565 var htm = '<div id="pop-help-recent-activity">' + msg1a + msg2a + msg2b + '</div>'; 43566 var header = 'Your Recent Edits'; 43567 GLO.Popup.Info.openSimple(htm, header); 43568 } 43569 43570 return _constructor; 43571})(); 43572 43573 43574if (GLO.Reports === undefined) { GLO.Reports = {}; } 43575 43576GLO.Reports.MessageHistory = (function() { 43577 function _cMessageHistory() { } 43578 43579 _cMessageHistory.init = function() { 43580 var jrpt = $('#table-message-history'); 43581 43582 UI.initTableSorter(jrpt); 43583 GLO.Report.CellSummary.initReport(jrpt, false, false); 43584 //GLO.Report.initShortcutKeys(); 43585 GLO.Report.initUrlAction(); 43586 } 43587 43588 function _findRow(element, tableId) { 43589 var tr = $(element).closest('tr'); 43590 43591 if (tr.length === 0) { 43592 tr = $('#' + tableId).find('td.cell-summary-selected').closest('tr'); 43593 43594 if (tr.length === 0) { 43595 tr = $('table.tablesorter').find('td.cell-summary-selected').closest('tr'); 43596 } 43597 } 43598 43599 return tr; 43600 } 43601 43602 _cMessageHistory.openTicket = function(element) { 43603 var tr = _findRow(element, 'table-message-history'); 43604 var serviceCount = UTIL.coalesceInt(tr.attr('appt_count_sr')); 43605 var productCount = UTIL.coalesceInt(tr.attr('inventory_count_sr')); 43606 var smid = tr.attr('smid'); 43607 43608 GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') ); 43609 43610 if (serviceCount > 0) { 43611 UserPortal.Edit.get(null, smid); 43612 } else { 43613 UserPortal.Price.get(smid); 43614 } 43615 } 43616 _cMessageHistory.viewTicketMessages = function(element) { 43617 var tr = _findRow(element, 'table-message-history');
43618 var jsonClient = GLO.ClientProfile.getClientFromProfile(); 43619 43620 var smid = UTIL.coalesceInt(jsonClient.smid, tr.attr('smid')); 43621 var clientId = UTIL.coalesceInt(jsonClient.id, $('#report-message-sent-history').attr('client_id')); 43622 var bkg = UTIL.coalesceInt(jsonClient.bkg, tr.attr('bkg')); 43623 43624 GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') ); 43625 GLO.Popup.closeIfExist( $('#pop-help-cell-summary').closest('.glopop') ); 43626 43627 ClientProfile.openMessagesSentById(clientId, smid, bkg); 43628 } 43629 43630 return _cMessageHistory; 43631})(); 43632 43633GLO.Reports.StaffProfile = (function() { 43634 function _conRptProfile() { } 43635 43636 _conRptProfile.init = function() { 43637 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 43638 var hashTab = _getHash(); 43639 43640 _conRptProfile.goToTab(hashTab); 43641 _conRptProfile.initReport(); 43642 43643 _initPermissionReport2(); 43644 WIZ.isWizard = false; 43645 43646 GLO.Report.initShortcutKeys(); 43647 GLO.Report.portalName = 'Staff Profiles'; 43648 43649 if (innerWidth < 800) { 43650 var td = $('#report-portal-header').find('td > span'); 43651 td.eq(0).html('<b>1</b>' + SA.Resource.Profile); 43652 td.eq(1).html('<b>2</b>' + SA.Resource.Config); 43653 td.eq(2).html('<b>3</b>' + SA.Resource.Services); 43654 td.eq(3).html('<b>4</b>' + SA.Resource.Hours); 43655 td.eq(4).html('<b>5</b>' + SA.Resource.Client); 43656 td.eq(5).html('<b>6</b>' + SA.Resource.Permissions); 43657 } 43658 43659 GLO.Report.enableFullPageCheck(); 43660 _initUrlForStaffProfile(highlight); 43661 43662 var jrptClient = $('table#staff-client-config-list'); 43663 GLO.Report.CellSummary.initReport(jrptClient, false, false); 43664 } 43665 function _initUrlForStaffProfile(highlight) { 43666 if (highlight.toLowerCase() == 'staff-alerts') { 43667 var jhighlight = $('#staff-notification-list').find('.report-column-alert-email, .report-column-alert-text'); 43668 UI.highlight(jhighlight, 1200, 6400, true); 43669 } else if (!UTIL.isEmpty(highlight)) { 43670 var jhighlight = $('#report-main.staff-profile-report .tablesorter:visible').find('.' + highlight); 43671 UI.highlight(jhighlight, 1200, 6400, true); 43672 } 43673 } 43674 _conRptProfile.initReport = function() { 43675 $("#quick-view .tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy }); 43676 $('.wiz-buttons, #feedback-container').remove(); 43677 } 43678 43679 _conRptProfile.initPermissionReport = function() { 43680 UI.initTableSorter( $("#quick-view #staff-service-list.tablesorter") ); //_conRptProfile.initReport(); 43681 $('.wiz-buttons, #feedback-container').remove(); 43682 43683 _initPermissionReport2(); 43684 } 43685 43686 function _initPermissionReport2() { 43687 $("#quick-view #staff-permission-list.tablesorter tbody").delegate('td','mouseover mouseleave', function(e) { 43688 if (e.type == 'mouseover') { 43689 var t = $(this); 43690 //t.parent().addClass("hover-column"); 43691 $("colgroup").eq(t.index()).addClass("hover-column"); 43692 } else { 43693 var t = $(this); 43694 //t.parent().removeClass("hover-column"); 43695 $("colgroup").eq(t.index()).removeClass("hover-column"); 43696 } 43697 }); 43698 43699 $("#quick-view #staff-permission-list.tablesorter").delegate('tbody', 'mouseover mouseleave', function(e) { 43700 if (e.type == 'mouseover') { 43701 $(this).find('tr:even').removeClass('EveryOtherRowQuiet'); 43702 } else { 43703 $(this).find('tr:even').addClass('EveryOtherRowQuiet'); 43704 } 43705 }); 43706 } 43707 43708 _conRptProfile.goToTab = function(tab) { 43709 $('#report-profile').addClass('hide'); 43710 $('#report-notification').addClass('hide'); 43711 $('#report-service').addClass('hide'); 43712 43713 $('#report-hour').addClass('hide'); 43714 $('#report-client-config').addClass('hide'); 43715 $('#report-inventory-permission').addClass('hide'); 43716 43717 $('#report-staff-address').addClass('hide'); 43718
43719 _setTabBackground(tab); 43720 _setHash(tab); 43721 } 43722 43723 function _getHash() { 43724 var hashTab = GLO.Uri.hash('tab').toLowerCase(); 43725 43726 if (hashTab === 'report-profile') { 43727 return 1; 43728 } else if (hashTab === 'report-notification') { 43729 return 2; 43730 } else if (hashTab === 'report-service') { 43731 return 3; 43732 43733 } else if (hashTab === 'report-hour') { 43734 return 4; 43735 } else if (hashTab === 'report-client-config') { 43736 return 5; 43737 } else if (hashTab === 'report-inventory-permission') { 43738 return 6; 43739 43740 } else if (hashTab === 'report-staff-address') { 43741 return 7; 43742 } else { 43743 return 1; 43744 } 43745 } 43746 43747 function _setHash(tab) { 43748 var hashTab = ''; 43749 43750 if (tab == 1) { 43751 hashTab = 'report-profile'; 43752 $('#report-profile').removeClass('hide'); 43753 } else if (tab == 2) { 43754 hashTab = 'report-notification'; 43755 $('#report-notification').removeClass('hide'); 43756 } else if (tab == 3) { 43757 hashTab = 'report-service'; 43758 $('#report-service').removeClass('hide'); 43759 43760 } else if (tab == 4) { 43761 hashTab = 'report-hour'; 43762 $('#report-hour').removeClass('hide'); 43763 } else if (tab == 5) { 43764 hashTab = 'report-client-config'; 43765 $('#report-client-config').removeClass('hide'); 43766 } else if (tab == 6) { 43767 hashTab = 'report-inventory-permission'; 43768 $('#report-inventory-permission').removeClass('hide'); 43769 43770 } else if (tab == 7) { 43771 hashTab = 'report-staff-address'; 43772 $('#report-staff-address').removeClass('hide'); 43773 } 43774 43775 document.location.hash = 'tab=' + hashTab; 43776 } 43777
43778 function _setTabBackground(tab) { 43779 var backColor = $('.shadow-content0').css('backgroundColor'); 43780 var jhead = $('#report-portal-header'); 43781 var oj = jhead.find('table tr td span b'); 43782 43783 oj.each(function() { 43784 $(this).parent().parent().removeClass('report-tab').css('backgroundColor', ''); 43785 }); 43786 43787 oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent(); 43788 oj.addClass('report-tab'); 43789 oj.css('backgroundColor', backColor); 43790 } 43791 43792 return _conRptProfile; 43793})(); 43794 43795 43796GLO.Report.ClientRefer = (function() { //Used by Payment Summary + Gift Card report 43797 function _conRptRefer() { } 43798 43799 _conRptRefer.init = function() { 43800 var jhead = $('.report-search-header'); 43801 GLO.Report.Template.initDateRange(jhead, true); 43802 43803 if (!GLO.Report.Sales.initStaffFilter()) { 43804 GLO.Report.Template.initStaffFilter(true); 43805 } 43806 43807 //_setDateMax(jhead, "#report-end"); 43808 //$('#header-icon-container').remove(); 43809 43810 GLO.Report.setupFastClick(); 43811 GLO.Report.enableFullPage(true, true); //= this report forces display all columns (because the # of columns depends on the # of referrals used during this date range period) 43812 //GLO.Report.enableFullPageCheck(); //= no need for this because all columns always displayed on this report 43813 43814 _loadData(); 43815 } 43816 43817 function _loadData() { 43818 var jrpt = $('#report-main'); 43819 UI.initTableSorter( jrpt.find('table.tablesorter:visible') ); 43820 jrpt.find('thead th.column-staff').click(); 43821 GLO.Report.CellSummary.initReport(jrpt, true, true); 43822 } 43823 43824 function _setDateMax(j, id, maxDate) { 43825 if (!UTIL.isDate(maxDate)) { 43826 maxDate = new Date().toSADate(true); 43827 } 43828 43829 var jdt = j.find(id); 43830 var val = jdt.val(); 43831 43832 jdt.datepicker("option", "maxDate", maxDate); 43833 jdt.val(val); 43834 } 43835 43836 _conRptRefer.search = function() { 43837 var jrpt = $('#report-main'); 43838 var btnSearch = jrpt.find('#btnSearch'); 43839 var jRptData = jrpt.find('.report-container'); 43840 var pageTitle = 'Client Referral Report: ' + start + ' - ' + end; 43841 43842 var start = jrpt.find('#report-start:visible').val(); 43843 var end = jrpt.find('#report-end:visible').val(); 43844 var sfilter = GLO.Uri.query('sfilter'); 43845 var qstring = 'start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&sfilter=' + sfilter; 43846 var url = GLO.Link.WebsiteDomain + 'report/refer?' + qstring; 43847 var jd = { "ispartial": 1 }; 43848 43849 if (!GLO.Report.hasReportPassword(jd)) { 43850 return; 43851 } 43852 43853 GLO.UI.Form.beginProcessing(btnSearch); 43854 43855 $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 43856 .success(function(data, textStatus, jqXHR) { 43857 jRptData.html(data); 43858 _loadData(); 43859 43860 GLO.UI.Form.resetProcessing(); 43861 window.history.pushState("", pageTitle, url); 43862 }) 43863 .error(function(jqXHR, textStatus, errorThrown) { 43864 GLO.UI.Form.resetProcessing(); 43865 GLO.Popup.Error('Unable to lookup data at this time<br/>Please try again'); 43866 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 43867 }); 43868 } 43869 43870 return _conRptRefer; 43871})(); 43872 43873 43874GLO.Report.CellSummary = (function() { 43875 function _conRptCell() { } 43876 var _isLookupDates = false; 43877 /* 43878 Supports HTML attributes: title, report, reportName, oncellopen, celltitle, rowheader 43879 */ 43880 43881 _conRptCell.initReport = function(jrpt, isLookupDates, isIncludeFooter) { 43882 _isLookupDates = UTIL.parseBool(isLookupDates); 43883 43884 if (!jrpt.hasClass('tablesorter')) { 43885 jrpt = jrpt.find('table.tablesorter'); 43886 } 43887 43888 jrpt.addClass('cell-summary'); 43889 jrpt.on('click', 'tbody td', GLO.Report.CellSummary.openCellSummary); 43890 43891 if (isIncludeFooter) { 43892 jrpt.on('click', 'tfoot td', GLO.Report.CellSummary.openCellSummary); 43893 } 43894 43895 _isLookupDates = isLookupDates; 43896 _initCells(jrpt, isIncludeFooter); 43897 } 43898 43899 function _initCells(jtbl, isIncludeFooter) { 43900 if (isIncludeFooter) { 43901 var tds = jtbl.find('tbody td, tfoot td'); 43902 } else { 43903 var tds = jtbl.find('tbody td'); 43904 } 43905 43906 for (var i=0; i < tds.length; i++) { 43907 var td = tds.eq(i); 43908 43909 if (_hasCellSummary(td)) { 43910 td.addClass('has-cell-summary'); 43911 } 43912 } 43913 } 43914 43915 function _hasCellSummary(td) { 43916 if (!UTIL.isEmpty(td.attr('onclick')) || td.find('a[onclick]').length > 0) { return false; } 43917 if (UTIL.parseBool(td.attr('no-cell-summary'))) { return false; } 43918 if (UTIL.isEmpty(td.html()) && !UTIL.parseBool(td.attr('is-force-cell-summary'))) { return false; } 43919 if (UTIL.isEmpty(td.attr('title')) && UTIL.isEmpty(td.attr('report')) && UTIL.isEmpty(td.attr('popup')) && UTIL.isEmpty(td.attr('oncellopen'))) { return false; } 43920 43921 return true; 43922 } 43923 43924 _conRptCell.openCellSummary = function() { 43925 var td = $(this); 43926 _openCellSummary2(td); 43927 } 43928 43929 function _openCellSummary2(td, htmInfo) { 43930 if (!_hasCellSummary(td) && UTIL.isEmpty(htmInfo) && UTIL.isEmpty(td.attr('popup'))) { return; } 43931 if ($('#pop-help-cell-summary').closest('.glopop').length > 0) { return; } 43932 43933 var title = UTIL.coalesce(td.find('.title').html(), td.attr('title_htm'), td.attr('title'));
43934 var msg = _conRptCell.getCellDescription(title); 43935 var h1 = _getCellHelpHeader(td); 43936 var htmReports = ''; 43937 43938 htmReports += _cellHelpAddReport(td, 'report', 'reportName'); 43939 htmReports += _cellHelpAddReport(td, 'report2', 'reportName2'); 43940 htmReports += _cellHelpAddReport(td, 'report3', 'reportName3'); 43941 htmReports += _cellHelpAddReport(td, 'report4', 'reportName4'); 43942 htmReports += _cellHelpAddReport(td, 'report5', 'reportName5'); 43943 43944 htmReports += _cellHelpAddPopup(td, 'popup', 'popupName'); 43945 htmReports += _cellHelpAddPopup(td, 'popup2', 'popupName2'); 43946 htmReports += _cellHelpAddPopup(td, 'popup3', 'popupName3'); 43947 htmReports += _cellHelpAddPopup(td, 'popup4', 'popupName4'); 43948 htmReports += _cellHelpAddPopup(td, 'popup5', 'popupName5'); 43949 43950 if (!UTIL.isEmpty(htmReports)) { 43951 var relatedReportsTitle = UTIL.coalesceString(td.attr('relatedReportsTitle'), SA.Resource.RelatedReports); 43952 htmReports = '<div id="pop-help-report-list"> <h3>' + relatedReportsTitle + '</h3>' + htmReports; 43953 } 43954 43955 var htmOnOpen = '<div id="cell-on-open"></div>'; 43956 var htmMsg = '<div id="pop-cell-description">' + msg + UTIL.cleanString(htmInfo) + '</div>'; 43957 var htm = '<div id="pop-help-cell-summary">' + htmMsg + htmOnOpen + htmReports + '</div> </div>'; 43958 var jpop = SA.Help.openSimple(h1, htm, true).addClass('no-persist'); 43959 jpop.find('.msg > div').css({ "padding": 0 }); 43960 43961 _cellOpenHighlight(td); 43962 _cellOpenEvent(jpop, td); 43963 } 43964 43965 function _cellOpenHighlight(td) { 43966 var jtbl = td.closest('table.cell-summary'); 43967 43968 jtbl.find('td.cell-summary-selected-prev').removeClass('cell-summary-selected-prev'); 43969 jtbl.find('td.cell-summary-selected').removeClass('cell-summary-selected').addClass('cell-summary-selected-prev'); 43970 43971 td.addClass('cell-summary-selected'); 43972 } 43973 43974 function _cellOpenEvent(jpop, td) { 43975 var fnstring = td.attr('oncellopen'); 43976 43977 if (fnstring) { 43978 var fn = _getFunctionFromString(fnstring); 43979 43980 if (typeof fn === 'function') { 43981 fn.call(td); 43982 } 43983 } 43984 } 43985 43986 _conRptCell.getCellDescription = function(title) { 43987 var msg = '', arr = UTIL.cleanString(title).split('|'); 43988 43989 for (var i=0; i < arr.length; i++) { 43990 if (!UTIL.isEmpty(arr[i])) { 43991 msg += '<p>' + _pluralToSingular(arr[i]) + '</p>'; 43992 } else { 43993 msg += '<br/>'; 43994 } 43995 } 43996 43997 return msg; 43998 } 43999 function _specialMessage(arr, tag) { 44000 for (var i=1; i < arr.length-1; i++) { 44001 44002 } 44003 } 44004 44005 function _pluralToSingular(text) { 44006 if (UTIL.isEmpty(text)) { return ''; } 44007 44008 text = UTIL.replaceAll(UTIL.replaceAll(String(text),' 1 clients', ' 1 client'),'(1 clients', '(1 client'); 44009 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 visits', ' 1 visit'),'(1 visits', '(1 visit'); 44010 44011 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 services', ' 1 service'),'(1 services', '(1 service'); 44012 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 tickets', ' 1 ticket'),'(1 tickets', '(1 ticket'); 44013 44014 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 tips', ' 1 tip'),'(1 tips', '(1 tip'); 44015 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 products', ' 1 product'),'(1 products', '(1 product'); 44016 text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 discounts', ' 1 discount'),'(1 discounts', '(1 discount'); 44017 44018 text = UTIL.replaceAll(text, '{', '<small>'); 44019 text = UTIL.replaceAll(text, '}', '</small>'); 44020 44021 text = UTIL.replaceAll(text, '(', '<small>('); 44022 text = UTIL.replaceAll(text, ')', ')</small>'); 44023 text = UTIL.replaceAll(text, '->', '<b class="arrow-right">➜</b>'); 44024 44025 if (text.length > 2) { 44026 if (text.substring(0,3) == '***') { 44027 text = '<span class="highlight-cell-row">' + text.substring(3) + '</span>'; 44028 } else if (text.substring(0,2) == '??') { 44029 text = '<b class="highlight-cell-row">' + text.substring(3) + '</b>'; 44030 } else if (text.substring(0,2) == '!!') { 44031 text = '<span class="highlight-cell-row-good">' + text.substring(1) + '</span>'; 44032 } else if (text.substring(0,2) == '* ' || text.substring(0,3) == ' * ') { 44033 text = '<ul class="highlight-cell-row-list"><li>' + text.substring(2) + '</li></ul>'; 44034 } 44035 } 44036 44037 return text; 44038 } 44039 44040 function _cellHelpAddReport(td, reportUrl, reportName) { 44041 reportUrl = td.attr(reportUrl); 44042 reportName = UTIL.coalesce(td.attr(reportName), 'Report'); 44043 44044 if (!UTIL.isEmpty(reportUrl)) { 44045 reportUrl = _conRptCell.getReport(reportUrl, td); 44046 return '<span class="btnAdd cell-help-report-link"> <a onclick="GLO.Report.CellSummary.gotoReport(\'' + reportUrl + '\', this, event)">' + reportName + '</a></span>'; 44047 } else { 44048 return ''; 44049 } 44050 } 44051 44052 function _cellHelpAddPopup(td, popupFunction, popupName) { 44053 popupFunction = td.attr(popupFunction); 44054 popupName = UTIL.coalesce(td.attr(popupName), 'View'); 44055 44056 if (!UTIL.isEmpty(popupFunction)) { 44057 //popupFunction = _getFunctionFromString(popupFunction); 44058 var onclick = ' onclick="' + popupFunction + '(this, event)"'; 44059 var btnAttributes = _parseAttributes(td[0]); 44060 44061 return '<span class="btnAdd cell-help-report-link"> <a' + onclick + btnAttributes + '>' + popupName + '</a></span>'; 44062 } else { 44063 return ''; 44064 } 44065 } 44066 44067 function _parseAttributes(htmElement) { 44068 var attributes = ''; 44069 44070 $.each(htmElement.attributes, function(i, attrib) { 44071 var name = attrib.name, value = attrib.value; 44072 44073 if (name !== 'class' && name !== 'title' && name !== 'oncellopen' && name !== 'celltitle' && name !== 'rowheader' && !UTIL.startsWith(name, 'report') && !UTIL.startsWith(name, 'popup')) { 44074 attributes += ' ' + name + '="' + value + '"'; 44075 } 44076 }); 44077 44078 return attributes; 44079 } 44080 44081 function _elementAttributesToJson(elem) { 44082 for (var i = 0; i < elem.attributes.length; i++) { 44083 var attrib = elem.attributes[i]; 44084 44085 if (attrib.specified) { 44086 console.log(attrib.name + " = " + attrib.value); 44087 } 44088 } 44089 } 44090 44091 function _getCellHelpHeader(td) { 44092 var tr = td.closest('tr'); 44093 var summaryTitle = UTIL.cleanString(td.attr('summarytitle'));
44094 44095 if (!UTIL.isEmpty(summaryTitle)) { 44096 return '<b>' + summaryTitle + '</b>'; 44097 } 44098 44099 var headerText = UTIL.cleanString(td.attr('celltitle')); 44100 var span1 = '<span style="white-space: nowrap; font-size: 150%; color: white;">', span2 = '</span>'; 44101 var cellIndex = td.parent().children().index(td); 44102 44103 var th = td.closest('table').find('thead > tr:last').find('th').eq(cellIndex).clone(); 44104 th.find('.question-icon').remove(); 44105 th.find('.table-header-press-help').remove(); 44106 44107 var columnName = th.text(); 44108 var columnNameHtm = span1 + columnName + span2; 44109 var jRowHeader = tr.find('.row-header'); 44110 44111 if (UTIL.isEmpty(headerText)) { 44112 headerText = UTIL.cleanString(tr.attr('rowheader')); 44113 44114 for (var i=0; i < jRowHeader.length; i++) { 44115 if (i > 0) { 44116 //if (jRowHeader.length == 2) { headerText += ':'; } 44117 headerText += ' '; 44118 } 44119 44120 headerText += jRowHeader.eq(i).text(); 44121 } 44122 44123 headerText = headerText.replace('$-', '-$'); 44124 } 44125 44126 if (UTIL.isEmpty(headerText)) { 44127 headerText = UTIL.directTagOnly(tr.find('td:first > a')); 44128 44129 if (UTIL.isEmpty(headerText)) { headerText = UTIL.directTagOnly(tr.find('td:first')); } 44130 if (UTIL.isEmpty(headerText)) { headerText = tr.find('td:first').text(); } 44131 } 44132 44133 if (UTIL.isEmpty(headerText) && tr.parent().prop("tagName") === 'TFOOT' && columnName != 'Total') { 44134 var colIndex = td.parent().children().index(td); 44135 headerText = 'Total'; 44136 } 44137 44138 if (!UTIL.isEmpty(headerText)) { 44139 headerText = span1 + headerText + span2 + '<b style="font-size: 150%;">•</b> '; 44140 } 44141 44142 return '<b style="color: white;">' + headerText + columnNameHtm + '</b>'; 44143 } 44144 44145 _conRptCell.getReport = function(url, jelement) { 44146 var dates = '', qs = '?', hash = '#', queryStart = url.indexOf('?'), hashStart = url.indexOf('#'); 44147 var isCal = (url.toLowerCase().indexOf('provider/calendar') !== -1), isActivityView = (url.toLowerCase().indexOf('provider/apptportal') !== -1); 44148 var sfilter = _reportUrlStaff(jelement, url); 44149 44150 if (_isLookupDates) { 44151 dates = _reportUrlDates(url); 44152 } 44153 44154 if (hashStart !== -1) { 44155 hash = url.substring(hashStart); 44156 url = url.substring(0, hashStart); 44157 } 44158 44159 if (queryStart !== -1) { 44160 qs = url.substring(queryStart); 44161 url = url.substring(0, queryStart); 44162 } 44163 44164 if (isCal) { 44165 qs += sfilter; 44166 } else if (isActivityView) { 44167 qs += sfilter; 44168 hash += dates; 44169 } else { 44170 qs += sfilter + dates; 44171 } 44172 44173 return _getReport2(url, qs, hash); 44174 } 44175 44176 function _reportUrlDates(url) { 44177 if (url && url.indexOf && url.indexOf('start=') !== -1) { 44178 return ''; 44179 } 44180 44181 var output = '', jfilter = $('#report-main .report-search-header'); 44182 var start = UTIL.fromSADate(jfilter.find('#report-start').val(), true, true); 44183 var end = UTIL.fromSADate(jfilter.find('#report-end').val(), true, true); 44184 44185 if (UTIL.isDate(start)) { 44186 output += '&start=' + start; 44187 } 44188 44189 if (UTIL.isDate(end)) { 44190 output += '&end=' + end; 44191 } 44192 44193 return output; 44194 } 44195 44196 function _reportUrlStaff(jelement, url) { 44197 if (url && url.indexOf && url.indexOf('sfilter=') !== -1) { 44198 return ''; 44199 } 44200 44201 if (jelement) { 44202 var sfilter = jelement.closest('tr').attr('staff_id'); 44203 } else { 44204 var sfilter = GLO.Uri.query('sfilter'); 44205 } 44206 44207 if (!UTIL.isEmpty(sfilter)) { 44208 return '&sfilter=' + sfilter; 44209 } else { 44210 return ''; 44211 } 44212 } 44213 44214 function _getReport2(path, query, hash) { 44215 query = query.replace('?&', '?'); 44216 44217 if (query && query.length > 1) { path += query; } 44218 if (hash && hash.length > 1) { path += hash; } 44219 44220 return path; 44221 } 44222 44223 _conRptCell.gotoReport = function(url, btn, event) { 44224 if (SA.Menu.isRequirePIN(url, btn, event)) { 44225 return false; 44226 } 44227 44228 var test = url.toLowerCase(); 44229 44230 if (test.indexOf('/') !== 0 && test.indexOf('http') == -1 && test.indexOf('www.') === -1) { 44231 url = '/' + url; 44232 } 44233 44234 if (btn) { 44235 GLO.UI.Form.beginProcessing(btn); 44236 } 44237 44238 if (event && event.ctrlKey) { 44239 var url = document.location.protocol + '//' + document.location.host + url; 44240 var childWindow = UI.openChildWindow(url, '', true); 44241 44242 setTimeout(function() { 44243 GLO.UI.Form.resetProcessing(btn); 44244 }, 2100); 44245 } else { 44246 setTimeout(function() { 44247 document.location = url; 44248 }, 100); 44249 } 44250 } 44251 44252 function _getFunctionFromString(string) { 44253 var scope = window; 44254 var scopeSplit = string.split('.'); 44255 44256 for (i = 0; i < scopeSplit.length - 1; i++) { 44257 scope = scope[scopeSplit[i]];
44258 if (scope == undefined) return; 44259 } 44260 44261 return scope[scopeSplit[scopeSplit.length - 1]]; 44262 } 44263 44264 _conRptCell.viewProductSummary = function() { 44265 var iid = (this).closest('tr').attr('inventory_id'); 44266 var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + iid; 44267 44268 var throbber = GLO.Report.Template2.getBlueThrobber(); 44269 var jpop = $('#pop-help-cell-summary').closest('.glopop'); 44270 var jthrobber = jpop.find('#cell-on-open').html(throbber); 44271 44272 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false }) 44273 .success(function(data, textStatus, jqXHR) { 44274 var tbl = $(data).find('table'); 44275 jthrobber.replaceWith(tbl); 44276 }) 44277 .error(function(jqXHR, textStatus, errorThrown) { 44278 jthrobber.remove(); 44279 }); 44280 } 44281 44282 _conRptCell.viewStaffServices = function(element, event) { //= inline popup 44283 var jbtn = $(element); 44284 var sid = jbtn.attr('staff_id'); 44285 44286 if (!UTIL.isEmpty(sid)) { 44287 Wiz5.openStaffQuickView(sid, event); 44288 } 44289 44290 _conRptCell.processingOpenPopup(jbtn); 44291 } 44292 44293 _conRptCell.viewProductSummary = function(element, event) { //= inline popup 44294 var jbtn = $(element); 44295 var iid = jbtn.attr('inventory_id'), gcid = jbtn.attr('gift_card_id'); 44296 44297 if (!UTIL.isEmpty(gcid)) { 44298 var gcnr = UTIL.cleanString(jbtn.attr('gift_number_vc')), gcmn = UTIL.cleanString(jbtn.attr('gift_balance_mn')); 44299 UserPortal.Price.GiftCard.openEdit(gcid, gcnr, gcmn); 44300 } else if (!UTIL.isEmpty(iid)) { 44301 GLO.Inventory.Item.openViewPopup(iid); 44302 } 44303 44304 _conRptCell.processingOpenPopup(jbtn); 44305 } 44306 44307 _conRptCell.processingOpenPopup = function(jbtn) { 44308 var jpop = jbtn.closest('.glopop'); 44309 44310 GLO.UI.Form.beginProcessing(jbtn); 44311 44312 setTimeout(function() { 44313 GLO.Popup.close(jpop); 44314 }, 800); 44315 } 44316 44317 44318 _conRptCell.ClientList = (function() { 44319 function _conRptCell_CL() {} 44320 44321 _conRptCell_CL.init = function() { 44322 var jtbl = $('#be-client-list').addClass('cell-summary'); 44323 44324 jtbl.on('click', 'tbody td', GLO.Report.CellSummary.ClientList.openCellSummary); 44325 44326 _initCells(jtbl, false); 44327 } 44328 44329 _conRptCell_CL.openCellSummary = function() { 44330 var td = $(this); 44331 var htm = _getInfo(td); 44332 44333 _openCellSummary2(td, htm); 44334 } 44335 44336 function _getInfo(td) { 44337 var htm = ''; 44338 44339 if (td.hasClass('be-phone')) { 44340 htm += _getPhoneColumn(td); 44341 } else if (td.hasClass('be-email')) { 44342 htm += _getEmailColumn(td); 44343 } else if (td.hasClass('last-visit')) { 44344 htm += _getVisitColumn(td, false); 44345 } else if (td.hasClass('next-visit')) { 44346 htm += _getVisitColumn(td, true); 44347 } else if (td.hasClass('visit-count')) { 44348 htm += _getVisitCountColumn(td); 44349 } else if (td.hasClass('product-count')) { 44350 htm += _getProductHistory(td); 44351 } else if (td.hasClass('product-first')) { 44352 htm += _getProductHistory(td); 44353 } else if (td.hasClass('product-last')) { 44354 htm += _getProductHistory(td); 44355 } 44356 44357 return htm; 44358 } 44359 44360 function _getProductHistory(td) { 44361 var htm = ''; 44362 44363 if (!UTIL.isEmpty(td.text())) { 44364 var tr = td.closest('tr'); 44365 var htmFirst = '', htmLast = '', isMobile = GLO.Info.isMobile(); 44366 44367 var dtFirst = tr.find('.product-first').attr('dt'), dtLast = tr.find('.product-last').attr('dt'); 44368 var tdCount = tr.find('.product-count'); 44369 44370 if (UTIL.isDate(dtFirst)) { 44371 var dtPretty = new Date(dtFirst).toGloDateString(true, true, isMobile, isMobile) + ' @ ' + new Date(dtFirst).toGloTime(); 44372 htmFirst = '<div class="first-product"><b style="font-size: smaller;">First Product Purchase:</b> ' + dtPretty + '</div>'; 44373 } 44374 44375 if (UTIL.isDate(dtLast)) { 44376 var dtPretty = new Date(dtLast).toGloDateString(true, true, isMobile, isMobile) + ' @ ' + new Date(dtLast).toGloTime(); 44377 htmLast = '<div class="first-product"><b style="font-size: smaller;">Last Product Purchase:</b> ' + dtPretty + '</div>'; 44378 } 44379 44380 htm += _getProductCountColumn(tdCount); 44381 htm += htmFirst + htmLast; 44382 } 44383 44384 return htm; 44385 } 44386 44387 function _getProductCountColumn(td) { 44388 var msg = '', cntTotal = UTIL.coalesceInt(td.text(), 0);
44389 var isMobile = GLO.Info.isMobile(); 44390 44391 var tr = td.closest('tr'); 44392 var cnt = UTIL.coalesceInt(tr.attr('products_in_range_sr'), 0); 44393 44394 var jfilter = $('#be-filter-client-area'); 44395 var start = UTIL.fromSADate(jfilter.find('#filter-start').val()), end = UTIL.fromSADate(jfilter.find('#filter-end').val()); 44396 var jbrand = jfilter.find('#filter-brand > option:selected'); 44397 var jcategory = jfilter.find('#filter-category > option:selected'); 44398 44399 var plural = 's', brand = '', categoryValue = jcategory.val(), categoryText = $.trim(jcategory.text()); 44400 44401 if (cnt == 1) { plural = ''; } 44402 if (!UTIL.isEmpty(jbrand.val())) { brand = ' ' + $.trim(jbrand.text()); } 44403 44404 if (!UTIL.isEmpty(categoryValue)) { 44405 if (parseInt(categoryValue) < 0) { 44406 if (categoryValue == -1) { 44407 categoryText = ''; 44408 msg = cnt + brand + ' product' + plural; 44409 } else { 44410 categoryText = ' when at least ' + Math.abs(categoryValue) + ' products purchased'; 44411 msg = cnt + brand + ' product' + plural + ' purchased' + categoryText; 44412 } 44413 } else { 44414 categoryText = ' ' + categoryText; 44415 msg = cnt + brand + categoryText + ' product' + plural; 44416 } 44417 } else { 44418 categoryText = ''; 44419 msg = cnt + brand + ' product' + plural; 44420 } 44421 44422 if (UTIL.isDate(start) && UTIL.isDate(end)) { 44423 msg += ' between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true); 44424 } else if (UTIL.isDate(start)) { 44425 msg += ' after ' + new Date(start).toGloDateString(true, true, isMobile, isMobile); 44426 } else if (UTIL.isDate(end)) { 44427 msg += ' before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile); 44428 } 44429 44430 if (cntTotal > cnt) { 44431 if (cntTotal == 1) { plural = ''; } else { plural = 's'; } 44432 var msgOverall = '<div style="margin-bottom: 8px; text-align: center;">Overall ' + cntTotal + brand + categoryText + ' product' + plural + ' sold</div>'; 44433 } else { 44434 var msgOverall = ''; 44435 } 44436 44437 msg = msgOverall + '<div class="product-message">' + msg + '</div>'; 44438 44439 var cid = tr.attr('client_id'), cname = tr.find('.be-client-name').find('>a').text(); 44440 var fnString = 'ClientProfile.openProductHistoryByClient(this, ' + cid + ', \'' + UTIL.htmlEncode3(cname) + '\')'; 44441 var viewLink = '<div class="view-product-history"><span class="btnAdd"><a onclick="' + fnString + '">View Product History</a></span></div>'; 44442 44443 return msg + viewLink 44444 } 44445 44446 function _getVisitCountColumn(td, isIgnoreVisitColumn) { 44447 var cnt = UTIL.coalesceInt(td.text(), 0); 44448 var tr = td.closest('tr'); 44449 44450 var jfilter = $('#be-filter-client-area'); 44451 var start = UTIL.fromSADate(jfilter.find('#filter-start').val()), end = UTIL.fromSADate(jfilter.find('#filter-end').val()); 44452 44453 var htm = _getVisitInfo(jfilter, tr, cnt, start, end); 44454 44455 if (!isIgnoreVisitColumn) { 44456 var jlast = tr.find('.last-visit'), jnext = tr.find('.next-visit'); 44457 htm += _getVisitColumn(jlast, false, true); 44458 htm += _getVisitColumn(jnext, true, true); 44459 } 44460 44461 htm += _getApptHistoryLink(tr, start, end); 44462 44463 if (parseInt(tr.find('.product-count').text()) > 0) { 44464 htm += '<hr/>' + _getProductHistory(td); 44465 } 44466 44467 htm += _getUnsubscribe(td, true, true); 44468 htm += _getNotes(tr); 44469 44470 return htm; 44471 } 44472 44473 function _getVisitInfo(jfilter, tr, bkgCount, start, end) { 44474 var isMobile = GLO.Info.isMobile(); 44475 var jsvc = jfilter.find('#filter-service > option:selected'); 44476 var serviceMessage = '', signInOnlyMsg = '', serviceValue = jsvc.val(), serviceText = $.trim(jsvc.text()); 44477 var cnt = UTIL.coalesceInt(tr.attr('services_in_range_sr'), 0); 44478 var siginOnlyCount = UTIL.coalesceInt(tr.attr('signin_only_count_sr'), 0); 44479 44480 if (siginOnlyCount > 0) { 44481 var ticketCount = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0) + UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0); 44482 var signInExplainer = '<span class="narrow-text">(client signed-in, but no associated ticket)</span>'; 44483
44484 signInOnlyMsg = '<div class="signin-only-message">' + siginOnlyCount + ' sign-in only ' + signInExplainer + ' + ' + UTIL.pluralLabel(ticketCount, 'ticket') + '</div>'; 44485 } 44486 44487 if (!UTIL.isEmpty(serviceValue)) { 44488 if (parseInt(serviceValue) < 0) { 44489 serviceMessage = UTIL.pluralLabel(cnt, 'service'); //serviceMessage = UTIL.pluralLabel(cnt, 'service') + ' with ' + serviceText; 44490 } else { 44491 serviceMessage = UTIL.pluralLabel(cnt, serviceText + ' service'); 44492 } 44493 } else { 44494 serviceMessage = UTIL.pluralLabel(cnt, 'service'); 44495 } 44496 44497 if (UTIL.isDate(start) && UTIL.isSameDay(start, end)) { 44498 serviceMessage += ' on ' + new Date(start).toGloDateString(true, true, true, true); 44499 } else if (UTIL.isDate(start) && UTIL.isDate(end)) { 44500 serviceMessage += ' between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true); 44501 } else if (UTIL.isDate(start)) { 44502 serviceMessage += ' after ' + new Date(start).toGloDateString(true, true, isMobile, isMobile); 44503 } else if (UTIL.isDate(end)) { 44504 serviceMessage += ' before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile); 44505 } 44506 44507 var msgFilter = '<div class="service-overall"> <b>' + UTIL.pluralLabel(bkgCount, 'visit') + '</b> <span class="narrow-text">(matching the client filter above)</span> </div>'; 44508 var overAll = _getAllTicketInfo(tr, bkgCount, cnt); 44509 44510 return msgFilter + '<div class="service-message">' + serviceMessage + '</div>' + signInOnlyMsg + overAll; 44511 } 44512 44513 function _getAllTicketInfo(tr, bkgCount, inDateRangeCount) { 44514 //if (bkgCount == inDateRangeCount) { return ''; } 44515 44516 var pOnly = UTIL.coalesceInt(tr.attr('product_only_visit_count_sr'), 0); 44517 var past = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0); 44518 var upcoming = UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0); 44519 44520 if (upcoming > 0 || past > 0) { 44521 return '<div class="service-overall">' + UTIL.pluralLabel(past, 'ticket') + ' in the past, ' + UTIL.pluralLabel(upcoming, 'upcoming ticket') + '</div>'; 44522 } 44523 44524 return ''; 44525 } 44526 44527 function _getApptHistoryLink(tr, start, end) { 44528 var startParam = null, endParam = null; 44529 var cid = tr.attr('client_id'), cname = tr.find('.be-client-name').find('>a').text(); 44530 44531 if (UTIL.isDate(start)) { 44532 startParam = '\'' + new Date(start).toGloDate() + '\''; 44533 } 44534 44535 if (UTIL.isDate(end)) { 44536 endParam = '\'' + new Date(end).toGloDate() + '\''; 44537 } 44538 44539 var fnString = 'ClientProfile.openApptHistoryByClient(this, ' + cid + ', null, ' + startParam + ', ' + endParam + ')'; 44540 44541 return '<div class="view-product-history"><span class="btnAdd"><a onclick="' + fnString + '">View Appointment History</a></span></div>'; 44542 } 44543 44544 function _getVisitColumn(td, isNext, isIgnoreCount) { 44545 var htm = '', dt = td.attr('dt'); 44546 var tr = td.closest('tr'); 44547 var apptCount = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0) + UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0); 44548 var siginOnlyCount = UTIL.coalesceInt(tr.attr('signin_only_count_sr'), 0); 44549 44550 if (UTIL.isDate(dt)) { 44551 var label = 'Last Visit', dt = new Date(dt), isMobile = GLO.Info.isMobile(); 44552 var dtService = td.attr('service_dt'); //only populated when 'dt' != service (so 'dt' is class or product purchase) 44553 var visitLink = '', htmPre = '', cid = td.closest('tr').attr('client_id'); 44554 44555 if (isNext) { 44556 label = 'Next Visit'; 44557 var pre = td.find('.is-prebooked').attr('title'); 44558 44559 if (!UTIL.isEmpty(pre)) { 44560 htmPre = '<div class="next-visit-pre-booked">' + pre + '</div>'; 44561 } 44562 } 44563 44564 if (apptCount > 1 && !UTIL.isDate(dtService)) { 44565 var visitLink = '<span class="btnAdd visit-link"><a onclick="GLO.Report.CellSummary.ClientList.viewAppt(this, ' + cid + ',\'' + dt.toGloDate(true) + '\')">View on Calendar</a></span>'; 44566 } 44567 44568 var dtPretty = dt.toGloDateString(true, true, isMobile, isMobile) + ' @ ' + dt.toGloTime(); 44569 var htmLastVisit = '<b style="font-size: smaller;">' + label + ':</b> <span class="visit-date">' + dtPretty + '</span> '; 44570 htm += '<div class="last-visit">' + htmLastVisit + visitLink + '</div>' + htmPre; 44571 44572 if (!isIgnoreCount) { 44573 var tdVisitCount = td.closest('tr').find('.visit-count'); 44574 htm += _getVisitCountColumn(tdVisitCount, true); 44575 } 44576 } 44577 44578 return htm; 44579 } 44580 44581 function _getEmailColumn(td) { 44582 var htm = '', emailShort = td.text(); 44583 var emailFull = UTIL.coalesce(td.attr('title'), emailShort); 44584 44585 if (UTIL.Validate.email(emailFull)) { 44586 var emailLink = '<a href="mailto:' + emailFull + '"> <b style="font-size: 85%;">Email Now:</b> ' + emailFull + '</a>'; 44587 htm += '<div class="email-link">' + emailLink + '</div>'; 44588 } 44589 44590 htm += _getUnsubscribe(td, true, false); 44591 return htm; 44592 } 44593 44594 function _getPhoneColumn(td) { 44595 var htm = '', phone = td.text(), tr = td.closest('tr'); 44596 44597 if (!(GLO.Info.isIosApp && GLO.Info.isAndroid) && phone.length === 12) { 44598 var phoneLink = '<a href="tel:' + phone + '" style="letter-spacing: 1px; font-size: 16px;"> <b style="font-size: 85%;">Call Now:</b> ' + UTIL.formatPhone(phone) + '</a>'; 44599 htm += '<div class="phone-link">' + phoneLink + '</div>'; 44600 } 44601 44602 htm += _getUnsubscribe(td, false, true); 44603 htm += _getNotes(tr); 44604 return htm; 44605 } 44606 44607 function _getNotes(tr) { 44608 var htm = '', jicons = tr.find('.be-icons'); 44609 var staffNote = UTIL.cleanString(jicons.find('.be-staff-note > img').attr('title'));
44610 var forbidNote = UTIL.cleanString(jicons.find('.be-forbid > img').attr('title')); 44611 44612 if (!UTIL.isEmpty(staffNote)) { htm += '<div class="staff-only-note"><b style="font-size: smaller;">Staff Only Note:</b> ' + staffNote + '</div>'; } 44613 if (!UTIL.isEmpty(forbidNote)) { htm += '<div class="forbid-note">' + forbidNote + '</div>'; } 44614 44615 return htm; 44616 } 44617 44618 function _getUnsubscribe(td, isEmail, isText) { 44619 var htm = '', jicons = td.closest('tr').find('.be-icons'); 44620 44621 if (isEmail) { 44622 var unsubscribeEmail = UTIL.cleanString(jicons.find('.be-unsubscribe-email').attr('title')); 44623 44624 if (!UTIL.isEmpty(unsubscribeEmail)) { 44625 htm += '<div class="unsubscribe" style="color: orange;">' + unsubscribeEmail + '</div>'; 44626 } 44627 } 44628 44629 if (isText) { 44630 var unsubscribeText = UTIL.cleanString(jicons.find('.be-unsubscribe-text').attr('title')); 44631 44632 if (!UTIL.isEmpty(unsubscribeText)) { 44633 htm += '<div class="unsubscribe">' + unsubscribeText + '</div>'; 44634 } 44635 } 44636 44637 return htm; 44638 } 44639 44640 _conRptCell_CL.viewAppt = function(btn, clientid, dt) { 44641 var visitUri = 'provider/calendar#dt=' + dt + '&clientid=' + clientid; 44642 44643 _conRptCell.gotoReport(visitUri, btn); 44644 } 44645 44646 return _conRptCell_CL; 44647 })(); 44648 44649 44650 return _conRptCell; 44651})(); 44652 44653 44654GLO.Message = (function() { 44655 function _conMsg() { } 44656 44657 _conMsg.view = function(messageId, processingMessage) { 44658 var url = GLO.Link.WebsiteDomain + 'message/' + messageId + '?ispartial=1'; 44659 44660 if (processingMessage) { 44661 var ojprocessing = GLO.Popup.Processing.open(processingMessage, 'Opening Message...'); 44662 } 44663 44664 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 44665 .success(function(data, textStatus, jqXHR) { 44666 if (ojprocessing) { 44667 ojprocessing.close(); 44668 } 44669 44670 var jhtm = $(data); 44671 GLO.Mobile.formatExternalLinksForIos(jhtm); 44672 jhtm.modal(); 44673 var jmodal = $('#simplemodal-container').addClass('view-message'); 44674 44675 if (!GLO.Info.isMobile()) { 44676 var handle = '#msg-header'; 44677 jmodal.draggable({ "handle": handle }).find(handle).css({ "cursor": "move" }); 44678 } 44679 44680 var width = jmodal.width() + 25; 44681 jmodal.css({ "padding": 0 }); 44682 jmodal.find('.simplemodal-data').css({ "padding": 0 }); 44683 jmodal.find('#msg-header').css({ "font-size": "100%", "border-top-left-radius": "6px" }); 44684 jmodal.find('#msg-subject').css({ "margin-bottom": "8px" }); 44685 jmodal.find('.simplemodal-wrap').addClass('scrollable-for-mac').css({ "overflow": "auto" }); //jmodal.find('.simplemodal-wrap').css({ "overflow": "auto", "width": width }); 44686 44687 $.modal.update(null, width); 44688 44689 setTimeout(function() { 44690 var jmodal = $('#simplemodal-container'); 44691 var height = jmodal.find('.simplemodal-data').outerHeight(); 44692 var newHeight = null; 44693 44694 if (height < innerHeight && height > jmodal.height()) { 44695 newHeight = height; 44696 } else { 44697 newHeight = innerHeight * .8; 44698 } 44699 44700 if (newHeight > 300) { 44701 jmodal.css({ "max-height": newHeight + 'px' }); 44702 $.modal.update(newHeight, null); 44703 } 44704 44705 width = parseInt(innerWidth - 40); 44706 44707 if (width < 310) { 44708 width = 310; 44709 } 44710 44711 if (jmodal.outerWidth() > width) { 44712 $.modal.update(newHeight, width); 44713 } 44714 44715 //$(window).trigger('resize.simplemodal'); 44716 }, 200); 44717 }) 44718 .error(function(jqXHR, textStatus, errorThrown) { }); 44719 } 44720 44721 _conMsg.viewCellSummary = function(element, event) { 44722 var jbtn = $(element); 44723 var msgid = jbtn.attr('message_id'); 44724 44725 _conMsg.view(msgid); 44726 GLO.Report.CellSummary.processingOpenPopup(jbtn); 44727 } 44728 44729 return _conMsg; 44730})(); 44731 44732 44733GLO.Message.Bulk = (function() { 44734 function _conBMsg() { } 44735 var _pageNumber, _pageCount, _isInitPage = true, _currentFilterAjax = null, _sortColumn = null, _sortDescending = null; 44736 var mmsImageUploadModal, mmsPreviewModal = null; 44737 44738 _conBMsg.initClientMarketingDashboard = function() { 44739 _loadMessageOverview(); 44740 } 44741 44742 function _loadMessageOverview() { 44743 var jcnt = $('#message-counts'); 44744 var emailCount = UTIL.displayMoney(jcnt.attr('free_email_nr'), true, false, true); 44745 var paidCount = UTIL.coalesceInt(jcnt.attr('message_package_nr'));
44746 var textBlastCount = UTIL.coalesceInt(jcnt.attr('text_blast_nr')); 44747 44748 if (paidCount > 0 && textBlastCount > 0) { 44749 var packageInfo = UTIL.displayMoney(paidCount, true, false, true) + ' normal paid messages'; 44750 packageInfo += UTIL.displayMoney(textBlastCount, true, false, true) + ' text blast messages'; 44751 } else if (paidCount > 0) { 44752 var packageInfo = UTIL.displayMoney(paidCount, true, false, true) + ' messages'; 44753 } else if (textBlastCount > 0) { 44754 var packageInfo = UTIL.displayMoney(textBlastCount, true, false, true) + ' text blast messages'; 44755 } else { 44756 var packageInfo = ''; 44757 } 44758 44759 var joverview = $('#marketing-overview'); 44760 joverview.find('#free-email-count').text(emailCount); 44761 joverview.find('#message-package-count').text(packageInfo); 44762 } 44763 44764 _conBMsg.initMarketingMessageHistory = function() { 44765 var jrpt = $('#message-blast-history table.tablesorter:visible'); 44766 UI.initTableSorter(jrpt); 44767 GLO.Report.CellSummary.initReport(jrpt, false, true); 44768 } 44769 44770 _conBMsg.init = function(fmtType) { 44771 GLO.Report.portalName = 'client-list'; 44772 _initSaveButton(); 44773 44774 var jlanguage = $('#language-icon-container').remove(); 44775 var helpIcon = '<span class="helpIcon2 sa-sprite" onclick="GLO.Message.Bulk.openHelp()"></span>'; 44776 44777 $('#bd').prepend('<h1 id="client-list-header">' + UTIL.cleanString(jlanguage.html()) + '<b>' + SA.Resource.ClientList + helpIcon + '</b></h1>'); 44778 44779 _initSavedFilter(); 44780 _initClientFilter(); 44781 _initClientFilterNarrowScreen(); 44782 _initClientFilterData(); 44783 44784 _initMessageArea(fmtType); 44785 44786 var isMessage = _initExistingMessage(); 44787 var jExisting = $('#bulk-email-container #bulk-sent-client-list'); 44788 44789 _initNonAdmin(); 44790 _initForMobile(); 44791 _isInitPage = false; 44792 44793 if (jExisting.length > 0) { //= is existing bulk message, not client list report (ie has bulk_id in query string). 44794 UI.initTableSorter(jExisting); 44795 44796 if ($('#bulk-email-container.accept-text-only').length > 0) { 44797 $('#bmsg-include-client-username').addClass('hide'); 44798 } 44799 } 44800 44801 /* if (GLO.Provider.isInCanada()) { 44802 $('#be-message-body-text #Text_vc').attr('maxlength', 136); 44803 } else { 44804 $('#be-message-body-text #Text_vc').attr('maxlength', 160); 44805 } */ 44806 44807 _initAutoSearch(isMessage); 44808 GLO.Report.enableFullPageCheck(); 44809 } 44810 44811 function _initSavedFilter() { 44812 var jfilter = $('#be-filter-client-area'); 44813 var query = jfilter.find('#ticket-type-filter').attr('saved_query_vc'); 44814 var bulkId = $('#Message_Bulk_id').val(); 44815 44816 if (!UTIL.isEmpty(bulkId)) { 44817 if (!UTIL.isEmpty(query)) { 44818 if (query.indexOf('id=' + bulkId) === -1) { 44819 query = query + '&id=' + bulkId; //UTIL.coalesceString(location.search, '').replace('?', ''); 44820 } 44821 44822 GLO.Report.TicketHistory.changeUrl(query, 'Saved Client List'); 44823 44824 if (jfilter.hasClass('is-sent')) { 44825 jfilter.find('input, select').prop('disabled', true); 44826 jfilter.find('.ui-icon-circle-close').remove(); 44827 jfilter.removeClass('hide'); 44828 } 44829 } 44830 } 44831 } 44832 44833 function _initAutoSearch(isMessage) { 44834 var jfilter = $('#be-filter-client-area'); 44835 var isAutoSearch = jfilter.length && !jfilter.hasClass('is-sent'); 44836 //var isAutoSearch = (!isMessage && $('#be-client-list').find('tbody > tr').length === 0); 44837 44838 if (isAutoSearch) { 44839 setTimeout(function() { 44840 $('#be-filter-client-area').find('#btnFilter > a').click(); 44841 //_initClientListHelp(); 44842 }, 40); 44843 } 44844 } 44845 44846 function _initClientListHelp() { 44847 var maxStep = 6, stepNumber = parseInt(GLO.Uri.url('helpstep')); 44848 44849 //if (GLO.Info.roleType < 210) { maxStep = 4; } 44850 44851 /* if (!UTIL.isNumber(stepNumber) || stepNumber > maxStep) { 44852 stepNumber = UTIL.randomNumber(1, maxStep)(); 44853 } */ 44854 44855 _conBMsg.openHelp(stepNumber); 44856 44857 var btnClose = $('.pop-help-post.glopop').find('.btnClose'); 44858 GLO.UI.Form.beginProcessing(btnClose); 44859 } 44860 44861 _conBMsg.openHelp = function(stepNumber) { 44862 SA.Help.openReportHelp('#client-list-help', stepNumber, 'info/ClientListHelp'); 44863 } 44864 44865 _conBMsg.openHelpEmailDeliverability = function() { 44866 var msg1 = '<p>When email messages are sent to a large number of people, email companies sometimes start filtering messages</p>'; 44867 var msg2 = '<p>To improve your messages deliverability we do several things including</p>'; 44868 var newCustomers = '<p class="narrow-text">
44868New ' + GLO.Info.getScheduleAnyoneHtm() + ' customers or high risk customers might have lower limits, ' + acctReview + '</p>'; 44869 var acctReview = 'if you receive a warning that you have a low limit per day or week feel free to contact us: account reviews typically increase limits to the normal settings'; 44870 44871 var li1 = '<li>Limit the number of messages that can be sent to the same email</li>'; 44872 var li2 = '<li>For each message we generate a deliverability score of 0-100, the higher the score the more likely the recepient will receive the message</li>'; 44873 var li3 = '<li>Work with email deliverability engines to improve successful delivery</li>'; 44874 44875 var list = '<ul>' + li1 + li2 + li3 + '</ul>'; 44876 var htm = '<div id="pop-help-email-deliverability">' + msg1 + msg2 + list + '</div>'; 44877 var jpop = GLO.Popup.Custom.openSimple(htm, 'Email Message Blast Deliverability Best Practices'); 44878 GLO.Popup.Custom.singleButton(jpop); 44879 } 44880 _conBMsg.openHelpTextDeliverability = function() { 44881 var isApproveMore = UTIL.parseBool($('#bulk-email-container').attr('allow_more_messages_fl')); 44882 44883 var msg1 = '<p>When text messages are sent to a large number of people, phone companies often start filtering the messages by blocking the messages completely or sending them to spam folders</p>'; 44884 var msg2 = '<p>To improve your messages deliverability we do several things including</p>'; 44885 44886 if (isApproveMore) { 44887 var acctReview = '', newCustomers = '', clientLimit = '5,000'; 44888 } else { 44889 var acctReview = 'if you receive a warning that you have a lower limit feel free to contact us: account reviews typically increase limits to the normal settings'; 44890 var newCustomers = '<p class="narrow-text">New ' + GLO.Info.getScheduleAnyoneHtm() + ' customers or high risk customers might have lower limits, ' + acctReview + '</p>'; 44891 var clientLimit = '1,000'; 44892 } 44893 44894 var optOut = '<ul style="margin-bottom: 0;"><li>This lets the phone company and clients know that clients who do not want the messages can easily opt-out</li>' 44895 + '<li>Of course, always do everything possible to not send message to clients who do not want it</li></ul>'; 44896 44897 var li1 = '<li>Before sending the message, we give you a deliverability score to help you check if any words or phrases in your text message are red flags to phone companies</li>'; 44898 var li2 = '<li>At the end of every message <b class="narrow-text" style="color: deeppink;">Reply STOP 2 opt out</b> is automatically added' + optOut + '</li>'; 44899 var li3 = '<li>Limit the number of messages that can be sent to the same phone number</li>'; 44900 var li4 = '<li>Limit the number of clients that can receive the same message to ' + clientLimit + ' clients' + newCustomers + '</li>'; 44901 var li5 = '<li>Work with the best text message delivery companies to improve successful delivery</li>'; 44902 var li6 = '<li>For each message we generate a deliverability score of 0-100, the higher the score the more likely the recepient will receive the message</li>'; 44903 44904 var list = '<ul>' + li1 + li2 + li3 + li4 + li5 + li6 + '</ul>'; 44905 var htm = '<div id="pop-help-text-deliverability">' + msg1 + msg2 + list + '</div>'; 44906 var jpop = GLO.Popup.Custom.openSimple(htm, 'Text Message Blast Deliverability Best Practices'); 44907 GLO.Popup.Custom.singleButton(jpop); 44908 } 44909 44910 _conBMsg.openHelpMMSPricing = function() { 44911 var isApproveMore = UTIL.parseBool($('#bulk-email-container').attr('allow_more_messages_fl')); 44912 var msg0 = '<p>MMS (Multimedia Messaging Service) is the standard protocol used to send longer text messages that may contain multimedia content like images. </p>'; 44913 var msg0Note ='<div style="padding: 20px;background-color:#cce5ff;color: black; border: solid #000;border-width: 0 0 0 3px;margin-right:8px;text-align:left;">MMS messages are charged per message part, while SMS messages are charged per message. Understanding what defines an MMS part will inform your understanding of how you will be billed and will help prevent accidental overages.</div><br/>'; 44914 var msg1 = '<p>MMS messages are charged per message segment. The character limit for a single MMS segment is 160 characters (GSM-7 encoding) or 70 characters (UCS-2 encoding) based on encoding type. While SMS messages can be joined together, messages longer than 160 characters are split by carriers prior to them being sent.</p>'; 44915 var msg1img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/mms-parts-pic.jpg" style="min-height: 250px; width: 90%; max-width: 800px; margin-bottom: 10px;"></div>'; 44916 var msg2 = '<p>The system will display the number of characters, number of segments and price just below the message box, so you can be aware of how many segments are being utilized and how it will impact your MMS blast pricing.</p>'; 44917 var msg2img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/mms-indicators.jpg" style="min-height: 220px; width: 90%; max-width: 500px; margin-bottom: 10px;"></div>'; 44918 var msg3 = '<p>The character encoding of your message determines the number of characters allowed per segment:</p>'; 44919 var li1Enc = '<li><b class="narrow-text">GSM-7 encoding:</b> Supports standard Latin characters and some special characters, allowing up to 160 characters per segment.</li>'; 44920 var li2Enc = '<li><b class="narrow-text">UCS-2 enconding:</b> Used for messages containing non-Latin characters or certain symbols <b>like emojis</b>, limiting each segment to 70 characters.</li>'; 44921 var listEnc = '<ul>' + li1Enc + li2Enc + '</ul>'; 44922 44923 var msg4 = '<p>Best Practices:</p>'; 44924 var li1BestPrac = '<li><b class="narrow-text">Keep Messages Concise:</b> Aim to stay within 1-2 MMS parts to optimize costs and delivery efficie
44924ncy.</li>'; 44925 var li2BestPrac = '<li><b class="narrow-text">Be Mindful of Encoding:</b> Be mindful of using special characters or emojis since they will trigger UCS-2 encoding and result in higher cost.</li>'; 44926 var li3BestPrac = '<li><b class="narrow-text">Utilize MMS Effectively:</b> Use Images with MMS but ensure file sizes are within supported limits (less than 1MB) to prevent delivery issues.</li>'; 44927 var listBestPrac = '<ul>' + li1BestPrac + li2BestPrac + li3BestPrac + '</ul>'; 44928 44929 var htm = '<div id="pop-help-text-deliverability">' + msg0 + msg0Note + msg1 + msg1img + msg2 + msg2img + msg3 + listEnc + msg4 + listBestPrac + '</div>'; 44930 var jpop = GLO.Popup.Custom.openSimple(htm, 'MMS Pricing & Deliverability Best Practices'); 44931 GLO.Popup.Custom.singleButton(jpop); 44932 } 44933 44934 function _initForMobile() { 44935 if (innerWidth < 500) { 44936 $('#filter-not-seen-since').attr('placeholder', 'Not Seen Since'); 44937 } 44938 } 44939 44940 function _initNonAdmin() { 44941 GLO.Info.init(); 44942 44943 if (GLO.Info.roleType < 210) { 44944 $('#filter-service').find('option[value="-1"]').remove(); 44945 _initClientList(); 44946 } 44947 } 44948 44949 function _initExistingMessage() { 44950 var j = $('#bulk-email-container'); 44951 var mbid = j.find('#Message_Bulk_id').val(); 44952 //var sentDate = j.find('#bulk-email-sent-date').attr('value'); 44953 44954 if (!_isEditableMsg()) { // (!UTIL.isEmpty(sentDate)) { 44955 j.find('input').prop('disabled', true); 44956 } 44957 44958 if (!UTIL.isEmpty(mbid)) { 44959 return true; 44960 } else { 44961 return false; 44962 } 44963 } 44964 44965 function _initMessageArea(fmtType) { 44966 var j = $('#be-top'); 44967 44968 if (j.length === 0) { 44969 $('#be-client-list').removeClass('hide'); 44970 return; 44971 } 44972 44973 var jfmt = $('#be-message-format .mobile-radio-button') 44974 var openMessage = (UTIL.parseBool(GLO.Uri.query('openMessage')) || UTIL.parseBool(GLO.Uri.query('openEmail')) || $('#Message_Bulk_id').val() > 0); 44975 var msgBody = j.find('#email-body-container .sa-text-editor')[0].innerHTML; 44976 44977 if (!openMessage && (msgBody.length > 8 || !UTIL.isEmpty(j.find('#Message_Bulk_id').val()))) { 44978 if (_getRemainingMessages(j) > 0) { 44979 openMessage = true; 44980 } 44981 } 44982 44983 if (openMessage && !$('#be-create-email-header').is(':visible')) { 44984 $('#be-create-email-header').click(); 44985 } 44986 44987 if (_isEditableMsg()) { 44988 jfmt.find('li').click(GLO.Message.Bulk.changeFormatType); 44989 jfmt.find('li[value="' + fmtType + '"]').click(); 44990 } else { 44991 jfmt.find('li[value="' + fmtType + '"]').addClass('selected'); 44992 _changeFormatType(fmtType); 44993 _initClientList(true); 44994 44995 if (fmtType == 1) { 44996 $('.sa-text-editor-menu').addClass('hide'); 44997 $('.sa-text-editor').attr('contenteditable', 'false'); 44998 } 44999 } 45000 45001 _conBMsg.monitorWidth(); 45002 setInterval(GLO.Message.Bulk.monitorWidth, 4900); 45003 } 45004 45005 function _isEditableMsg() { 45006 return $('#bulk-email-sent-date').length === 0 && $('#bulk-email-schedule-date').length == 0 && $('#bulk-email-in-progress').length == 0; 45007 } 45008 45009 _conBMsg.monitorWidth = function() { 45010 //var widthDoc = $('#doc3').width(); 45011 var j = $('#bulk-email-container'); 45012 var jmsg = j.find('.sa-text-editor'); 45013 45014 var widthMsg = jmsg.width(); 45015 var widthLabel = j.find('.be-message-body').outerWidth(); 45016 var widthBE = j.find('#be-top').width(); 45017 45018 if (widthMsg > widthBE - widthLabel - 10) { 45019 var mw = widthBE - widthLabel - 20 + 'px'; 45020 jmsg.css({ "max-width": mw }); 45021 } else if (widthBE > widthMsg) { 45022 var mw = widthBE - widthLabel - 20 + 'px'; 45023 jmsg.css({ "max-width": mw }); 45024 } 45025 } 45026 45027 function _initStaffDropDown(j) { 45028 var jstaff = j.find('#filter-staff').html(UserPortal.getStaffDropDown().html()); //var slist = '<option value="">(all staff)</option>' + UserPortal.getStaffDropDown().html(); 45029 jstaff.find('option[value=""]').remove(); 45030 45031 var ddInactive = j.find('#InactiveStaffList').find('option'); 45032 45033 if (ddInactive.length > 0) { 45034 var htmInactive = '<optgroup label="Inactive Staff">'; 45035 45036 for (var i = ddInactive.length - 1; i >= 0; i--) { 45037 htmInactive += ddInactive.eq(i).outerHTML(); 45038 } 45039 45040 jstaff.html('<optgroup label="Active Staff">' + jstaff.html() + '</optgroup>'); 45041 jstaff.prepend(htmInactive + '</optgroup>'); 45042 } 45043 45044 j.find('#InactiveStaffList').remove(); 45045 jstaff.prepend('<option value="" style="text-align: center;" selected="selected"> ( All Staff ) </option>'); 45046 } 45047 45048 function _initClientFilter() { 45049 var j = $('#ticket-type-filter'); 45050 var yearRange = GLO.UI.getYearRange(true); //'2012:' + (new Date().getFullYear() + 2); 45051 45052 _initStaffDropDown(j);
45053 j.find('#filter-brand').find('option:first').text('( ' + SA.Resource.AllBrands + ' )'); 45054 j.find('#filter-category').find('option:first').text('( ' + SA.Resource.AllCategories + ' )'); 45055 j.find('#filter-category').find('option:first').after('<option value="-1">At Least 1 Product Purchase</option>'); 45056 45057 j.find('#filter-start').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(1400), showCurrentAtPos: 1, changeYear: true, yearRange: yearRange }); 45058 j.find('#filter-end').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange }); 45059 j.find('#filter-not-seen-since').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange }); 45060 45061 var jclientRefer = j.find('#Referred_By_Client_id'); 45062 45063 if (jclientRefer.length) { 45064 UI.initAutoComplete(jclientRefer, GLO.Link.Object.Provider.ClientSearch); 45065 } 45066 45067 _initNeverHad(j); 45068 45069 if (j.find('#btnFilter').length === 0) { 45070 j.find('input, select').prop('disabled', true); 45071 } 45072 } 45073 45074 function _initNeverHad(j) { 45075 var noServiceTitle = 'Ignore clients that have had an appointment with this service'; 45076 var noProductTitle = 'Ignore clients who have bought these products'; 45077 var noService = UTIL.coalesce(GLO.Uri.url('noappt'), GLO.Uri.url('noclass'), GLO.Uri.url('noapptever'), GLO.Uri.url('noclassever')); 45078 45079 var jNeverHadService = '<select id="filter-never-had-service" title="' + noServiceTitle + '">' + j.find('#filter-service').html() + '</select>'; 45080 var jNeverHadProduct = '<select id="filter-never-had-product" title="' + noProductTitle + '">' 45081 + '<option value=""></option>' 45082 + '<option id="never-had-any-product" value="-1">Never Purchased Any Product</option>' 45083 + '<optgroup id="filter-never-had-brand" label="Never Purchased Product with Brand">' + j.find('#filter-brand').html() + '</optgroup>' 45084 + '<optgroup id="filter-never-had-category" label="Never Purchased Product in Category">' + j.find('#filter-category').html() + '</optgroup>' 45085 + '</select>'; 45086 45087 j.find('#filter-never-had-service').replaceWith(jNeverHadService); 45088 j.find('#filter-never-had-product').replaceWith(jNeverHadProduct); 45089 45090 if (noService == -2) { 45091 j.find('#filter-never-had-service').find('option:first').after('<option value="-2"> At Least 1 Class</option>'); 45092 } 45093 45094 j.find('#filter-never-had-service').find('option:first').html(''); 45095 j.find('#filter-never-had-service').find('option[value="1"]').attr('id', 'filter-never-any-service').html('Never Had Any Service'); 45096 45097 j.find('#filter-never-had-product').find('#filter-never-had-brand > option:first').remove(); 45098 j.find('#filter-never-had-product').find('#filter-never-had-category > option:first').remove(); 45099 } 45100 function _initClientFilterNarrowScreen() { //= some fields just too confusing on small UI 45101 if (innerWidth >= 400) { return; } 45102 45103 var j = $('#be-filter-client-area'); 45104 45105 j.find('li.bday-filter-container').remove(); 45106 j.find('li.filter-never-had-container').remove(); 45107 } 45108 function _initClientFilterData() { 45109 var j = $('#ticket-type-filter'); 45110 45111 j.find('#filter-first-name').val(UTIL.cleanString(GLO.Uri.url('fname'))); 45112 j.find('#filter-last-name').val(UTIL.cleanString(GLO.Uri.url('lname'))); 45113 45114 _initClientFilterDataElement(j, '#filter-staff', 'original_staff_id', null, 'staff'); 45115 _initClientFilterDataElement(j, '#filter-service', 'original_service_id', 'original_service_group_id', 'service'); 45116 _initClientFilterDataElement(j, '#filter-brand', 'original_vendor_id', 'original_pline_id', 'brand'); 45117 _initClientFilterDataElement(j, '#filter-category', 'original_category_id', 'original_category_type_id', 'category'); 45118 45119 _initClientFilterDataElement(j, '#filter-start', 'original_dt', null, 'start'); 45120 _initClientFilterDataElement(j, '#filter-end', 'original_dt', null, 'end'); 45121 _initClientFilterDataElement(j, '#filter-not-seen-since', 'original_dt', null, 'notsince'); 45122 45123 var noService = UTIL.coalesce(GLO.Uri.url('noappt'), GLO.Uri.url('noclass'), GLO.Uri.url('noapptever'), GLO.Uri.url('noclassever')); 45124 var noProduct = UTIL.coalesce(GLO.Uri.url('noproduct'), GLO.Uri.url('noproductever')); 45125 45126 if (noService) { j.find('#filter-never-had-service').val(noService); } 45127 if (noProduct) { j.find('#filter-never-had-product').val(noProduct); } 45128 45129 _initClientFilterBirthday(j); 45130 _initClientFilterTag(j); 45131 _initClientFilterRefer(j); 45132 _initClientFilterVisitCount(j); 45133 45134 j.find('#Zip_vc').val(GLO.Uri.url('zip')); 45135 45136 _initMinServiceAndProduct(j); 45137 _getProfileCreateQueryString(j, true); 45138 _initDefaultFilter(j); 45139 } 45140 function _initClientFilterVisitCount(j) { 45141 if (UTIL.parseBool(GLO.Uri.url('lastwithstaff')) && j.find('#Last_Visit_With_Staff_fl:visible').length) { 45142 j.find('#Last_Visit_With_Staff_fl').prop('checked', true); 45143 } 45144
45145 var wasNewClient = GLO.Uri.url('wasnewclient'); 45146 var min = GLO.Uri.url('minvisit'), max = GLO.Uri.url('maxvisit'), exact = GLO.Uri.url('exactvisit'); 45147 var jtype = j.find('#filter-visit-count-type'), jamount = j.find('#filter-visit-count'); 45148 45149 if (UTIL.parseBool(wasNewClient)) { 45150 j.find('#Was_New_Client_fl').prop('checked', true); 45151 } 45152 45153 if (UTIL.isNumber(min)) { 45154 j.find('#Min_Visit_sr').val(min); 45155 jamount.val(min); 45156 jtype.find('option[value="-1"]').prop('selected', true); 45157 } 45158 45159 if (UTIL.isNumber(max)) { 45160 j.find('#Max_Visit_sr').val(max); 45161 jamount.val(max); 45162 jtype.find('option[value="1"]').prop('selected', true); 45163 } 45164 45165 if (UTIL.isNumber(exact)) { 45166 jamount.val(exact); 45167 jtype.find('option[value="0"]').prop('selected', true); 45168 } 45169 } 45170 function _initClientFilterRefer(j) { 45171 j.find('#Provider_Referral_id').val(GLO.Uri.url('prefer')); 45172 45173 var clientReferId = GLO.Uri.url('crefer'); 45174 45175 if (UTIL.isNumber(clientReferId)) { 45176 var jreferClient = j.find('#Referred_By_Client_id').attr('autoid', clientReferId); 45177 _conBMsg.getClientNameForField(clientReferId, jreferClient); 45178 } 45179 } 45180 function _initClientFilterTag(j) { 45181 var tagType = GLO.Uri.url('tagtype'), tagRelate = UTIL.coalesce(GLO.Uri.url('tagrelationship'), 'both'), tagNote = UTIL.cleanString(GLO.Uri.url('tagnote')); 45182 45183 if (!UTIL.isEmpty(tagType)) { 45184 j.find('#Client_Tag_Type_id').val(tagType).change(); 45185 j.find('#Client_Tag_Relationship_cd').val(tagRelate); 45186 } 45187 45188 j.find('#Tag_Note_vc').val(tagNote); 45189 } 45190 function _initClientFilterBirthday(j) { 45191 j.find('#bday-start-month').val(GLO.Uri.url('bmonth1')); 45192 j.find('#bday-start-day').val(GLO.Uri.url('bday1')); 45193 j.find('#bday-end-month').val(GLO.Uri.url('bmonth2')); 45194 j.find('#bday-end-day').val(GLO.Uri.url('bday2')); 45195 } 45196 45197 _conBMsg.getClientNameForField = function(cid, jclient) { 45198 var url = GLO.Link.Object.Provider.Ajax + 'ClientQuick?id=' + cid; 45199 45200 $.ajax({ type: "GET", url: url, "cache": false }) 45201 .success( function(data, textStatus, jqXHR) { 45202 var jdata = $(data); 45203 var cname = jdata.attr('name'); 45204 45205 if (!UTIL.isEmpty(cname)) { 45206 jclient.val(cname); 45207 } 45208 }) 45209 .error( function(jqXHR, textStatus, errorThrown) { 45210 //GLO.UI.Form.resetProcessing(); 45211 }); 45212 } 45213 45214 function _initDefaultFilter(j) { 45215 var staffCount = j.find('#filter-staff').find('option').length; 45216 45217 if (UTIL.coalesceInt(staffCount) < 5) { return; } 45218 if (UTIL.parseBool(GLO.Uri.url('allclients'))) { return; } 45219 45220 var arrQS = window.location.search.substring(1).split('&'); 45221 var len = arrQS.length - 1; 45222 45223 if (arrQS.has('help')) { --len; } 45224 if (arrQS.has('highlight')) { --len; } 45225 if (arrQS.has('open')) { --len; } 45226 45227 if (arrQS.has('helloback')) { --len; } 45228 if (arrQS.has('openback')) { --len; } 45229 if (arrQS.has('pageback')) { --len; } 45230 45231 //if (arrQS.has('openEmail')) { --len; } 45232 //if (arrQS.has('format')) { --len; } 45233 45234 var quality = _filterSettingQuality(arrQS); 45235 45236 if (len < 1 && quality < 2) { 45237 if (staffCount > 9 && quality == 0) { 45238 var today = new Date(); 45239 var start = new Date(today.setMonth(today.getMonth() - 1)).toGloDate(); 45240 var end = new Date(today.setMonth(today.getMonth() + 1)).toGloDate(); 45241 45242 j.find('#filter-start').val(start); 45243 j.find('#filter-end').val(end); 45244 } 45245 45246 j.find('#filter-service').val(-1); 45247 } 45248 } 45249 45250 function _filterSettingQuality(arrQS) { 45251 if (arrQS.length > 0 && arrQS[0].split('=').length > 1) { 45252 var key = arrQS[0].split('=')[0].toLowerCase(); 45253 45254 if (key === 'staff' || key === 'crefer') { 45255 return 2; 45256 } else if (key === 'service' || key === 'brand' || key === 'category' || key === 'prefer' || key === 'minloyalty' 45257 || key === 'filter-first-name' || key === 'filter-last-name' || key === 'bday1' || key === 'zip' || key === 'tagrelationship' || key === 'tagtype') { 45258 return 1; 45259 } 45260 } 45261 45262 return 0; 45263 } 45264 45265 function _initMinServiceAndProduct(j) { 45266 var jsvc = j.find('#filter-service'); 45267 var jcat = j.find('#filter-category'); 45268 var minsvc = UTIL.coalesceInt(jsvc.attr('min_service_sr'), GLO.Uri.url('minservice')); 45269 var minproduct = UTIL.coalesceInt(jcat.attr('min_product_sr'), GLO.Uri.url('minproduct')); 45270 45271 if (minsvc > 0) { 45272 var jopt2 = jsvc.find('option').eq(1); 45273 45274 if (minsvc > 1) { 45275 jopt2.after('<option value="' + (-minsvc) + '">At Least ' + minsvc + ' Services</option>'); 45276 jsvc.find('option').eq(2).prop('selected', true) 45277 } else { 45278 jopt2.prop('selected', true); 45279 } 45280 } 45281 45282 if (minproduct > 0) { 45283 var jopt2 = jcat.find('option').eq(1); 45284 45285 if (minproduct > 1) { 45286 jopt2.after('<option value="' + (-minproduct) + '">At Least ' + minproduct + ' Product Purchases</option>'); 45287 jcat.find('option').eq(2).prop('selected', true); 45288 } else { 45289 jopt2.prop('selected', true); 45290 } 45291 } 45292 } 45293 45294 function _initClientFilterDataElement(j, selector, attribute1, attribute2, queryKey) { 45295 var val, jelement = j.find(selector); 45296 45297 if (!UTIL.isEmpty(attribute1)) { 45298 val = jelement.attr(attribute1); 45299 jelement.removeAttr(attribute1); 45300 } 45301 45302 if (UTIL.isEmpty(val) && !UTIL.isEmpty(attribute2)) { 45303 val = jelement.attr(attribute2); 45304 jelement.removeAttr(attribute2); 45305 } 45306 45307 if (UTIL.isEmpty(val) && !UTIL.isEmpty(queryKey)) { 45308 val = GLO.Uri.url(queryKey); 45309 } 45310 45311 if (!UTIL.isEmpty(val)) { 45312 if (attribute1 === 'original_dt') { 45313 val = new Date(val).toSADate(true); 45314 jelement.val(val); 45315 } else { 45316 jelement.val(val); 45317 } 45318 } 45319 } 45320 45321 function _initClientList(isLoading) { 45322 _pageNumber = 1;
45323 _pageCount = Math.ceil(_getActiveRows().length / 100); 45324 45325 if (isLoading || _isInitPage) { 45326 var jtbl = $('#be-client-list'); 45327 var sortArray = null; 45328 45329 if (_findSortColumn()) { 45330 sortArray = [_sortColumn, _sortDescending]; 45331 } 45332 45333 UI.initTableSorter(jtbl, sortArray, true); //jtbl.bind("sortStart",function() { $('#be-client-list tr.hide').removeClass('hide'); }); 45334 45335 jtbl.bind("sortEnd",function(event) { 45336 GLO.Message.Bulk.gotoPage(_pageNumber); 45337 }); 45338 } 45339 45340 return _setPage(true); 45341 } 45342 45343 function _findSortColumn() { 45344 if (!UTIL.isNumber(_sortColumn) && !UTIL.isEmpty(_sortColumn)) { 45345 var sortColumn = String(_sortColumn).toLowerCase(); 45346 var jhead = $('#be-client-list').find('thead > tr'); 45347 45348 if (sortColumn == 'client') { 45349 _sortColumn = jhead.find('.be-client-name').index(); 45350 } else if (sortColumn == 'icon') { 45351 _sortColumn = jhead.find('.be-icons').index(); 45352 } else if (sortColumn == 'phone') { 45353 _sortColumn = jhead.find('.be-phone-column').index(); 45354 } else if (sortColumn == 'email') { 45355 _sortColumn = jhead.find('.be-email-column').index(); 45356 } else { 45357 _sortColumn = jhead.find('.' + sortColumn).index(); 45358 } 45359 } 45360 45361 if (UTIL.isNumber(_sortColumn) && _sortColumn > 0) { 45362 _sortColumn = parseInt(_sortColumn); 45363 return true; 45364 } else { 45365 _sortColumn = _sortDescending = null; 45366 return false; 45367 } 45368 } 45369 45370 function _displayRemainingMessages(j, fmt) { 45371 var jremaining = j.find('#be-remaining-messages'); 45372 var jtotal = j.find('#be-total-monthly-messages'); 45373 var jbonus = j.find('#be-bonus-messages'); 45374 var bonusCount = UTIL.coalesceInt(jbonus.attr('bonus_count_sr'), 0); 45375 45376 if (fmt == 3) { 45377 var available = jremaining.attr('text_nr'), max = jtotal.attr('text_nr'); 45378 jbonus.text(UTIL.coalesceInt(bonusCount/3)); 45379 } else { 45380 var available = jremaining.attr('email_nr'), max = jtotal.attr('email_nr'); 45381 jbonus.text(bonusCount); 45382 } 45383 45384 jremaining.text(available); 45385 jtotal.text(max); 45386 } 45387 function _getRemainingMessages(jcontainer) { 45388 var jPayAsUse = jcontainer.find('#bmsg-per-message'); 45389 var jremaining = jcontainer.find('#be-remaining-messages'); 45390 var isText = (jcontainer.find('#Message_Format_cd').find('li.selected').attr('value') == 3); 45391 45392 if (jPayAsUse.length) { 45393 var jcontainer = $('#bulk-email-container'); 45394 var isMax = UTIL.parseBool(jcontainer.attr('allow_more_messages_fl')); 45395 var maxAllowedText = UTIL.coalesceInt(jcontainer.attr('max_text_allowed')); 45396 45397 if (isMax) { 45398 if (isText) { 45399 if (maxAllowedText > 0) { 45400 return maxAllowedText; 45401 } else { 45402 return 5000; 45403 } 45404 } else { 45405 return 15000; 45406 } 45407 } else { 45408 if (isText) { 45409 return 1000; 45410 } else { 45411 return 5000; 45412 } 45413 } 45414 } else if (isText) { 45415 var cnt = jremaining.attr('text_nr'); 45416 } else { 45417 var cnt = jremaining.attr('email_nr'); 45418 } 45419 45420 return UTIL.coalesceInt(cnt, 0); 45421 } 45422 45423 function _getActiveRows(forceEmailOnly, forceTextOnly) { 45424 var j = $('#bulk-email-container'); 45425 var jtbl = j.find('#be-client-list > tbody'); 45426 45427 if (forceEmailOnly || j.hasClass('accept-email-only')) { 45428 return jtbl.find('tr.accept-email'); 45429 } else if (forceTextOnly || (j.hasClass('accept-text-only'))) { // && GLO.Data.provider.textPackage < 10 45430 return jtbl.find('tr.accept-text'); 45431 } else { 45432 return jtbl.find('tr'); 45433 } 45434 } 45435 45436 function _displayMoreInfoPopup(actionType, reason2) { 45437 if (actionType === 'email-blast' || actionType === 'email-followup') { 45438 var h1 = SA.Resource.CustomerMarketing; 45439 var msg = SA.Resource.MarketingHelp + '<br/><br/>' + SA.Resource.MarketingHelp2; 45440 } else { //if (actionType === 'mobile-app') { 45441 var h1 = GLO.Data.provider.name + ' iPhone App'; 45442 var msg = '<div style="text-align: left;">' 45443 + '<div style="">Want your business to have it\'s own iPhone / iPad app where customers can view your services, book appointments, etc?</div><br/>' 45444 + '<div style="text-align: center;">We can help!</div><br/>' 45445 + '<div style=" margin-bottom: 10px;">Contact us to get started creating your very own iPhone app your customers can use</div>' 45446 + '<div style="">If you have any special requests you can enter them below</div>'; 45447 + '</div>'; 45448 } 45449 45450 var msg = $('<div id="pop-request-more-info" style="padding-left: 6px; padding-right: 2px;"> <h1 action_type_vc="' + actionType + '" class="friendly-msg2">' + h1 + '</h1>' 45451 + '<div style="max-width: 500px; letter-spacing: 1px; line-height: 180%;">' + msg + '</div>' 45452 + '<div> <textarea id="More_Info_vc" maxlength="2000" placeholder="' + SA.Resource.SpecialRequests + '"></textarea> </div>' 45453 + '</div>'); 45454 45455 var jpop = new GLO.Popup.Custom(msg, function() { 45456 GLO.Message.Bulk.sendPleaseContact(actionType, false); 45457 }).getPopup().addClass('no-persist'); 45458 45459 jpop.find('.btnSave').css({ "float": "right", "margin-left": "0", "text-align": "center" }).find('> a').text('Ok'); 45460 jpop.find('.btnCancel').css({ "width": "80px" }).find('> a').css({ "letter-spacing": "2px" }).click(function() { 45461 GLO.Message.Bulk.sendPleaseContact(actionType, true, reason2); 45462 });
45463 } 45464 45465 _conBMsg.sendPleaseContact = function(actionType, isIgnore, note) { 45466 var jpop = $('#pop-request-more-info').closest('.glopop'); 45467 var note2 = jpop.find('#More_Info_vc').val(); 45468 45469 if (!UTIL.isEmpty(note) && !UTIL.isEmpty(note2)) { note = note2 + ': ' + note; } 45470 45471 note = UTIL.htmlEncode(note, note2); 45472 45473 var url = GLO.Link.WebsiteDomain + "log/NotifySA"; 45474 var jd = { "isIgnore": UTIL.parseBool(isIgnore), "action_type_vc": actionType, "note_vc": note }; 45475 45476 GLO.Popup.close(jpop); 45477 45478 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 45479 .success(function (data, textStatus, jqXHR) { 45480 45481 }) 45482 .error(function (jqXHR, textStatus, errorThrown) { 45483 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 45484 }) 45485 } 45486 45487 _conBMsg.gotoUpgrade = function(btn, reason, reason2, helloback) { 45488 if (GLO.Info.isIosApp) { 45489 _displayMoreInfoPopup(reason, reason2); 45490 return; 45491 } 45492 45493 var j = $('#be-top'); 45494 var btnSave = j.find('#be-message-body3 #btnSaveForLater > a'); 45495 var jbody = j.find('#email-body-container .sa-text-editor'); 45496 var body = null, timeoutDelay = 600; 45497 45498 if (jbody.length > 0) { 45499 body = jbody[0].innerHTML; 45500 } 45501 45502 if (!UI.borderIsTransparent(btnSave) && body.length > 20) { 45503 var jsubject = j.find('#Subject_vc'); 45504 45505 if (UTIL.isEmpty(jsubject.val())) { 45506 jsubject.val('Subject'); 45507 } 45508 45509 btnSave.click(); 45510 timeoutDelay = 1200; 45511 } 45512 45513 if (btn) { 45514 btn = $(btn).parent(); 45515 GLO.UI.Form.beginProcessing(btn); 45516 } 45517 45518 setTimeout(function() { 45519 var url = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=' + UTIL.cleanString(reason); 45520 45521 if (helloback) { url += '&helloback=' + helloback; } 45522 45523 document.location = url; 45524 }, 600); 45525 } 45526 45527 _conBMsg.removeBulk = function(element) { 45528 var btn = $(element).parent(); 45529 var tr = btn.closest('tr').addClass('prep-remove'); 45530 45531 var msg = $('<div> <h1 class="friendly-msg2">' + SA.Resource.DeleteMessage + '</h1> <div class="friendly-msg2">' + SA.Resource.DeleteMessageConfirm + '</div> </div>'); 45532 45533 var oj = new GLO.Popup.Confirm(msg, GLO.Message.Bulk.removeBulkConfirmed, function() { 45534 tr.removeClass('prep-remove'); 45535 GLO.Popup.close(); 45536 }); 45537 45538 var jpop = oj.getPopup(); 45539 var jbtn = jpop.find('.pop-buttons'); 45540 } 45541 45542 _conBMsg.removeBulkConfirmed = function() { 45543 var tr = $('tr.prep-remove'); 45544 var btn = tr.find('#btnTrashBin > a'); 45545 var id = tr.attr('message_bulk_id'); 45546 var uri = GLO.Link.WebsiteDomain + 'message/BulkRemove?id=' + id; 45547 45548 GLO.UI.Form.beginProcessing(btn); 45549 45550 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } }) 45551 .success(function(data, textStatus, jqXHR) { 45552 tr.remove(); 45553 GLO.UI.Form.resetProcessing(btn); 45554 }) 45555 .error(function(jqXHR, textStatus, errorThrown) { 45556 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 45557 tr.removeClass('prep-remove'); 45558 }); 45559 } 45560 45561 function _setPage(isInit) { 45562 var tbl = $('#be-client-list'); 45563 var rows = _getActiveRows(); //tbl.find('tbody > tr'); 45564 var clientCount = rows.length; 45565 var isEmailOnly = $('#Include_Email_Only_fl').prop('checked'); 45566 var isTextOnly = false; // $('#Include_Text_Only_fl').prop('checked'); 45567 45568 if (rows.length > 150) { 45569 for (var i = _pageNumber * 100; i < rows.length; i++) { 45570 rows.eq(i).addClass('hide'); 45571 //if (isEmailOnly && _hasEmail(tr)) { ++clientCount; } 45572 } 45573 45574 if (_pageNumber > 1) { 45575 for (var i = 0; i < _pageNumber * 100; i++) { 45576 rows.eq(i).addClass('hide'); 45577 //if (isEmailOnly && _hasEmail(tr)) { ++clientCount; } 45578 } 45579 } 45580 45581 for (var i = (_pageNumber -1) * 100; i < _pageNumber * 100; i++) { 45582 rows.eq(i).removeClass('hide'); 45583 //if (isEmailOnly && _hasEmail(tr)) { ++clientCount; } 45584 } 45585 45586 _setPageControl(tbl, rows.length); 45587 //if (!isEmailOnly) { clientCount = rows.length; } 45588 } else { 45589 $('#sa-page-control').remove(); 45590 45591 /* 45592 if (isInit && isEmailOnly) { 45593 for (var i = 0; i < rows.length; i++) { 45594 if (isEmailOnly && _hasEmail(rows.eq(i))) { ++clientCount; } 45595 } 45596 } else { 45597 clientCount = rows.length; 45598 } 45599 */ 45600 } 45601 45602 if (isInit || rows.length > 150) { 45603 var msg = clientCount + ' ' + SA.Resource.Clients.toLowerCase(); 45604 45605 if (clientCount === 0) { 45606 clientCount = $('#bulk-sent-client-list').find('tbody tr').length; 45607 45608 if (clientCount > 0) { 45609 msg = '<i style="letter-spacing: 0;">Sent to ' + UTIL.numberWithCommas(clientCount) + ' ' + SA.Resource.Clients + '</i>'; 45610 } 45611 } 45612 45613 if (!GLO.Info.isMobile()) { 45614 if (isEmailOnly) { 45615 msg += ' ' + SA.Resource.with_email; 45616 } else if (isTextOnly) { 45617 msg += ' ' + SA.Resource.with_text; 45618 } 45619 } 45620 45621 $('#be-filter-client-header').find('.quieter').html(msg); 45622 } 45623 45624 tbl.removeClass('hide'); 45625 return clientCount; 45626 } 45627 45628 function _hasEmail(tr) { 45629 if (tr.hasClass('accept-email')) { // if (!UTIL.isEmpty(tr.find('.be-email').text())) { 45630 return true; 45631 } else { 45632 return false; 45633 } 45634 } 45635 45636 function _setPageControl(tbl, rowCount) { 45637 //var prev = '<i class="fa fa-chevron-circle-left" onclick="GLO.Message.Bulk.prevPage()"></i>'; 45638 //var next = '<i class="fa fa-chevron-circle-right" onclick="GLO.Message.Bulk.nextPage()"></i>'; 45639 45640 if (_pageNumber < 2) { 45641 var prev = '<i class="fa fa-arrow-circle-left hide" onclick="GLO.Message.Bulk.prevPage()"></i>'; 45642 } else { 45643 var prev = '<i class="fa fa-arrow-circle-left" onclick="GLO.Message.Bulk.prevPage()"></i>'; 45644 } 45645 45646 if (_pageNumber >= _pageCount) { 45647 var next = '<i class="fa fa-arrow-circle-right hide" onclick="GLO.Message.Bulk.nextPage()"></i>'; 45648 } else { 45649 var next = '<i class="fa fa-arrow-circle-right" onclick="GLO.Message.Bulk.nextPage()"></i>'; 45650 } 45651 45652 var cntItem = '<span id="sa-page-control-client-count" style="position: absolute; left: 8px; bottom: 0; margin: 4px;">' + rowCount + ' ' + SA.Resource.Clients.toLowerCase() + '</span>'; 45653 var htm = '<div id="sa-page-control">' + cntItem + '<div id="sa-page-control-center">' + prev + '<span>page ' + _pageNumber + ' of ' + _pageCount + '</span>' + next + '</div> </div>'; 45654 45655 if ($('#sa-page-control').length > 0) { 45656 $('#sa-page-control').html($(htm).html()); 45657 } else { 45658 tbl.after(htm); 45659 } 45660 } 45661 45662 _conBMsg.prevPage = function() { 45663 if (_pageNumber > 1) { 45664 _conBMsg.gotoPage(_pageNumber - 1); 45665 } 45666 } 45667 45668 _conBMsg.nextPage = function() { 45669 if (_pageNumber < _pageCount) { 45670 _conBMsg.gotoPage(_pageNumber + 1); 45671 } 45672 } 45673 45674 _conBMsg.gotoPage = function(pageNumber) { 45675 _pageNumber = pageNumber; 45676 _setPage(); 45677 } 45678 45679 _conBMsg.clearDate = function(dateString) { 45680 var j = $('#ticket-type-filter'); 45681 45682 if (dateString === 'start') { 45683 j.find('#filter-start').val(''); 45684 } else if (dateString === 'end') { 45685 j.find('#filter-end').val(''); 45686 } else if (dateString === 'bday-start') { 45687 j.find('#bday-start').val(''); 45688 } else if (dateString === 'bday-end') { 45689 j.find('#bday-end').val(''); 45690 } else if (dateString === 'not-seen') { 45691 j.find('#filter-not-seen-since').val(''); 45692 } else { 45693 j.find('#' + dateString).val(''); 45694 } 45695 } 45696 45697 _conBMsg.changeFormatType = function() { 45698 UI.changeMobileSelect.call(this); 45699 45700 var fmtType = $(this).attr('value'); 45701 _changeFormatType(fmtType); 45702 } 45703 45704 function _changeFormatType(fmtType) { 45705 var btns = $('#be-message-body3'); 45706 var isCreateMessageOpen = $('#be-top').is(':visible'); 45707 _conBMsg.destroyMMSIndicators(); 45708 45709 if (fmtType == 1) { 45710 var jc = $('#bulk-email-container').removeClass('accept-text-only').removeClass('accept-mms-only'); 45711 45712 if (isCreateMessageOpen) { jc.addClass('accept-email-only'); } 45713 45714 var trHide = $('#bmsg-include-only-text').addClass('hide'); 45715 var trShow = $('#bmsg-include-only-email').removeClass('hide'); 45716 45717 $('#be-message-body-text, #be-message-body-text-info').addClass('hide'); 45718 $("#be-message-body-text-info").css("margin-top", ""); 45719 $('#be-message-body-mms').addClass('hide'); 45720 $('#be-message-body-email').removeClass('hide'); 45721 45722 $('#be-message-body-email-info').removeClass('hide'); 45723 $('#bmsg-include-client-username').removeClass('hide'); 45724 45725 btns.find('#btnSendSample').addClass('hide'); 45726 btns.find('#btnPreview').removeClass('hide'); 45727 btns.find('#btnMMSPreview').addClass('hide'); 45728 $('#mms-pricing-help').addClass('hide'); 45729 45730 } else if (fmtType == 3) { //sms 45731 var jc = $('#bulk-email-container').removeClass('accept-email-only').removeClass('accept-mms-only'); 45732 45733 if (isCreateMessageOpen || $('#Message_Bulk_id').val() > 0) { 45734 jc.addClass('accept-text-only'); 45735 } 45736 45737 var trHide = $('#bmsg-include-only-email').addClass('hide'); 45738 var trShow = $('#bmsg-include-only-text').removeClass('hide').prop('checked', false); 45739 45740 //if (GLO.Data.provider.textPackage > 9) { trShow.prop('checked', false); } 45741 45742 $('#bmsg-include-client-username').addClass('hide'); 45743 $('#be-message-body-text, #be-message-body-text-info').removeClass('hide'); 45744 $("#be-message-body-text-info").css("margin-top", ""); 45745 $('#be-message-body-email-info').addClass('hide'); 45746 $('#be-message-body-email').addClass('hide'); 45747 $('#be-message-body-mms').addClass('hide'); 45748 45749 btns.find('#btnPreview').addClass('hide'); 45750 btns.find('#btnSendSample').removeClass('hide'); 45751 btns.find('#btnMMSPreview').addClass('hide'); 45752 $('#mms-pricing-help').addClass('hide'); 45753 45754 } else { //mms 45755 var jc = $('#bulk-email-container').removeClass('accept-email-only').removeClass('accept-text-only'); 45756 45757 if (isCreateMessageOpen || $('#Message_Bulk_id').val() > 0) { 45758 jc.addClass('accept-mms-only'); 45759 } 45760 45761 var trHide = $('#bmsg-include-only-email').addClass('hide'); 45762 var trShow = $('#bmsg-include-only-text').removeClass('hide').prop('checked', false); 45763 45764 //if (GLO.Data.provider.textPackage > 9) { trShow.prop('checked', false); } 45765 45766 $('#bmsg-include-client-username').addClass('hide'); 45767 $('#be-message-body-mms, #be-message-body-text-info').removeClass('hide'); 45768 $('#be-message-body-email-info').addClass('hide'); 45769 $('#be-message-body-email').addClass('hide'); 45770 $('#be-message-body-text').addClass('hide'); 45771 $("#be-message-body-text-info").css("margin-top", "70px"); 45772 45773 btns.find('#btnPreview').addClass('hide'); 45774 btns.find('#btnSendSample').removeClass('hide'); 45775 btns.find('#btnMMSPreview').removeClass('hide'); 45776 $('#mms-pricing-help').removeClass('hide'); 45777 45778 45779 _conBMsg.initMMSIndicators(); 45780 $('#mms_text_vc').keyup(); 45781 } 45782 45783 _displayRemainingMessages(jc, fmtType); 45784 trHide.find(':checkbox').prop('checked', false); 45785 45786 if (isCreateMessageOpen) {
45787 trShow.find(':checkbox:visible').prop('checked', true); 45788 } 45789 45790 _conBMsg.onlyClientsWithEmail(); 45791 } 45792 45793 _conBMsg.toggleFilterArea = function() { 45794 var h2 = $('#be-filter-client-header'); 45795 var h2click = $('#be-click-to-filter-client'); 45796 var j = $('#be-filter-client-area'); 45797 45798 if (j.hasClass('hide')) { 45799 h2click.addClass('hide'); 45800 h2.removeClass('hide'); //h2.find('.fa-plus-circle').removeClass('fa-plus-circle').addClass('fa-minus-circle'); 45801 45802 j.removeClass('hide'); 45803 } else { 45804 h2.addClass('hide'); //h2.find('.fa-minus-circle').removeClass('fa-minus-circle').addClass('fa-plus-circle'); 45805 h2click.removeClass('hide'); 45806 45807 $('#ui-datepicker-div').css('display', 'none'); 45808 j.addClass('hide'); 45809 } 45810 } 45811 45812 _conBMsg.toggleMessageArea = function() { 45813 var h2 = $('#be-create-email-header'); 45814 var j = $('#be-top') 45815 var h2click = $('#be-click-to-write-email'); 45816 45817 if (j.hasClass('hide')) { 45818 h2.removeClass('hide'); //h2.find('.fa-plus-circle').removeClass('fa-plus-circle').addClass('fa-minus-circle'); 45819 j.removeClass('hide'); 45820 h2click.addClass('hide'); 45821 } else { 45822 h2.addClass('hide'); //h2.find('.fa-minus-circle').removeClass('fa-minus-circle').addClass('fa-plus-circle'); 45823 j.addClass('hide'); 45824 h2click.removeClass('hide'); 45825 } 45826 } 45827 45828 _conBMsg.onlyClientsWithEmail = function() { 45829 var i=0, clientCount = 0, trs = $('#be-client-list').find('tbody > tr'); 45830 var isEmailOnly = $('#Include_Email_Only_fl:visible').prop('checked'); 45831 45832 if (isEmailOnly) { 45833 $('#bulk-email-container').addClass('accept-email-only'); 45834 45835 for (; i < trs.length; i++) { 45836 if (trs.eq(i).find('.be-email').text() === '') { 45837 trs.eq(i).addClass('hideX'); 45838 } else { 45839 trs.eq(i).removeClass('hideX'); 45840 ++clientCount; 45841 } 45842 } 45843 45844 /* 45845 var jEmailHeader = $('#be-client-list .be-email-column'); 45846 45847 if (!jEmailHeader.hasClass('headerSortUp')) { 45848 jEmailHeader.click(); 45849 45850 if (trs.length > 2 && !jEmailHeader.hasClass('headerSortDown')) { 45851 var ojProcessing = new GLO.Popup.Processing('Loading Only Clients with Email Addresses...'); 45852 45853 setTimeout(function() { 45854 ojProcessing.close(); 45855 $('#be-client-list .be-email-column').click(); 45856 }, 1500); 45857 } 45858 } 45859 */ 45860 } else { 45861 $('#bulk-email-container').removeClass('accept-email-only'); 45862 45863 for (; i < trs.length; i++) { 45864 trs.eq(i).removeClass('hideX'); 45865 } 45866 45867 clientCount = i; 45868 } 45869 45870 var msg = clientCount + ' ' + SA.Resource.Clients.toLowerCase(); 45871 if (isEmailOnly && !GLO.Info.isMobile()) { msg += ' with email'; } 45872 45873 $('#be-filter-client-header').find('.quieter').text(clientCount + ' ' + SA.Resource.Clients.toLowerCase()); 45874 _initClientList(false); 45875 } 45876 45877 /* _conBMsg.onlyClientsWithText = function() { 45878 var trs = $('#be-client-list').find('tbody > tr'); 45879 45880 if ($('#Include_Text_Only_fl').prop('checked')) { 45881 $('#bulk-email-container').addClass('accept-text-only'); 45882 45883 for (var i=0; i < trs.length; i++) { 45884 if (trs.eq(i).hasClass('accept-text').length === 0) { 45885 trs.eq(i).addClass('hideX'); 45886 } else { 45887 trs.eq(i).removeClass('hideX'); 45888 } 45889 } 45890 } else { 45891 $('#bulk-email-container').removeClass('accept-text-only'); 45892 45893 for (var i=0; i < trs.length; i++) { 45894 trs.eq(i).removeClass('hideX'); 45895 } 45896 } 45897 45898 _initClientList(false); //_conBMsg.gotoPage(_pageNumber); 45899 } */ 45900 45901 /* _conBMsg.changeUrl = function(qs) { 45902 if (window.history.pushState) { 45903 var url = window.location.origin + window.location.pathname + '?' + qs; 45904 45905 window.history.pushState({ "pageTitle": "Client List" } , "", url); 45906 } 45907 } */ 45908 45909 _conBMsg.changeEndDate = function(element) { 45910 var jfilter = $('#ticket-type-filter'); 45911 var dtEnd = element.value; 45912 var jNotSince = jfilter.find('#filter-not-seen-since'); 45913 var dtNotSince = jNotSince.val(); 45914 45915 if (UTIL.isDate(dtEnd) && UTIL.isDate(dtNotSince)) { 45916 if (new Date(dtEnd) > new Date(dtNotSince)) {
45917 var newNotSince = new Date(dtEnd).toGloDate(); 45918 jNotSince.val(newNotSince).focus(); 45919 UI.highlight(jNotSince, 1200, 6400, false); 45920 } 45921 } 45922 } 45923 function _filterIsValid(start, end, notSince) { 45924 var jfilter = $('#ticket-type-filter'); 45925 45926 if (UTIL.isDate(start) && !UTIL.isDate(end)) { 45927 end = new Date().toGloDate(); 45928 jfilter.find('#filter-end').val(end); 45929 } 45930 45931 if (new Date(start) > new Date(end)) { 45932 var msg = '<h1 class="friendly-quick-msg">' + SA.Resource.InvalidDates + '</h1> <div class="friendly-quick-msg">' + SA.Resource.StartDateWarning + '</div>'; 45933 new GLO.Popup.Warning(msg, function() { $('#ticket-type-filter').find('#filter-not-since').focus(); }); 45934 return false; 45935 } else if (UTIL.isDate(notSince) && new Date(end) > new Date(notSince)) { 45936 if (new Date(notSince) > new Date(start)) { 45937 end = new Date(notSince).toGloDate(); 45938 var jend = jfilter.find('#filter-end'); 45939 45940 jend.val(end); 45941 UI.highlight(jend, 1200, 6400, false); 45942 } else { 45943 var msg = '<h1 class="friendly-quick-msg">' + SA.Resource.InvalidDates + '</h1> <div class="friendly-quick-msg">' + SA.Resource.NotSeenSinceWarning + '</div>';
45944 new GLO.Popup.Warning(msg, function() { $('#ticket-type-filter').find('#filter-end').focus(); }); 45945 return false; 45946 } 45947 } 45948 45949 return true; 45950 } 45951 45952 function _getStaticQueryString() { 45953 var qs = ''; 45954 45955 var help = GLO.Uri.query('help'), highlight = GLO.Uri.query('highlight'), open = GLO.Uri.query('open'), helpstep = GLO.Uri.query('helpstep'); 45956 var helloback = GLO.Uri.query('helloback'), openback = GLO.Uri.query('openback'), pageback = GLO.Uri.query('pageback'); 45957 var openMessage = GLO.Uri.query('openMessage'); //, format = GLO.Uri.query('format'); 45958 45959 if (help) { qs += '&help=' + help; } 45960 if (highlight) { qs += '&highlight=' + highlight; } 45961 if (open) { qs += '&open=' + open; } 45962 if (helpstep) { qs += '&helpstep=' + helpstep; } 45963 45964 if (helloback) { qs += '&helloback=' + helloback; } 45965 if (openback) { qs += '&openback=' + openback; } 45966 if (pageback) { qs += '&pageback=' + pageback; } 45967 45968 if (openMessage) { qs += '&openMessage=' + openMessage; } 45969 45970 return qs; 45971 } 45972 45973 function _getQueryString(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct, isLastVisitWithStaff, fname, lname) { 45974 var qs = ''; 45975 45976 if (!UTIL.isEmpty(start)) { 45977 if (qs !== '') { qs += '&'; } 45978 45979 qs += 'start=' + start 45980 } 45981 45982 if (!UTIL.isEmpty(end)) { 45983 if (qs !== '') { qs += '&'; } 45984 45985 qs += 'end=' + end 45986 } 45987 45988 if (!UTIL.isEmpty(notSince)) { 45989 if (qs !== '') { qs += '&'; } 45990 45991 qs += 'notsince=' + notSince 45992 } 45993 45994 if (!UTIL.isEmpty(sid)) { 45995 if (qs !== '') { qs += '&'; } 45996 45997 qs += 'staff=' + sid 45998 } 45999 46000 if (!UTIL.isEmpty(svc)) { 46001 if (qs !== '') { qs += '&'; } 46002 46003 qs += 'service=' + svc 46004 } 46005 46006 if (!UTIL.isEmpty(brand)) { 46007 if (qs !== '') { qs += '&'; } 46008 46009 qs += 'brand=' + brand 46010 } 46011 46012 if (!UTIL.isEmpty(category)) { 46013 if (qs !== '') { qs += '&'; } 46014 46015 qs += 'category=' + category; 46016 } 46017 46018 var bulkId = UTIL.coalesceInt(GLO.Uri.query('id'), GLO.Uri.query('bulk_id')); 46019 46020 if (!UTIL.isEmpty(bulkId)) { 46021 if (qs !== '') { qs += '&'; } 46022 46023 qs += 'id=' + bulkId; 46024 } 46025 46026 if (UTIL.parseBool(isLastVisitWithStaff)) { 46027 if (qs !== '') { qs += '&'; } 46028 46029 qs += 'lastwithstaff=1'; 46030 } 46031 46032 qs = _getQueryStringKeyValue(qs, 'noappt', noAppt); 46033 qs = _getQueryStringKeyValue(qs, 'noclass', noClass); 46034 qs = _getQueryStringKeyValue(qs, 'noproduct', noProduct); 46035 46036 qs = _getQueryStringKeyValue(qs, 'noapptever', noApptEver) 46037 qs = _getQueryStringKeyValue(qs, 'noclassever', noApptEver); 46038 qs = _getQueryStringKeyValue(qs, 'noproductever', noProductEver); 46039 qs = _getQueryStringKeyValue(qs, 'minservice', minService); 46040 qs = _getQueryStringKeyValue(qs, 'minproduct', minProduct); 46041 46042 qs = _getQueryStringKeyValue(qs, 'fname', fname); 46043 qs = _getQueryStringKeyValue(qs, 'lname', lname); 46044 46045 return qs; 46046 } 46047 46048 function _getQueryStringKeyValue(qs, key, value) { 46049 if (!UTIL.isEmpty(value)) { 46050 if (qs !== '') { qs += '&'; } 46051 46052 qs += key + '=' + value; 46053 } 46054 46055 return qs; 46056 } 46057 46058 function _displaySearchSummary(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct 46059 , providerRefId, clientRefId, fname, lname, zip) { 46060 var jfilter = $('#be-filter-client-area'); 46061 var msg = _getSearchSummary_Appointment(jfilter, start, end, sid, svc, minService); 46062 msg += _getSearchSummary_Product(jfilter, start, end, brand, category, minProduct); 46063 msg += _getSearchSummary_Bday(jfilter); 46064 msg += _getSearchSummary_Tag(jfilter); 46065 46066 msg += _getSearchSummary_Profile(jfilter, fname, lname, zip); //name, date created, zip 46067 msg += _getSearchSummary_Loyalty(jfilter); 46068 msg += _getSearchSummary_Refer(jfilter, providerRefId, clientRefId); 46069 46070 msg += _getSearchSummary_NotSeenSince(jfilter, notSince); 46071 msg += _getSearchSummary_NoAppointment(jfilter, noAppt, noClass, noApptEver); 46072 msg += _getSearchSummary_NoProduct(jfilter, noProduct, noProductEver); 46073 46074 msg += _getEmailOrTextRestriction(); 46075 46076 //msg += _staticSearchSummary(); 46077 return _openSearchSummary(msg); 46078 } 46079 46080 function _staticSearchSummary() { 46081 var arrow = '<b class="more-info-arrow">➜</b>'; 46082 46083 return '<div id="search-summary-more-info">' + '<h5>More Information</h5>' 46084 + '<p><span onclick="GLO.Message.Bulk.openHelp()">Tips on managing your client list and sending your clients marketing messages' + arrow + '</span></p>' 46085 + '<p><span onclick="GLO.Message.Marketing.openHelp()">
46085Details of Emails & Texts ' + GLO.Info.getScheduleAnyoneHtm() + ' Sends' + arrow + '</span></p>' 46086 + '</div>'; 46087 } 46088 46089 function _getEmailOrTextRestriction() { 46090 var msg = '', jmsg = $('#be-top'); 46091 var fmt = jmsg.find('#Message_Format_cd').find('li.selected').attr('value'); 46092 46093 if (fmt == 3) { 46094 if (jmsg.find('#Include_Email_Only_fl').prop('checked')) { 46095 msg = 'Have an email address'; 46096 } 46097 //} else { 46098 // if (jmsg.find('#Include_Text_Only_fl').prop('checked')) { 46099 // msg = 'Have opted-in to text messages'; 46100 // } 46101 } 46102 46103 return _getSearchSummaryRow(msg); 46104 } 46105 function _getSearchSummary_Bday(jfilter) { 46106 var mo1 = UTIL.coalesceInt(jfilter.find('#bday-start-month').val(), 0); 46107 var day1 = UTIL.coalesceInt(jfilter.find('#bday-start-day').val(), 1); 46108 var mo2 = UTIL.coalesceInt(jfilter.find('#bday-end-month').val(), 0); 46109 var day2 = UTIL.coalesceInt(jfilter.find('#bday-end-day').val(), 1); 46110 46111 if (mo1 === 0 || mo2 === 0 || mo1 > mo2) { 46112 return ''; 46113 } else { 46114 var d1 = new Date(new Date().setMonth(mo1 - 1)).getMonthString(true) + ' ' + day1; 46115 var d2 = new Date(new Date().setMonth(mo2 - 1)).getMonthString(true) + ' ' + day2; 46116 46117 var msg = 'Birthday between ' + d1 + ' - ' + d2; 46118 return _getSearchSummaryRow(msg); 46119 } 46120 } 46121 function _getSearchSummary_Tag(jfilter) { 46122 var tagType = jfilter.find('#Client_Tag_Type_id option:selected').text(); 46123 var jTagRelate = jfilter.find('#Client_Tag_Relationship_cd option:selected'); 46124 var tagNote = jfilter.find('#Tag_Note_vc').val(); 46125 var msg = ''; 46126 46127 if (!UTIL.isEmpty(tagType)) { 46128 tagType = '<b>' + tagType + '</b>'; 46129 46130 if (!UTIL.isEmpty(jTagRelate.val()) && jTagRelate.val() != 'both') { 46131 tagType += ' <small>(' + jTagRelate.text() + ')</small>'; 46132 } 46133 46134 if (!UTIL.isEmpty(tagNote)) { 46135 tagType += ' <small> and the tag note contains <i>"' + tagNote + '"</i></small>'; 46136 } 46137 46138 msg = 'Client has the tag: ' + tagType; 46139 } else if (!UTIL.isEmpty(tagNote)) { 46140 msg = 'Client has any tag where the tag note contains: <i>"' + tagNote + '"</i>'; 46141 } 46142 46143 return _getSearchSummaryRow(msg); 46144 } 46145 function _getSearchSummary_Profile(jfilter, fname, lname, zip) { 46146 var htm = '', msg = ''; 46147 var dt1 = jfilter.find('#profile-create-start').val(); 46148 var dt2 = jfilter.find('#profile-create-end').val(); 46149 46150 if (UTIL.isDate(dt1) && UTIL.isDate(dt2)) { 46151 msg = 'Client profiles created between ' + dt1 + ' and ' + dt2; 46152 } else if (UTIL.isDate(dt1)) { 46153 msg = 'Client profiles created after ' + dt1; 46154 } else if (UTIL.isDate(dt2)) { 46155 msg = 'Client profiles created before ' + dt2; 46156 } 46157 46158 if (!UTIL.isEmpty(fname)) { 46159 htm += _getSearchSummaryRow('First name starts with ' + fname); 46160 } 46161 46162 if (!UTIL.isEmpty(fname)) { 46163 htm += _getSearchSummaryRow('Last name starts with ' + fname); 46164 } 46165 46166 if (!UTIL.isEmpty(zip)) { 46167 htm += _getSearchSummaryRow('' + jfilter.find('#Zip_vc').attr('placeholder') + ' is ' + zip); 46168 } 46169 46170 return htm + _getSearchSummaryRow(msg); 46171 } 46172 function _getSearchSummary_Loyalty(jfilter) { 46173 var msg = '', min = jfilter.find('#Loyalty_Min_sr').val(), max = jfilter.find('#Loyalty_Max_sr').val(); 46174 46175 if (parseInt(min) > 0 && parseInt(max) >= 0) { 46176 msg = 'Loyalty point balance between ' + min + ' - ' + max; 46177 } else if (parseInt(min) > 0) { 46178 msg = 'More than ' + min + ' loyalty points'; 46179 } else if (parseInt(max) > 0) { 46180 msg = 'Less than ' + max + ' loyalty points'; 46181 } else if (parseInt(max) == 0) { 46182 msg = 'Zero loyalty points'; 46183 } 46184 46185 return _getSearchSummaryRow(msg); 46186 } 46187 function _getSearchSummary_Refer(jfilter, providerRefId, clientRefId) { 46188 var msg = ''; 46189 46190 if (providerRefId) { 46191 msg = 'Referred by ' + jfilter.find('#Provider_Referral_id option:selected').text(); 46192 } 46193 46194 //if (clientRefId) { msg = 'Clients referred by ' + ???; } 46195 46196 return _getSearchSummaryRow(msg); 46197 } 46198 function _getSearchSummary_Appointment(jfilter, start, end, sid, svc, minService) { 46199 var msg = '', appt = ' appointment ', isMobile = GLO.Info.isMobile(); 46200 46201 if (!UTIL.isEmpty(svc)) { 46202 msg += jfilter.find('#filter-service :selected').text() + appt; 46203 appt = ' '; 46204 } 46205 46206 if (!UTIL.isEmpty(sid)) { 46207 msg += appt + 'with ' + jfilter.find('#filter-staff :selected').text(); 46208 appt = ' '; 46209 } 46210 46211 if (UTIL.isDate(start) && UTIL.isDate(end)) { 46212 msg += appt + 'between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true); 46213 } else if (UTIL.isDate(start)) { 46214 msg += appt + 'since ' + new Date(start).toGloDateString(true, true, isMobile, isMobile) 46215 } else if (UTIL.isDate(end)) { 46216 msg += appt + 'before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile); 46217 } else if (minService > 0 && UTIL.isEmpty(msg)) { 46218 msg = 'At Least ' + UTIL.pluralLabel(minService, 'Service'); 46219 return _getSearchSummaryRow(msg); 46220 } 46221 46222 return _getSearchSummaryRow(msg); 46223 } 46224 46225 function _getSearchSummary_NotSeenSince(jfilter, notSince) { 46226 var msg = '', dtPretty = new Date(notSince).toGloDateString(true, true); 46227 46228 if (UTIL.isDate(notSince)) { 46229 if (GLO.Info.providerPackage === 1) { 46230 msg = 'Have not visited since ' + dtPretty; 46231 } else { 46232 msg = 'Have not had appointment or product purchase since ' + dtPretty; 46233 } 46234 } 46235 46236 return _getSearchSummaryRow(msg, true); 46237 } 46238 46239 function _getText(jfilter, isNeverHad, isService) { 46240 if (isNeverHad && isService) { 46241 var j = jfilter.find('#filter-never-had-service option:selected'); 46242 } else if (isNeverHad) { 46243 var j = jfilter.find('#filter-never-had-product option:selected'); 46244 } 46245 46246 if (UTIL.coalesceInt(j.val(), 0) < 0) { 46247 var text = ' any'; 46248 } else { 46249 var text = ' a ' + $.trim(j.text()); 46250 } 46251 46252 return text; 46253 } 46254 46255 function _getSearchSummary_NoAppointment(jfilter, noAppt, noClass, noApptEver) { 46256 var msg = ''; 46257 var serviceText = _getText(jfilter, true, true); 46258 46259 if (!UTIL.isEmpty(noAppt)) { 46260 msg = 'Have never had' + serviceText + ' appointment'; 46261 } else if (!UTIL.isEmpty(noClass)) { 46262 msg = 'Have never had' + serviceText + ' class reservation'; 46263 } else if (!UTIL.isEmpty(noApptEver)) { 46264 msg = 'Have never had an appointment'; 46265 } 46266 46267 return _getSearchSummaryRow(msg, true); 46268 } 46269 46270 function _getSearchSummary_Product(jfilter, start, end, brand, category, minProduct) {
46271 var msg = '', product = ' product ', isMobile = GLO.Info.isMobile(); 46272 46273 if (UTIL.isEmpty(brand) && UTIL.isEmpty(category)) { 46274 if (minProduct > 0) { 46275 var msg = 'At Least ' + UTIL.pluralLabel(minProduct, 'Product Purchase'); 46276 return _getSearchSummaryRow(msg); 46277 } else { 46278 return ''; 46279 } 46280 } 46281 46282 if (!UTIL.isEmpty(brand)) { 46283 msg += jfilter.find('#filter-brand :selected').text() + product; 46284 product = ' '; 46285 } 46286 46287 if (!UTIL.isEmpty(category)) { 46288 msg += jfilter.find('#filter-brand :selected').text() + product; 46289 product = ' '; 46290 } 46291 46292 if (UTIL.isDate(start) && UTIL.isDate(end)) { 46293 msg += product + 'between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true); 46294 } else if (UTIL.isDate(start)) { 46295 msg += product + 'since ' + new Date(start).toGloDateString(true, true, isMobile, isMobile) 46296 } else if (UTIL.isDate(end)) { 46297 msg += product + 'before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile); 46298 } 46299 46300 return _getSearchSummaryRow(msg); 46301 } 46302 46303 function _getSearchSummary_NoProduct(jfilter, noProduct, noProductEver) { 46304 var msg = ''; 46305 46306 if (!UTIL.isEmpty(noProduct)) { 46307 var productText = _getText(jfilter, true, false); 46308 msg = 'Have never purchased ' + productText + ' product'; 46309 } else if (!UTIL.isEmpty(noProductEver)) { 46310 msg = 'Have never purchased a product'; 46311 } 46312 46313 return _getSearchSummaryRow(msg, true); 46314 } 46315 46316 function _getSearchSummaryRow(msg, isNever) { 46317 if (msg !== '') { 46318 msg = $.trim(msg); 46319 msg = msg.substring(0,1).toUpperCase() + msg.substring(1); 46320 46321 if (isNever) { 46322 return '<li class="search-summary-not-since">' + msg + '</li>'; 46323 } else { 46324 return '<li>' + msg + '</li>'; 46325 } 46326 } 46327 46328 return msg; 46329 } 46330 46331 function _openSearchSummary(msg) { 46332 var isAddAllButton = false; 46333 46334 if (msg !== '') { 46335 var action = '<h6 id="search-summary-label"><b id="search-summary-action">Finding</b> Clients With<b id="search-summary-dots">...</b></h6>'; 46336 msg = action + '<ul>' + msg + '</ul>'; 46337 isAddAllButton = true; 46338 } else { 46339 msg = '<h6 id="search-summary-label"><b id="search-summary-action">Retrieving</b> <b>All Clients</b><b id="search-summary-dots">...</b></h6>'; 46340 } 46341 46342 var cssThrobber = 'height: 40px; width: 40px; margin: 0; margin-top: 12px;'; 46343 var throbber = '<div id="search-summary-throbber">' + GLO.Report.Template2.getBlueThrobber(cssThrobber) + '</div>'; 46344 46345 var htm = '<div id="search-summary">' + msg + throbber + '</div>'; 46346 var h1 = UTIL.coalesce(GLO.Uri.query('label'), 'Searching Client List'); 46347 var ojpop = GLO.Popup.Custom.open(htm, h1); 46348 var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": 0 }); 46349 GLO.Popup.Custom.singleButton(jpop); 46350 46351 var marginBottom = 100; 46352 46353 if (innerWidth < 550) { marginBottom = 120; } 46354 46355 var moreInfo = _staticSearchSummary(); 46356 var jbtns = jpop.find('.pop-buttons-parent').css({ "position": "relative", "margin-bottom": marginBottom + "px" }); 46357 jbtns.find('.btnSA').css({ "z-index": "100" }); 46358 jbtns.after(moreInfo); 46359 46360 if (innerWidth > 620) { 46361 jpop.css({ "min-width": "600px" }); 46362 } else if (innerWidth > 520) { 46363 jpop.css({ "min-width": "500px" }); 46364 } 46365 46366 if (isAddAllButton) { 46367 jbtns.find('.pop-buttons').append('<span id="search-summary-all-button" class="btnAdd"><a onclick="GLO.Message.Bulk.filterAllClients()">Display<br/>All Clients</a></span>'); 46368 } 46369 46370 jbtns.find('.pop-buttons').prepend('<span id="search-cancel-button" class="btnAdd"><a onclick="GLO.Message.Bulk.cancelSearch()">Cancel<br/>Search</a></span>'); 46371 ojpop.realign(); 46372 return ojpop; 46373 } 46374 46375 _conBMsg.changeTag = function(ddTagType) { 46376 ddTagType = $(ddTagType); 46377 var jtagName = ddTagType.find('option:selected'); 46378 var tagName = jtagName.text(); 46379 var relationship = jtagName.attr('relationship_name_vc'); 46380 var jtag = ddTagType.closest('#tag-filter-container'); 46381 var htmRelateOptions = ''; //var jTagRelationship = jtag.find('#tag-relationship-container'); 46382
46383 if (!UTIL.isEmpty(relationship)) { 46384 jtag.addClass('has-relationship'); 46385 //jTagRelationship.removeClass('hide').find('label').html('<small>include</small>' + relationship); 46386 46387 htmRelateOptions += '<option value="both">include both: ' + tagName + ' and ' + relationship + '</option>'; 46388 htmRelateOptions += '<option value="onlytag">only: ' + tagName + '</option>'; 46389 htmRelateOptions += '<option value="onlyrelate">only: ' + relationship + '</option>'; 46390 } else { 46391 //jTagRelationship.addClass('hide'); 46392 jtag.removeClass('has-relationship'); 46393 } 46394 46395 jtag.find('#Client_Tag_Relationship_cd').html(htmRelateOptions); 46396 } 46397 46398 _conBMsg.cancelSearch = function(isSearchAll) { 46399 GLO.Popup.close( $('#search-summary').closest('.glopop') ); 46400 UTIL.abortAjaxRequest(_currentFilterAjax, true, !isSearchAll); 46401 } 46402 _conBMsg.filterAllClients = function() { 46403 _conBMsg.cancelSearch(true); 46404 $('#ticket-type-filter').find('input,select').val(''); 46405 GLO.Message.Bulk.filter(); 46406 } 46407 46408 _conBMsg.getTagQueryString = function(jfilter) { 46409 if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10 && GLO.Info.providerPackage != 20) { return ''; } 46410 46411 var qs = ''; 46412 var tagTypeId = jfilter.find('#Client_Tag_Type_id').val(); 46413 var tagRelationship = jfilter.find('#Client_Tag_Relationship_cd:visible').val(); 46414 var tagNote = jfilter.find('#Tag_Note_vc:visible').val(); 46415 46416 if (!UTIL.isEmpty(tagTypeId)) { 46417 qs += '&tagtype=' + tagTypeId; 46418 46419 if (tagRelationship) { 46420 qs += '&tagrelationship=' + tagRelationship; 46421 } 46422 } 46423 46424 if (!UTIL.isEmpty(tagNote)) { 46425 qs += '&tagnote=' + tagNote; 46426 } 46427 46428 return qs; 46429 } 46430 function _getProfileCreateQueryString(jfilter, isInit) { 46431 var dt1 = jfilter.find('#profile-create-start').val(); 46432 var dt2 = jfilter.find('#profile-create-end').val(); 46433 46434 if (isInit) { 46435 dt1 = UTIL.coalesceDate(dt1, GLO.Uri.query('profile-create1')); 46436 dt2 = UTIL.coalesceDate(dt2, GLO.Uri.query('profile-create2')); 46437 } 46438 46439 if (!UTIL.isEmpty(dt1) || !UTIL.isEmpty(dt2)) { 46440 var yearRange = GLO.UI.getYearRange(true); //'2012:' + (new Date().getFullYear()); 46441 46442 jfilter.find('.profile-create-container').removeClass('hideX'); 46443 jfilter.find('#profile-create-start').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(1400), showCurrentAtPos: 1, changeYear: true, yearRange: yearRange }); 46444 jfilter.find('#profile-create-end').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange }); 46445 46446 return '&profile-create1=' + dt1 + '&profile-create2=' + dt2; 46447 } 46448 46449 return ''; 46450 } 46451 function _getVisitCountQueryString(jfilter) { 46452 var jmin = jfilter.find('#Min_Visit_sr'), jmax = jfilter.find('#Max_Visit_sr'); 46453 var exact, min, max, qs = ''; 46454 46455 if (jmin.length || jmax.length) { 46456 min = jmin.val(); 46457 max = jmax.val(); 46458 } else { 46459 var countType = jfilter.find('#filter-visit-count-type').val(); 46460 var countAmount = jfilter.find('#filter-visit-count').val(); 46461 46462 if (countType == 1) { 46463 max = countAmount; 46464 } else if (countType == -1) { 46465 min = countAmount; 46466 } else if (countType == 0) { 46467 exact = countAmount; 46468 } 46469 } 46470 46471 if (!UTIL.isEmpty(min)) { 46472 qs += '&minvisit=' + min; 46473 } 46474 if (!UTIL.isEmpty(max)) { 46475 qs += '&maxvisit=' + max; 46476 } 46477 if (!UTIL.isEmpty(exact)) { 46478 qs += '&exactvisit=' + exact; 46479 } 46480 46481 return qs; 46482 } 46483 function _getLoyaltyQueryString(jfilter, isInit) { 46484 var jmin = jfilter.find('#Loyalty_Min_sr'), jmax = jfilter.find('#Loyalty_Max_sr'); 46485 var min = jmin.val(), max = jmax.val(); 46486 46487 var qs = ''; 46488 46489 if (jmin.length && parseInt(min) >= 0) { 46490 qs += '&minloyalty=' + min; 46491 } 46492 46493 if (jmax.length && parseInt(max) >= 0) { 46494 qs += '&maxloyalty=' + max; 46495 } 46496 46497 return qs 46498 } 46499 function _getProfileReferAndZip(jfilter, providerRefId, clientRefId, zip) { 46500 var qs = ''; 46501 46502 if (!UTIL.isEmpty(providerRefId)) { 46503 qs += '&prefer=' + providerRefId; 46504 } 46505 46506 if (!UTIL.isEmpty(clientRefId)) { 46507 qs += '&crefer=' + clientRefId; 46508 } 46509 46510 if (!UTIL.isEmpty(zip)) { 46511 qs += '&zip=' + zip; 46512 } 46513 46514 return qs 46515 } 46516 function _getBdayQueryString(jfilter) { 46517 var mo1 = jfilter.find('#bday-start-month').val(); 46518 var day1 = jfilter.find('#bday-start-day').val(); 46519 46520 var mo2 = jfilter.find('#bday-end-month').val(); 46521 var day2 = jfilter.find('#bday-end-day').val(); 46522 46523 var bdayStart = UTIL.birthDay(mo1, day1, false); 46524 var bdayEnd = UTIL.birthDay(mo2, day2, true); 46525 46526 if (bdayStart === 0 || bdayEnd === 0 || bdayStart > bdayEnd) { 46527 return ''; 46528 } else { 46529 return '&bmonth1=' + mo1 + '&bday1=' + day1 + '&bmonth2=' + mo2 + '&bday2=' + day2 + '&b1=' + bdayStart + '&b2=' + bdayEnd; 46530 } 46531 } 46532 _conBMsg.changeBirthdayStart = function(element) { 46533 var j = $('.bday-filter-container'); 46534 var jday1 = j.find('#bday-start-day'); 46535 var jmo2 = j.find('#bday-end-month'); 46536 var jday2 = j.find('#bday-end-day'); 46537 46538 var day1 = UTIL.coalesceInt(jday1.val(), 0); 46539 var mo2 = UTIL.coalesceInt(jmo2.val(), 0); 46540 var day2 = UTIL.coalesceInt(jday2.val(), 0); 46541 46542 if (UTIL.isEmpty(element.value)) { 46543 jday1.val(''); 46544 jmo2.val(''); 46545 jday2.val(''); 46546 } else if (mo2 === 0 || element.value > mo2) { 46547 jmo2.val(element.value); 46548 46549 if (day1 === 0) { 46550 jday1.val(1); 46551 } 46552 46553 if (day2 === 0 || (day1 == 1 && day2 > 27)) { 46554 var lastDay = UTIL.lastDayOfMonth(element.value - 1); 46555 jday2.val(lastDay); 46556 } 46557 } 46558 } 46559 46560 _conBMsg.openHelpWasNewClient = function(element) { 46561 var arrow = '<span class="arrow-right" style="color: inherit;">➜
46561</span>'; 46562 var msg1 = '<p style="line-height: 1.4; letter-spacing: 0; font-weight: bold; font-size: larger;">Identify which clients had their first visit</p>'; 46563 var msg2 = '<p style="line-height: 1.4;">Then you can send a message to these clients to convert new customers to regular clients</p>'; 46564 46565 var li1 = '<li class="pop-help-note" style="color: green;">'; 46566 var note1 = li1 + 'a 1st time client is only 30-40% likely to return for a second visit</p>'; 46567 var note2 = li1 + 'after a clients second visit they are 50-70% likely to return for a third visit</p>'; 46568 var note3 = li1 + 'After a client\'s third visit they are very likely to become regular clients</p>'; 46569 46570 var noteMsgCss = 'margin: 0; margin-top: 32px; padding-top: 8px; border-top: 1px solid green; font-weight: bold; color: green;' 46571 var noteMsg = '<p style="' + noteMsgCss + '">Convert New Clients ' + arrow + ' Regular Clients</p>'; 46572 var noteList = noteMsg + '<ul class="pop-help-note-list">' + note1 + note2 + note3 + '</ul>'; 46573 46574 var htm = '<div id="pop-help-was-new-client">' + msg1 + msg2 + noteList + _getProviderParentHelp() + '</div>'; 46575 GLO.Popup.Info.open(htm, '1st Visit During Date Range'); 46576 } 46577 function _getProviderParentHelp() { 46578 if (GLO.Data.provider.relationship > 0 || GLO.Data.provider.reportParentId > 0) { 46579 var bWasNewClient = '<b class="narrow-text" title="Was a New Client">1st Visit During Date Range</b>'; 46580 var msgCss = 'margin-bottom: 2px; line-height: 1.2; text-align: left; letter-spacing: 0; font-family: arial; font-stretch: condensed; font-size: 120%; font-weight: bold; color: purple;'; 46581 var msg = '<p style="' + msgCss + '">When set these fields, filters across all your locations</p>'; 46582 46583 var li1 = '<li class="pop-help-note" style="color: purple;">'; 46584 var list1 = li1 + bWasNewClient + ' only clients who were <i class="narrow-text">New client</i> during the given date range <span class="narrow-text">(never been to any location)</span></li>'; 46585 var list2 = li1 + '<b class="narrow-text">Not-Seen-Since</b> date range <span class="narrow-text">(at any location)</span> </li>'; 46586 46587 return '<div id="provider-parent-help">' + msg + '<ul class="pop-help-note-list">' + list1 + list2 + '</ul></div>'; 46588 } else { 46589 return ''; 46590 } 46591 } 46592 _conBMsg.openHelpWithStaff = function(element) { 46593 var name = UTIL.maxString($('#ticket-type-filter #filter-staff').find(':selected').text(), 12, true); 46594 var msg = '<div id="pop-help-filter-with-staff">' + UTIL.replaceAll($(element).attr('title'), 'staff', name) + '</div>'; 46595 46596 GLO.Popup.Info.open(msg, 'Filter Information'); 46597 } 46598 46599 function _toggleStaffLastVisit(jfilter, sid) { 46600 var jwith = jfilter.find('#filter-last-visit-with-staff'); 46601 46602 if (UTIL.isNumber(sid)) { 46603 var name = UTIL.maxString(jfilter.find('#filter-staff').find(':selected').text(), 12, true); 46604 46605 if (jwith.hasClass('hide')) { 46606 jwith.removeClass('hide').find('span i').text(name); 46607 } else { 46608 return jwith.find('#Last_Visit_With_Staff_fl').prop('checked'); 46609 } 46610 } else { 46611 jwith.addClass('hide'); 46612 } 46613 46614 return false; 46615 } 46616 46617 _conBMsg.changeNotSeenSince = function() { 46618 var jfilter = $('#ticket-type-filter'); 46619 var start = UTIL.fromSADate(jfilter.find('#filter-start').val(), true, true); 46620 var end = UTIL.fromSADate(jfilter.find('#filter-end').val(), true, true); 46621 var notSince = jfilter.find('#filter-not-seen-since').val(); 46622 46623 if (UTIL.isDate(notSince)) { 46624 notSince = new Date(UTIL.fromSADate(notSince, true, true)); 46625 var newEnd = notSince.addDays(-1).toGloDate(); 46626 46627 if (new Date(start) > notSince) { 46628 var jsvc = jfilter.find('#filter-service'); 46629 var dayDiff = UTIL.dayDiff(new Date(end), new Date(start)); 46630 var newStart = new Date(new Date(newEnd).addDays(dayDiff)).toGloDate(); 46631 46632 jfilter.find('#filter-start').val(newStart); 46633 jfilter.find('#filter-end').val(newEnd); 46634 46635 if (UTIL.isEmpty(jsvc.val())) { 46636 jsvc.val(-1); 46637 } 46638 } else if (new Date(end) > notSince) { 46639 var jsvc = jfilter.find('#filter-service'); 46640 jfilter.find('#filter-end').val(newEnd); 46641 46642 if (UTIL.isEmpty(jsvc.val())) { 46643 jsvc.val(-1); 46644 } 46645 } else if (UTIL.isEmpty(start) && UTIL.isEmpty(end) && document.location.search.split('&').length < 3) {
46646 var days = UTIL.dayDiff(notSince, new Date()) + 1; 46647 var dtStart = new Date(notSince).addDays(-days * 2); 46648 46649 jfilter.find('#filter-start').val(dtStart.toGloDate()); 46650 jfilter.find('#filter-end').val(notSince.toGloDate()); 46651 } 46652 } 46653 46654 GLO.Message.Bulk.filter(); 46655 } 46656 46657 _conBMsg.filter = function(isExport) { 46658 var jfilter = $('#ticket-type-filter'); 46659 var sid = jfilter.find('#filter-staff').val(); //var sfilter = GLO.Uri.query('sfilter'); 46660 var isLastVisitWithStaff = _toggleStaffLastVisit(jfilter, sid); 46661 var fname = jfilter.find('#filter-first-name').val(), lname = jfilter.find('#filter-last-name').val(); 46662 46663 var start = jfilter.find('#filter-start').val(); 46664 if (!UTIL.isEmpty(start)) { start = UTIL.fromSADate(start, true, true); } 46665 46666 var end = jfilter.find('#filter-end').val(); 46667 if (!UTIL.isEmpty(end)) { end = UTIL.fromSADate(end, true, true); } 46668 46669 var notSince = jfilter.find('#filter-not-seen-since').val(); 46670 if (!UTIL.isEmpty(notSince)) { notSince = UTIL.fromSADate(notSince, true, true); } 46671 46672 var svc = jfilter.find('#filter-service').val(); 46673 var brand = jfilter.find('#filter-brand').val(); 46674 var category = jfilter.find('#filter-category').val(); 46675 46676 var noProduct = jfilter.find('#filter-never-had-product').val(); 46677 46678 var noAppt = null, noClass = null, noApptEver = null, noProductEver = null; 46679 var jNoService = jfilter.find('#filter-never-had-service').find('option:selected'); 46680 46681 if (noProduct == -1) { 46682 noProductEver = 1, noProduct = null; 46683 } 46684 46685 if (jNoService.attr('id') === 'filter-never-any-service') { 46686 noApptEver = 1; 46687 } else if (UTIL.parseBool(jNoService.attr('has_class_fl'))) { 46688 noClass = UTIL.cleanString(jNoService.attr('value')); 46689 } else { 46690 noAppt = UTIL.cleanString(jNoService.attr('value')); 46691 } 46692 46693 var minService = null, minProduct = null, jd = {}; 46694 var providerRefId = jfilter.find('#Provider_Referral_id').val(), clientRefId = jfilter.find('#Referred_By_Client_id').attr('autoid'); 46695 var zip = jfilter.find('#Zip_vc').val(); 46696 46697 if (svc < 0) { 46698 minService = -svc, svc = null; 46699 } 46700 46701 if (category < 0) { 46702 minProduct = -category, category = null; 46703 } 46704 46705 if (UTIL.isDate(start) && !UTIL.isDate(end)) { 46706 end = new Date().toGloDate(); 46707 jfilter.find('#filter-end').val(new Date().toGloDateString(false, true, true, false)); 46708 } else if (!UTIL.isDate(start) && UTIL.isDate(end)) { 46709 //start = ''; 46710 } 46711 46712 if (!_filterIsValid(start, end, notSince)) { 46713 return; 46714 } else if (!GLO.Report.hasReportPassword(jd)) { 46715 return; 46716 } 46717 46718 var end = jfilter.find('#filter-end').val(); //= filterIsValid might change end date value 46719 if (!UTIL.isEmpty(end)) { end = UTIL.fromSADate(end, true, true); } 46720 46721 var fmt = $('#be-message-format #Message_Format_cd').find('li.selected').attr('value'); 46722 46723 if (fmt == 3) { 46724 $('#Include_Email_Only_fl').prop('checked', false).change(); 46725 } 46726 46727 var ojpop = _displaySearchSummary(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct 46728 , providerRefId, clientRefId, fname, lname, zip); 46729 _setSort(); 46730 46731 var qs = _getQueryString(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct, isLastVisitWithStaff, fname, lname); 46732 qs += _conBMsg.getTagQueryString(jfilter); 46733 qs += _getBdayQueryString(jfilter); 46734 qs += _getProfileCreateQueryString(jfilter); 46735 qs += _getProfileReferAndZip(jfilter, providerRefId, clientRefId, zip); 46736 qs += _getLoyaltyQueryString(jfilter); 46737 qs += _getVisitCountQueryString(jfilter); 46738 46739 if (jfilter.find('#Was_New_Client_fl').prop('checked')) { 46740 qs += '&wasnewclient=1'; 46741 } 46742 46743 if (qs && qs.length > 0 && qs.substring(0,1) === '&') { 46744 qs = qs.substring(1); 46745 } 46746 46747 var url = GLO.Link.WebsiteDomain + 'message/FilterClientList?' + qs; 46748 46749 if (isExport) { 46750 _exportClientList(jfilter, url); 46751 return; 46752 } 46753
46754 var qs2 = _getStaticQueryString(); 46755 var jbtn = jfilter.find('.btnSearch'); 46756 GLO.UI.Form.beginProcessing(jbtn); 46757 46758 setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs + qs2, 'Client List'); }, 50); 46759 46760 _currentFilterAjax = $.ajax({ type: "POST", url: url, "cache": false, "data": jd }) 46761 .success(function(data, textStatus, jqXHR) { 46762 GLO.UI.Form.resetProcessing(); 46763 var jcontainer = $('#client-list-container'); 46764 46765 if (!UTIL.isEmpty(data) && $(data).attr('id') == 'client-list-container') { 46766 jcontainer.replaceWith(data); 46767 var clientsFound = _initClientList(true); 46768 } else { 46769 jcontainer.html(data); 46770 var clientsFound = 0; 46771 GLO.Popup.Info(SA.Resource.NoResultsFound); 46772 } 46773 46774 _clientListLoadComplete(ojpop, clientsFound); 46775 }) 46776 .error(function(jqXHR, textStatus, errorThrown) { 46777 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 46778 GLO.UI.Form.resetProcessing(); 46779 }); 46780 } 46781 46782 function _exportClientList(jfilter, url) { 46783 var btnExport = jfilter.find('.btnExportToExcel'); 46784 GLO.UI.Form.beginProcessing(btnExport); 46785 46786 window.setTimeout(function() { 46787 GLO.UI.Form.resetProcessing(btnExport); 46788 }, 14500); 46789 46790 url += '&ExportToExcel=1'; 46791 var childWindow = UI.openChildWindow(url, '', true); 46792 } 46793 46794 function _initUrlClientList() { 46795 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 46796 46797 if (!UTIL.isEmpty(highlight)) { 46798 var jhighlight = $('#' + highlight + ', .' + highlight); 46799 46800 if (jhighlight.length > 0) { 46801 GLO.Popup.closeIfExist($('#search-summary').closest('.glopop')); 46802 UI.highlight(jhighlight, 800, 6400, true); 46803 } 46804 46805 var qs = document.location.search; 46806 46807 if (qs.length) { 46808 qs = qs.replace('highlight=' + highlight, ''); 46809 qs = qs.replace('&&', ''); 46810 46811 if (qs.substring(0,1) === '?') { 46812 qs = qs.substring(1); 46813 } 46814 46815 setTimeout(function() { 46816 GLO.Report.TicketHistory.changeUrl(qs, 'Client List'); 46817 }, 50); 46818 } 46819 } 46820 } 46821 function _clientListLoadComplete(ojpop, clientsFound) { 46822 $('#search-summary').find('#search-summary-action').text('Loading'); 46823 46824 setTimeout(function() { 46825 $('#search-summary').find('#search-summary-dots').remove(); 46826 GLO.Report.CellSummary.ClientList.init(); 46827 }, 1200); 46828 46829 setTimeout(function() { 46830 $('#search-summary').find('#search-summary-throbber').remove(); 46831 $('#search-summary').find('#search-summary-label').html('Clients Loaded'); 46832 _clientListLoadCompleteBigResult(ojpop, clientsFound); 46833 }, 2400); 46834 46835 $('#be-client-list').on('click.open-tag', '.client-tag', GLO.Message.Bulk.openTag); 46836 //$('#be-client-list').find('.client-tag').attr('onclick', 'GLO.Message.Bulk.openTag(this)'); 46837 46838 _initUrlClientList(); 46839 } 46840 function _clientListLoadCompleteBigResult(ojpop, clientsFound) { 46841 if (clientsFound < 2000) { 46842 return; 46843 } else if (clientsFound > 4500) { 46844 var msg = '<p>When search returns more than 5,000 clients, then only returns clients that have</p>'; 46845 var li1 = '<li>first name</li>'; 46846 var li2 = '<li>at least one of the following: Last Name, Mobile Phone, or Email</li>'; 46847 var li3 = '<li>if all filter fields are empty then client must have Mobile Phone or Email</li>'; 46848 var htm = msg + '<ul>' + li1 + li2 + li3 + '</ul>'; 46849 } else if (clientsFound > 1800) { 46850 var htm = '<p>When search returns more than 2,000 clients, then only returns clients that have: phone, email, or have visited at least 1 time</p>'; 46851 } 46852 46853 $('#search-summary').append('<div id="client-search-big-result">' + htm + '</div>'); 46854 ojpop.realign(); ojpop.realign(); 46855 } 46856 46857 _conBMsg.openTag = function(element) { 46858 var jtag = $(this); 46859 var tr = jtag.closest('tr'); 46860 var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.be-client-name').find('a').text(); 46861 46862 GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName); 46863 } 46864 46865 function _setSort() { 46866 _sortColumn = GLO.Uri.query('sort'); 46867 _sortDescending = UTIL.coalesceInt(GLO.Uri.query('descending'), 0); 46868 } 46869 46870 function _initSaveButton() { 46871 var j = $('#bulk-email-container'); 46872 var jBtnSave = j.find('#btnSaveForLater').find('a'); 46873 46874 j.find('textarea, .sa-text-editor').on('keyup', function() { jBtnSave.css({ "border": "3px solid Red" }); });
46875 j.find('input:not(#Include_Text_Only_fl, #Include_Email_Only_fl), select, textarea, .sa-text-editor').on('change', function() { jBtnSave.css({ "border": "3px solid Red" }); }); 46876 } 46877 46878 _conBMsg.imageUploadComplete = function(jupload, fileName, imgId, imgSize) { 46879 var jbanner = $('#pop-preview-message').find('.banner, .custom-banner').find('img'); 46880 jbanner.attr('src', GLO.Data.cdnDirectory + 'upload-folder/' + fileName); //this does NOT refresh image so have to do replaceWith 46881 jbanner.replaceWith(jbanner.outerHTML()); 46882 } 46883 46884 _conBMsg.checkAll = function(element) { 46885 if (element.checked) { 46886 var context = '#be-client-list > tbody'; 46887 46888 var btnAll = '<span id="btnAll" class="btnAdd"><a>All Clients Below</a></span>'; 46889 var btnThisPage = '<span id="btnThisPage" class="btnAdd"><a>Clients on This Page</a></span>'; 46890 var btnCustomNumber = '<span id="btnCustomNumber" class="btnAdd"><a>Select Number of Clients</a></span>'; 46891 46892 var msg = '<p style="padding: 2px 8px; text-align: center;">Which Clients do you want to select?</p>'; 46893 var htmBtns = '<div>' + btnAll + btnThisPage + btnCustomNumber + '</div>'; 46894 var htm = '<div id="pop-select-rows">' + msg + htmBtns + '</div>'; 46895 46896 var fnCancel = function() { 46897 element.checked = false; //$('#be-client-list').find('th.be-checkbox > input:checkbox').prop('checked', false); 46898 GLO.Popup.closeIfExist( $('#pop-select-rows').closest('.glopop') ); 46899 }; 46900 46901 var jpop = GLO.Popup.Custom.openSimple(htm, 'Select which Clients?', null, fnCancel); 46902 var jbtns = jpop.find('.pop-buttons').css({ "text-align": "center" }); 46903 46904 jpop.find('#btnAll > a').click(function() { GLO.Message.Bulk.checkAllRows(element, context); }); 46905 jpop.find('#btnThisPage > a').click(function() { GLO.Message.Bulk.checkThisPage(element, context); }); 46906 jpop.find('#btnCustomNumber > a').click(function() { GLO.Message.Bulk.checkCustomAmount(element, context); }); 46907 46908 jbtns.find('.btnSave').remove(); 46909 jbtns.find('.btnCancel').css({ "float": "none", "position": "relative", "font-size": "18px", "font-weight": "bold" }); 46910 } else { 46911 _conBMsg.checkAll2(element, '#be-client-list > tbody'); 46912 } 46913 } 46914 _conBMsg.checkAllRows = function(element, context) { 46915 _conBMsg.checkAll2(element, context); 46916 } 46917 _conBMsg.checkThisPage = function(element, context) { 46918 _conBMsg.checkAll2(element, context, null, true); 46919 } 46920 _conBMsg.checkCustomAmount = function(element, context) { 46921 var msg = '<p style="padding: 2px 8px; text-align: center;">How many clients do you want to select?</p>'; 46922 var input = '<div> <input id="Row_Count_sr" type="number" style="width: 120px; letter-spacing: 1px; font-size: 20px; font-weight: bold;"/> </div>'; 46923 var htm = '<div id="pop-select-rows-custom">' + msg + input + '</div>'; 46924 46925 var fn = function() { 46926 var numberToSelect = $('#pop-select-rows-custom').closest('.glopop').find('#Row_Count_sr').val(); 46927 _conBMsg.checkAll2(element, context, numberToSelect); 46928 } 46929 46930 var jpop = GLO.Popup.Custom.openSimple(htm, 'Select How Many Rows'); 46931 GLO.Popup.Custom.singleButton(jpop, 'Select Rows').click(fn); 46932 } 46933 _conBMsg.checkAll2 = function(parentCheckBox, context, numberToSelect, isVisibleOnly) { 46934 GLO.Popup.closeIfExist( $('#pop-select-rows-custom').closest('.glopop') ); 46935 GLO.Popup.closeIfExist( $('#pop-select-rows').closest('.glopop') ); 46936 46937 if (isVisibleOnly || numberToSelect > 0) { 46938 var chk = $(context + ' input:checkbox:visible'); 46939 } else { 46940 var chk = $(context + ' input:checkbox'); 46941 } 46942 46943 var count = 0; 46944 var jcheckbox = $(parentCheckBox); 46945 var isChecked = jcheckbox.prop('checked'); 46946 46947 chk.each(function() { 46948 ++count; 46949 46950 if (isChecked) { 46951 if (!$(this).closest('tr').hasClass('hideX')) { 46952 $(this).prop('checked', true); 46953 } 46954 } else { 46955 $(this).prop('checked', false); 46956 } 46957 46958 if (numberToSelect > 0 && numberToSelect == count) { 46959 isChecked = false; 46960 } 46961 }); 46962 46963 //setTimeout(function() { jcheckbox.prop('checked', isChecked); }, 200); //= for some reason the 'all' checkbox doesn't stay checked. 46964 } 46965 46966 function _getCxml(j, encode, fmt) { 46967 var forceEmailOnly = (fmt == 1), forceTextOnly = (fmt == 3 || fmt == 6); // && GLO.Data.provider.textPackage < 10
46968 var tr, trs = _getActiveRows(forceEmailOnly, forceTextOnly); //j.find('#be-client-list > tbody > tr'); 46969 var jemail, email, cxml = ''; 46970 var providerDD = j.find('#be-mobile-provider-dd'); 46971 //var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value'); 46972 46973 for (var i=0; i < trs.length; i++) { 46974 if (trs.eq(i).not('.hideX').find(':checkbox').prop('checked')) { 46975 if (fmt == 3 || fmt == 6) { 46976 jemail = trs.eq(i).find('.be-phone'); 46977 email = UTIL.replaceAll(UTIL.replaceAll(UTIL.replaceAll(UTIL.replaceAll(jemail.text(), '-', ''), '(', ''), ')', ''), ' ', ''); 46978 //var postfix = providerDD.find('option[value="' + jemail.attr('mobile_provider_cd') + '"]').attr('email_postfix_vc'); 46979 46980 if (!UTIL.isEmpty(email)) { // && !UTIL.isEmpty(postfix) 46981 email = email; // + postfix 46982 } else if (!email || email.length != 10) { // || GLO.Data.provider.textPackage < 10 46983 email = null; 46984 } 46985 } else { 46986 jemail = trs.eq(i).find('.be-email'); 46987 email = UTIL.coalesce(jemail.attr('title'), jemail.text()); 46988 } 46989 46990 if (!UTIL.isEmpty(email)) { 46991 cxml += '<tr client_id="' + trs.eq(i).attr('client_id') + '" email_vc="' + email + '"/>'; 46992 } 46993 } 46994 } 46995 46996 if (cxml === '') { 46997 return ''; 46998 } else { 46999 if (encode) { 47000 return UTIL.htmlEncode('<table>' + cxml + '</table>'); 47001 } else { 47002 return '<table>' + cxml + '</table>'; 47003 } 47004 } 47005 } 47006 47007 function _hasRemainingMessages(j, clientCount) { 47008 var remaining = _getRemainingMessages(j); 47009 47010 if (remaining < clientCount) { 47011 var h1 = '<h1>' + SA.Resource.NotEnoughMessages + '</h1>'; 47012 var msg = '<div style="line-height: 180%;">You are about to send ' + clientCount + ' messages but only have ' + remaining + ' remaining this month</div>'; 47013 47014 if (remaining == 0) { 47015 msg += '<div style="padding-top: 20px; padding-bottom: 20px; text-align: center;">' 47016 + '<span class="btnAdd btnUpgrade"> <a onclick="GLO.Message.Bulk.gotoUpgrade(this, \'email-blast\')">Upgrade to Send more Email and Texts</a> </span>' 47017 + '</div>'; 47018 } else { 47019 msg += '<div style="padding-top: 20px;">Do you want to:<ul style="margin: 0; text-align: center;">' 47020 + '<li><a onclick="GLO.Message.Bulk.sendAllRemaining()">Send message to first ' + remaining + ' clients</a></li>' 47021 + '<li><a onclick="GLO.Message.Bulk.closeNotEnough()">Select specific clients below to send message</a></li>' 47022 + '<li> <span class="btnAdd btnUpgrade" style="margin-top: 8px;"> <a onclick="GLO.Message.Bulk.gotoUpgrade(this, \'email-blast\')">Upgrade to Send more Email and Texts</a> </span> </li>' 47023 + '</ul> </div>'; 47024 } 47025 47026 var css = 'padding: 0 8px; letter-spacing: 1px;'; 47027 var jmsg = $('<div id="pop-bulk-not-enough" style="' + css + '">' + h1 + msg + '</div>'); 47028 47029 var jpop = new GLO.Popup.Custom(jmsg).getPopup().addClass('no-persist'); 47030 var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" }); 47031 47032 jbtns.find('.btnSave').remove(); 47033 jbtns.find('.btnCancel').css( { "float": "none", "width": "60px", "margin": "inherit", "letter-spacing": "1px" }).find('a').text(SA.Resource.Close); 47034 47035 return false; 47036 } else { 47037 return true; 47038 } 47039 } 47040 47041 _conBMsg.closeNotEnough = function() { 47042 GLO.Popup.close( $('#pop-bulk-not-enough').closest('.glopop') ); 47043 } 47044 47045 _conBMsg.gotoHistory = function(btn, helloback) { 47046 btn = $(btn).parent(); 47047 GLO.UI.Form.beginProcessing(btn); 47048 47049 setTimeout(function() { 47050 var url = GLO.Link.WebsiteDomain + 'message/MarketingHistory?'; 47051 47052 if (helloback) { url += 'helloback=' + helloback; } 47053 47054 document.location = url; 47055 }, 600); 47056 } 47057 47058 _conBMsg.gotoChangePlan = function(btn, helloback) { 47059 btn = $(btn).parent(); 47060 GLO.UI.Form.beginProcessing(btn); 47061 47062 setTimeout(function() { 47063 var url = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-plan'; 47064 47065 if (helloback) { url += '&helloback=' + helloback; } 47066 47067 document.location = url; 47068 }, 600); 47069 } 47070 47071 _conBMsg.gotoClientList = function(btn, isNewMsg, helloback) { 47072 var url = GLO.Link.WebsiteDomain + '/message/ClientList?'; 47073 47074 if (SA.Menu.isRequirePIN(url, btn)) { 47075 return false; 47076 } 47077 47078 btn = $(btn).parent(); 47079 GLO.UI.Form.beginProcessing(btn); 47080 47081 setTimeout(function() { 47082 if (isNewMsg) { url += 'openMessage=1&summaryonly=1'; } 47083 if (helloback) { url += '&helloback=' + helloback; } 47084 47085 document.location = url; 47086 }, 600); 47087 } 47088 47089 function _blindSend(j, fmt, fmtType) { 47090 var remaining = _getRemainingMessages(j); 47091 var jsummary = j.find('#client-list-summary'); 47092 47093 if (fmt == 3) { 47094 var fmtString = SA.Resource.Text, clientCount = UTIL.coalesceInt(jsummary.attr('client_text_count_nr'), 0); 47095 } else { 47096 var fmtString = SA.Resource.Email, clientCount = UTIL.coalesceInt(jsummary.attr('client_email_count_nr'), 0); 47097 } 47098 47099 if (remaining == 0) { 47100 var msg = '<div>' + SA.Resource.You_have_no_remaining_messages_this_month + '</div><div>' + SA.Resource.UpgradeYourPlan + '</div>'; 47101 var fn = function() { 47102 document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-package'; 47103 }; 47104 47105 GLO.Popup.Confirm.open(msg, SA.Resource.CannotSendMessage, fn); 47106 } else { 47107 if (clientCount > remaining) { 47108 var msg = '<div class="main-prompt-message">You have ' + remaining + ' remaining messages this month</div>' 47109 + '<div style="margin-top: 20px;">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' ' + remaining + ' ' + SA.Resource.of_the + ' ' + clientCount + ' ' + SA.Resource.clients_that_accept + ' ' + fmtString + 's?</div>' 47110 + '</div>'; 47111 } else if (clientCount == 0 && remaining > 0) { 47112 var msg = '<div class="main-prompt-message">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' all ' + SA.Resource.Clients + ' (up to ' + remaining + ' clients)?</div>'; 47113 } else { 47114 var msg = '<div class="main-prompt-message">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' ' + clientCount + ' ' + SA.Resource.Clients + '?</div>'; 47115 } 47116 47117 _openConfirmBlastPopup(clientCount, fmt, msg, SA.Resource.ConfirmSend, GLO.Message.Bulk.sendBlind); 47118 } 47119 } 47120 47121 _conBMsg.sendAllRemaining = function() { 47122 var j = $('#bulk-email-container'); 47123 var remaining = _getRemainingMessages(j); 47124 var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value'); 47125 var clientList = $(_getCxml(j, false, fmt)).find('tr'); 47126 var cid, tbody = j.find('#be-client-list > tbody'); 47127 47128 for (var i = remaining; i < clientList.length; i++) { 47129 cid = clientList.eq(i).attr('client_id'); 47130 tbody.find('tr[client_id="' + cid + '"]').find(':checkbox').prop('checked', false); 47131 } 47132 47133 GLO.Popup.close( $('#pop-bulk-not-enough').closest('.glopop') ); 47134 _conBMsg.sendAll(); 47135 } 47136 47137 function _canSendBulkMessages() { 47138 if (GLO.Provider.isPaidAccount()) { 47139 return true; 47140 } 47141 47142 if (GLO.Data.provider.signupDetail > 499) { 47143 var upgradeLabel = 'Update Credit Card'; 47144 } else { 47145 var upgradeLabel = 'Upgrade Now'; 47146 } 47147 47148 var upgradeButton = '<span style="position: absolute; left: 4px; bottom: 12px; min-height: 20px;" class="btnAdd">
47148<a onclick="GLO.Uri.gotoUri(\'/provider/profile/6\')">' + upgradeLabel + '</a></span>'; 47149 var pb = '<span id="btnPreview" class="btnAdd"> <a onclick="GLO.Message.Bulk.closeAndpreview()">Preview button</a> </span>'; 47150 var btnSendSample = $('#pop-preview-message-buttons #btnSendSample:visible'); 47151 47152 if (btnSendSample.length === 1) { pb = btnSendSample.outerHTML(); } 47153 47154 var h1 = '<h1 class="friendly-msg2">Paid Package Required to Send Marketing Message</h1>'; 47155 var msg1 = '<div>You must have an active paying account to send marketing messages</div>'; 47156 var msg2 = '<div style="margin-top: 12px;">You can use the ' + pb + ' to send yourself a sample message</div>'; 47157 var htm = '<div id="pop-paid-plan-required">' + h1 + '<div class="friendly-msg2" style="margin-bottom: 40px; text-align: left;">' + msg1 + msg2 + '</div></div>'; 47158 47159 var jpop = new GLO.Popup.Info(htm).getPopup(); 47160 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 47161 47162 jbtns.find('.btnOk').css({ "padding-top": "7px" }).find('>a').text('Close').css({ "padding-top": "4px", "padding-bottom": "3px" }); 47163 jbtns.prepend(upgradeButton); 47164 47165 return false; 47166 } 47167 47168 _conBMsg.closeAndpreview = function() { 47169 GLO.Popup.close($('#pop-paid-plan-required').closest('.glopop')); 47170 GLO.Message.Bulk.preview(); 47171 } 47172 47173 function _textBlastDisclaimer(isSimpleOnly) { 47174 var msg1 = 'Response rates to encourage existing clients to come back or visit for a specific reason are often positive'; 47175 var msg1b = ' - make sure your text messages are appropriate, relevant, and compelling for the recipients'; 47176 47177 if (!isSimpleOnly) { 47178 var msg2 = 'Response rates for unsolicited SMS text message campaigns will almost always be low, and therefore the return on your investment will be poor'; 47179 var msg3 = 'It is usually a bad idea to send text messages to people who are not already clients and it could be illegal to send unsolicited messages in the United States '; 47180 var msg3b = '<small>(based on the Telephone Consumer Protection Act)</small> and Canada <small>(see Canada\'s Anti-Spam Legislation)</small>'; 47181 var msg4 = 'When customers receive a text blast message they can reply to the text with: STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, or QUIT and they will no longer receive text messages'; 47182 47183 var htm = '<p>' + msg1 + msg1b + '</p><p>' + msg2 + '</p><p>' + msg3 + msg3b + '</p><p>' + msg4 + '</p>'; 47184 } else { 47185 var htm = '<p>' + msg1 + msg1b + '</p>'; 47186 } 47187 47188 htm += '<p>Text messages can only be scheduled between 9am - 8pm <small>(any messages not sent before 9pm will be sent the next morning starting at 9am)</small></p>'; 47189 return '<div id="pop-text-blast-disclaimer">' + htm + '</div>'; 47190 } 47191 47192 _conBMsg.sendAll = function() { 47193 if (!_canSendBulkMessages()) { return false; } 47194 47195 var j = $('#bulk-email-container'); 47196 var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value'); 47197 //var clientCount = $('#be-client-list').find('>tbody :checked').length; //input:checkbox:checked 47198 var clientCount = $(_getCxml(j, false, fmt)).find('tr').length; 47199 47200 if (fmt == 3) { //sms 47201 var fmtType = 'a text', fmtClass = 'accept-text'; 47202 } else if (fmt == 6) { //mms 47203 var fmtType = 'a MMS', fmtClass = 'accept-text'; 47204 } else { 47205 var fmtType = 'an email', fmtClass = 'accept-email'; //.be-email 47206 } 47207 47208 if (clientCount === 0) { 47209 if (j.find('#be-client-list').length === 0) { 47210 _blindSend(j, fmt); 47211 return; 47212 } 47213 47214 var tr = $('#be-client-list').find('>tbody .' + fmtClass); 47215 clientCount = tr.length; 47216 47217 for (var i=0; i < clientCount; i++) { 47218 tr.eq(i).find(':checkbox').prop('checked', true); 47219 } 47220 } 47221 47222 if (!_hasRemainingMessages(j, clientCount)) { return; } 47223 47224 var h1 = 'Confirm Send ' + fmtType + ' to ' + clientCount + ' Clients?'; 47225 var msg = '<div style="margin-bottom: 16px; padding-top: 8px;">Confirm Send ' + fmtType + ' Blast to ' + clientCount + ' Clients?</div>'; 47226 47227 _openConfirmBlastPopup(clientCount, fmt, msg, h1, GLO.Message.Bulk.sendAllConfirmed); 47228 _conBMsg.getScore(); 47229 } 47230 47231 function _previewBeforeSending(fmt, isSaving) { 47232 if (fmt == 3) { 47233 var msg1 = 'Please Review Message before Sending'; 47234 } else { 47235 var msg1 = 'Please Preview Message before sending'; 47236 } 47237 47238 var msg2 = '<p>We suggest sending yourself a sample before sending message blast</p>'; 47239 var htmPleasePreview = '<div id="pop-processing-please-preview"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>'; 47240 var fnFocus = function() { 47241 GLO.Popup.closeIfExist( $('#bulk-deliverability-score').closest('.glopop') ); 47242 47243 var btnRow = $('#be-message-body3'); 47244 UI.highlight(btnRow, 1200, 16400, true); 47245 }; 47246 47247 if (isSaving) { 47248 var h1 = 'Saving Message...'; 47249 var ojpop = GLO.Popup.Processing.open(htmPleasePreview, h1, fnFocus); 47250 } else { 47251 var h1 = 'Send Yourself a Sample?'; 47252 var ojpop = GLO.Popup.Info.open(htmPleasePreview, h1, fnFocus); 47253 } 47254 47255 return ojpop; 47256 } 47257 47258 function _openConfirmBlastPopup(clientCount, fmt, msg, h1, fn) { 47259 var j = $('#bulk-email-container'); 47260 var mbid = j.find('#Message_Bulk_id').val(); 47261 47262 if (fmt == 3 || fmt == 6) { 47263 var disclaimer = _textBlastDisclaimer(); 47264 var fnMoreInfo = 'GLO.Message.Marketing.openHelp(15)'; 47265 msg += _htmPreviewTextBlast(fmt); 47266 } else { 47267 var disclaimer = ''; 47268 var fnMoreInfo = 'GLO.Message.Marketing.openHelp(14)'; 47269 } 47270 47271 if (UTIL.isEmpty(mbid)) { 47272 _previewBeforeSending(fmt, true); 47273 _conBMsg.save(false, false, true); 47274 return; 47275 } else if (clientCount > 500) { 47276 disclaimer += '<p style="margin-top: 16px;">The first 100 messages are sent when scheduled, then the next 100 messages are sent every 5 minutes</p>'; 47277 disclaimer += '<p style="margin-top: 16px;">It might take a few minutes to prepare and schedule all of these messages</p>'; 47278 } 47279
47280 var htmSchedule = _getScheduleBlastHtm(); 47281 var htm = '<div>' + msg + htmSchedule + disclaimer + '</div>'; 47282 47283 var ojpop = GLO.Popup.Confirm.open(htm, h1, fn); 47284 var jpop = ojpop.getPopup().css({ "background-color": "#eee" }).attr('id', 'pop-confirm-send-blast'); 47285 var infoCSS = 'position: absolute; right: 8px; margin-top: -36px; z-index: 99;' 47286 var helpMoreInfo = '<span class="helpIcon2 sa-sprite" onclick="' + fnMoreInfo + '" title="Client Marketing Blats" style="' + infoCSS + '"></span>'; 47287 47288 var jbtns = jpop.find('.pop-buttons-parent').append(helpMoreInfo).find('.pop-buttons').css({ "width": "inherit", "max-width": "98%" }); 47289 47290 if (innerWidth >= 480) { 47291 var cssNo = { "width": "120px", "margin-left": "12px", "margin-top": "-6px", "padding": "4px 12px 2px", "border-radius": "12px", "border": "1px outset black", "background-color": "white" }; 47292 jbtns.find('.btnNo').css(cssNo).find('>a').text('No, Not Yet').css({ "letter-spacing": "1px", "font-size": "18px", "border-bottom": 0 }); 47293 jbtns.find('.btnYes').addClass('btnSave').css({ "width": "180px", "margin-right": "48px" }).find('>a').text('Yes, Send Messages').css({ "padding": "6px 12px 4px" }); 47294 } else { 47295 var cssNo = { "width": "60px", "margin-left": "12px", "margin-top": "-8px", "padding": "4px 12px 2px", "border-radius": "12px", "border": "1px outset black", "background-color": "white" }; 47296 jbtns.find('.btnNo').css(cssNo).find('>a').css({ "letter-spacing": "1px", "font-size": "18px", "border-bottom": 0 }); 47297 jbtns.find('.btnYes').addClass('btnSave').css({ "width": "80px", "margin-right": "48px" }).find('>a').css({ "padding": "2px 20px 1px", "font-size": "18px" }); 47298 } 47299 47300 _initPopupConfirmSend(jpop, fmt); 47301 47302 if (jpop.height() > innerHeight - 100) { 47303 ojpop.addScrollBar(); 47304 } 47305 } 47306 47307 function _htmPreviewTextBlast(fmt) { 47308 var jtop = $('#be-top'); 47309 var msg = ''; 47310 if (fmt == 3) { 47311 msg = jtop.find('#be-message-body-text #Text_vc').val(); 47312 47313 if (msg.length < 140) { 47314 msg += ' '; 47315 } 47316 } 47317 47318 if (fmt == 6) { 47319 msg = jtop.find('#be-message-body-mms #mms_text_vc').val(); 47320 47321 if (msg.length > 1500) { 47322 msg += msg.substring(0,1500); 47323 } 47324 } 47325 47326 return '<div id="be-preview-text-message">' + msg + ' ' + jtop.find('#be-message-text-post').text() + '</div>'; 47327 } 47328 47329 function _initPopupConfirmSend(jpop, fmt) { 47330 var day = new Date(); 47331 var tm = day.toGloTime(true); 47332 47333 if (fmt === 3 || fmt === 6) { 47334 var todayAtEightPM = new Date(); 47335 todayAtEightPM.setHours(20); 47336 todayAtEightPM.setMinutes(0); 47337 47338 var tomorrowAtNineAM = new Date(); 47339 tomorrowAtNineAM.setDate(tomorrowAtNineAM.getDate() + 1); 47340 tomorrowAtNineAM.setHours(9); 47341 tomorrowAtNineAM.setMinutes(0); 47342 47343 if (day > todayAtEightPM) { 47344 day = new Date(day.setDate(day.getDate() + 1)); 47345 tm = ' 9:00 AM'; 47346 } else if (day < tomorrowAtNineAM) { 47347 tm = ' 9:00 AM'; 47348 } 47349 } 47350 47351 jpop.find("#Blast_d").datepicker({ "minDate": day }).val(day.toGloDate()); 47352 47353 var oTime = UI.timeMask('#Blast_tm'); 47354 UI.setTimeMaskValue(jpop.find('#Blast_tm'), tm); 47355 47356 setTimeout(function() { 47357 jpop.find(':focus').blur(); 47358 }, 100); 47359 } 47360 47361 function _getScheduleBlastHtm() { 47362 var css = '<style> .ui-datepicker { z-index: 9999 !important; } </style>'; 47363 var label = '<label for="">Send at</label>'; 47364 var htmDate = '<input type="text" id="Blast_d" name="Blast_d" pattern="[0-9]*" onclick="GLO.UI.displayDatePicker(this)"/>' 47365 47366 if (GLO.Info.isIPhone || GLO.Info.isAndroid) { 47367 var htmTime = '<input type="time" id="Blast_tm" name="Blast_tm"/>'; 47368 } else { 47369 var htmTime = '<input type="text" id="Blast_tm" name="Blast_tm"/>'; 47370 } 47371 47372 return '<div>' + label + htmDate + htmTime + css + '</div>'; 47373 } 47374 47375 _conBMsg.canSendSample = function(messageFormat) { 47376 if (messageFormat == 3 || messageFormat == 6) { 47377 if (GLO.Staff.hasText(GLO.Info.StaffId)) { 47378 return true; 47379 } 47380 } else if (GLO.Staff.hasEmail(GLO.Info.StaffId)) { 47381 return true; 47382 } 47383 47384 return false; 47385 } 47386 47387 _conBMsg.sendAllConfirmed = function() { 47388 _conBMsg.save(false, true); 47389 } 47390 47391 _conBMsg.sendSample = function() { 47392 var fmt = $('#bulk-email-container').find('#Message_Format_cd').find('li.selected').attr('value'); 47393
47394 if (_conBMsg.canSendSample(fmt)) { 47395 _conBMsg.save(true); 47396 } 47397 } 47398 47399 _conBMsg.preview = function() { 47400 _conBMsg.save(false, false, true); 47401 } 47402 47403 _conBMsg.sendBlind = function() { 47404 _conBMsg.save(false, false, false, true); 47405 } 47406 47407 _conBMsg.getScore = function() { 47408 var j = $('#bulk-email-container'); 47409 var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value'); 47410 var cxml = _getCxml(j, false, 3); 47411 47412 if (!UTIL.isEmpty(cxml)) { 47413 var messageCount = $(cxml).find('tr').length; 47414 } else { 47415 var messageCount = _getActiveRows(false, true).length; 47416 } 47417 47418 var uri = GLO.Link.WebsiteDomain + 'message/BulkScore?count=' + messageCount + '&format=' + fmt; 47419 47420 if (fmt == 3) { 47421 var body = UTIL.htmlEncode(j.find('#Text_vc').val()); 47422 } else if (fmt == 6) { 47423 var body = UTIL.htmlEncode(j.find('#mms_text_vc').val()); 47424 } else { 47425 var body = UTIL.htmlEncode(DOMPurify.sanitize(j.find('.sa-editor .sa-text-editor')[0].innerHTML)); 47426 } 47427 47428 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "body": body } }) 47429 .success(function(data, textStatus, jqXHR) { 47430 var jd = $(data); 47431 GLO.Popup.closeIfExist($('#pop-bulk-deliverability-score').closest('.glopop')); 47432 47433 if (jd.attr('id') === 'bulk-deliverability-score') { 47434 var ojpop = new GLO.Popup.Custom(jd); 47435 var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score'); 47436 GLO.Popup.Custom.singleButton(jpop, 'Close'); 47437 47438 ojpop.realign(); ojpop.realign(); 47439 47440 var score = jd.find('h2 b').text(); 47441 47442 if (score < 65) { 47443 GLO.Popup.closeIfExist($('#pop-confirm-send-blast.glopop')); 47444 } 47445 } 47446 }) 47447 .error(function(jqXHR, textStatus, errorThrown) { 47448 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 47449 }); 47450 } 47451 47452 function _allowSendBlast(jd) { 47453 var jwrite = $('#be-write-email-container'); 47454 47455 if (jwrite.attr('provider_var') == 'MembershipSalons' && !UTIL.parseBool(jwrite.attr('provider_allow_blast_fl'))) { 47456 var pass = $('#pop-confirm-var-pass #VAR_Password_vc').val(); 47457 47458 if (!UTIL.isEmpty(pass)) { 47459 jd.pass = pass; 47460 GLO.Popup.close($('#pop-confirm-var-pass')); 47461 } else { 47462 var htm = '<div><label for="VAR_Password_vc">Enter Password to Send Message Blast</label><input type="password" id="VAR_Password_vc"/></div>'; 47463 var ojpop = GLO.Popup.Confirm.open(htm, 'Enter Password to Send Messages', GLO.Message.Bulk.sendQuick); 47464 ojpop.getPopup().attr('id', 'pop-confirm-var-pass'); 47465 47466 ojpop.realign(); 47467 return false; 47468 } 47469 } 47470 47471 return true; 47472 } 47473 47474 _conBMsg.sendQuick = function() { 47475 var id = GLO.Uri.query('id'); 47476 _sendAll(id); 47477 } 47478 47479 function _sendAll(id, clientCount) { 47480 var uri = GLO.Link.WebsiteDomain + 'message/BulkSend?id=' + id; 47481 var j = $('#bulk-email-container'); 47482 var jd = { "id": id }; 47483 var locationId = j.find('#usepid').val(); 47484 47485 if (!UTIL.isEmpty(locationId)) { 47486 uri += '&usepid=' + locationId; 47487 } 47488 47489 if (!_allowSendBlast(jd)) { 47490 return; 47491 } 47492 47493 if (clientCount == 0 || UTIL.coalesceInt(clientCount, 999) > 100) { 47494 var small = '<i class="narrow-text">(if there are more than 100 clients being sent this message)</i>'; 47495 var msg1 = '<p style="margin-top: 16px; line-height: 1.5;">The first 100 messages are sent when scheduled, then the next 100 messages are sent every 5 minutes ' + small + '</p>'; 47496 var msg2 = '<p style="margin-top: 16px; line-height: 1.5;">It might take a few minutes to prepare and schedule all of these messages</p>'; 47497 } else { 47498 var msg1 = '<p>'; 47499 var msg2 = '<p style="margin-top: 16px; line-height: 1.5;">We are preparing and scheduling each of these messages</p>'; 47500 } 47501 47502 var htm = '<div id="pop-processing-message-blast">' + msg1 + msg2 + '</div>'; 47503 47504 GLO.UI.Form.beginProcessing(j.find('#btnSendAll')); 47505 var jprocessing = GLO.Popup.Processing.open(htm, 'Preparing & Scheduling Messages'); 47506
47507 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 47508 .success(function(data, textStatus, jqXHR) { 47509 GLO.UI.Form.resetProcessing(); 47510 var warning = UTIL.coalesceInt($(data).attr('warning_cd')); 47511 47512 if (warning > 399) { 47513 var msg = '<div id="pop-warn-message-blast-disabled" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>'; 47514 GLO.Popup.Warning.open(msg, 'Message Blast Disabled'); 47515 } else if (warning > 199) { 47516 var msg = '<div id="pop-confirm-message-blast-upgrade" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>'; 47517 new GLO.Popup.Confirm(msg, function() { 47518 document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-package'; 47519 }); 47520 } else if (warning > 0) { 47521 var msg = '<div id="pop-warn-message-blast" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>'; 47522 new GLO.Popup.Warning(msg); 47523 } else { 47524 var msg = '<div style="margin-top: 4px; margin-bottom: 2px; letter-spacing: 1px; font-size: 140%;">Messages Sent</div>'; 47525 new GLO.Popup.Success(msg); 47526 document.location = GLO.Link.WebsiteDomain + 'message/ClientList?bulk_id=' + id; 47527 } 47528 47529 jprocessing.close(); 47530 }) 47531 .error(function(jqXHR, textStatus, errorThrown) { 47532 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 47533 }); 47534 } 47535 47536 function _setBlindCount(j, fmt) { 47537 var jsummary = j.find('#client-list-summary'); 47538 var remaining = _getRemainingMessages(j); 47539 47540 if (fmt == 3) { 47541 var cnt = UTIL.coalesceInt(jsummary.attr('client_text_count_nr'), 0); 47542 } else { 47543 var cnt = UTIL.coalesceInt(jsummary.attr('client_email_count_nr'), 0); 47544 } 47545 47546 if (cnt > remaining) { 47547 return remaining; 47548 } else { 47549 return cnt; 47550 } 47551 } 47552 47553 function _getScheduleDate() { 47554 var jpop = $('#pop-confirm-send-blast').closest('.glopop'); 47555 var day = jpop.find('#Blast_d').val(); 47556 var tm = jpop.find('#Blast_tm').val(); 47557 47558 if (UTIL.isDate(day + ' ' + $.trim(tm))) { 47559 var dt = new Date(day + ' ' + $.trim(tm)); 47560 return dt.toGloDate() + ' ' + dt.toGloTime(); 47561 } else if (UTIL.isDate(day)) { 47562 return new Date(day).toGloDate(); 47563 } else { 47564 return ''; 47565 } 47566 } 47567 47568 function _isValidSend(subject, body, fmt) { 47569 var css = 'letter-spacing: 1px; font-size: larger;'; 47570 47571 if (UTIL.isEmpty(subject) && fmt == 1) { 47572 var msg = '<h1 style="margin-bottom: 0; color: White; ' + css + '">' + SA.Resource.NoSubject + '</h1><div style="' + css + '">' + SA.Resource.PleaseIncludeSubject + '</div>'; 47573 47574 new GLO.Popup.Warning(msg, function() { 47575 $('#bulk-email-container #Subject_vc').focus(); 47576 }); 47577 return false; 47578 } else if (UTIL.isEmpty(body)) { 47579 var msg = '<h1 style="margin-bottom: 0; color: White; ' + css + '">' + SA.Resource.NoMessage + '</h1><div style="' + css + '">' + SA.Resource.Please_include_a_message + '</div>'; 47580 47581 new GLO.Popup.Warning(msg, function() { $('#email-body-container .sa-text-editor').focus(); }); 47582 return false; 47583 } 47584 47585 return true; 47586 } 47587 47588 _conBMsg.save = function(sendSample, sendAll, displayPreview, sendBlind) { 47589 var j = $('#bulk-email-container'); 47590 var jpopPreview = $('#pop-preview-message').closest('.glopop'); 47591 var mbid = j.find('#Message_Bulk_id').val(); 47592 var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value'); 47593 var mmsAttachmentName = ''; 47594 var smsSegments = 1; 47595 var mmsPrice = 0.035; 47596 var locationId = j.find('#usepid').val(); 47597 47598 if (fmt == 1) { 47599 var subject = j.find('#Subject_vc').val(); 47600 var body = j.find('#email-body-container .sa-text-editor')[0].innerHTML; //j.find('#Body_vc').val(); 47601 body = UTIL.htmlEncode(DOMPurify.sanitize(body)); 47602 var up = j.find('#Include_Username_Password_fl').prop('checked'); 47603 } else if (fmt == 6) { //mms 47604 var subject = null, up = null; 47605 var body = UTIL.htmlEncode(j.find('#mms_text_vc').val()); 47606 mmsAttachmentName = j.find('#mms-uploaded-file-name').text(); 47607 var resultTuple = GLO.Message.Bulk.calcMmsPartsAndPrice(body); 47608 smsSegments = resultTuple.item1; 47609 mmsPrice = resultTuple.item2; 47610 } 47611 else { //sms 47612 var subject = null, up = null; 47613 var body = UTIL.htmlEncode(j.find('#Text_vc').val()); 47614 } 47615 47616 if (!_isValidSend(subject, body, fmt)) { 47617 return; 47618 /* } else if (sendAll && UTIL.isEmpty(mbid)) { 47619 sendAll = false; 47620 displayPreview = true; 47621 //jpopProcessing = GLO.Popup.Processing.open('Please Preview Message before sending', 'Saving Message...').getPopup(); 47622 */ 47623 } 47624 47625 var isDisplayEmailPreview = (displayPreview && fmt == 1); 47626 var cxml = _getCxml(j, true, fmt); 47627 var clientCount = $(_getCxml(j, false, fmt)).find('tr').length
47628 var dtSchedule = _getScheduleDate(); 47629 var jd = { "Message_Bulk_id": mbid, "subject": subject, "body": body, "Include_Username_Password_fl": up, "Message_Format_cd": fmt 47630 , "Send_Sample_fl": UTIL.parseBool(sendSample), "Preview_fl": isDisplayEmailPreview, "Send_Blind_fl": sendBlind, "schedule_dt": dtSchedule, 47631 "client_xml": cxml, "mms_image_filename_vc": mmsAttachmentName, "sms_segments": smsSegments, "mms_price": mmsPrice }; 47632 47633 if (!_isValidScheduleDate(dtSchedule, fmt)) { return false; } 47634 47635 if (UTIL.parseBool(sendBlind)) { jd.Send_Blind_Count_nr = _setBlindCount(j, fmt); } 47636 47637 var uri = GLO.Link.WebsiteDomain + 'message/ClientList'; 47638 GLO.UI.Form.beginProcessing(j.find('.btnSave')); 47639 47640 if (!UTIL.isEmpty(locationId)) { 47641 uri += '?usepid=' + locationId; 47642 } 47643 47644 if (sendSample) { 47645 GLO.UI.Form.beginProcessing(jpopPreview.find('#btnSendSample')); 47646 } else { 47647 GLO.UI.Form.beginProcessing(jpopPreview.find('#btnSendAll')); 47648 } 47649 47650 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 47651 .success(function(data, textStatus, jqXHR) { 47652 GLO.UI.Form.resetProcessing(); 47653 GLO.Popup.closeIfExist(jpopPreview); 47654 47655 _initSaveButton(); 47656 47657 var j = $('#bulk-email-container #btnSaveForLater').find('a').css({ "border-color": "transparent" }); 47658 var jdata = $(data); 47659 47660 if (UTIL.isEmpty(mbid)) { 47661 if (jdata.length > 3) { 47662 mbid = jdata.eq(3).attr('message_bulk_id') 47663 } else { 47664 mbid = jdata.attr('message_bulk_id'); 47665 } 47666 47667 var jmbid = $('#bulk-email-container #Message_Bulk_id').val(mbid); 47668 } 47669 47670 if (sendAll || sendBlind) { 47671 _sendAll(mbid, clientCount); 47672 } else if (sendSample) { 47673 var success_htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">Changes Saved</h1><div class="friendly-msg4" style="margin-bottom: 20px; font-size: large;">Sample Sent to You</div></div>'; 47674 new GLO.Popup.Info(success_htm); 47675 47676 _conBMsg.getScore(); 47677 } else if (displayPreview) { 47678 if (isDisplayEmailPreview) { 47679 _displayPreview(data); 47680 _conBMsg.getScore(); 47681 } 47682 47683 if (GLO.Popup.closeIfExist($('#pop-processing-please-preview').closest('.glopop'))) { 47684 _previewBeforeSending(fmt, false); 47685 } 47686 } else { 47687 var success_htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">Changes Saved</h1><div class="friendly-msg4" style="margin-bottom: 20px; font-size: large;">Changes Saved</div></div>'; 47688 new GLO.Popup.Info(success_htm); 47689 _conBMsg.getScore(); 47690 } 47691 47692 if (UTIL.isEmpty(GLO.Uri.query('id'))) { 47693 //GLO.Uri.query('id', mbid); //window.history.pushState('Client Marketing', 'Client Marketing', '/message/ClientList?id=' + mbid); 47694 var newUrl = GLO.Uri.addQueryKeyAndValue(location.href, 'id=' + mbid); 47695 window.history.pushState('Message Blast', 'Client Marketing', newUrl); 47696 } 47697 }) 47698 .error(function(jqXHR, textStatus, errorThrown) { 47699 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 47700 }); 47701 } 47702 47703 function _isValidScheduleDate(dtSchedule, fmt) { 47704 if (fmt == 3) { 47705 var day = new Date(dtSchedule); 47706 47707 var dayAtEightPM = new Date(day); 47708 dayAtEightPM.setHours(20); 47709 dayAtEightPM.setMinutes(0); 47710 47711 var dayAtNineAM = new Date(day); 47712 dayAtNineAM.setDate(dayAtNineAM.getDate()); 47713 dayAtNineAM.setHours(9); 47714 dayAtNineAM.setMinutes(0); 47715 47716 var fn = function() { $('#pop-confirm-send-blast #Blast_tm').focus(); } 47717 47718 if (day > dayAtEightPM) { 47719 var msg = 'Cannot Send Texts After 8 PM'; 47720 GLO.Popup.Warning.open(msg, 'Invalid Time', fn); 47721 return false; 47722 } else if (day < dayAtNineAM) { 47723 var msg = 'Cannot Send Texts Before 9 AM'; 47724 GLO.Popup.Warning.open(msg, 'Invalid Time', fn); 47725 return false; 47726 } 47727 } 47728 47729 return true; 47730 } 47731 47732 function _displayPreview(data) { 47733 if (GLO.Info.isMobile() || innerWidth < 500) { 47734 var style = '', btnSample = 'Send Sample', btnSendAll = 'Send', h1Text = 'Preview'; 47735 var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;'; 47736 } else { 47737 var btnSample = 'Send Sample (to me)', btnSendAll = 'Send Message', h1Text = 'Email Preview'; 47738 var style = ''; //' style="width: ' + parseInt(innerWidth * .9) + 'px;"' 47739 var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;'; 47740 } 47741 47742 var htmlButtons = '<div id="pop-preview-message-buttons">' 47743 + '<span id="btnSendSample" class="btnSendSample btnAdd"> <a onclick="GLO.Message.Bulk.sendSample()">' + btnSample + '</a> </span>' 47744 + '<span class="btnOk btn">
47744<a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>' 47745 + '<span id="btnSendAll" class="btnAdd btnAction1"> <a onclick="GLO.Message.Bulk.sendAll()">' + btnSendAll + '</a> </span>' 47746 + '</div'; 47747 47748 var uploadHtm = $('#be-message-widgets .sa-upload').outerHTML(); 47749 47750 var h1 = '<h1 style="position: relative; margin-bottom: 0;">' 47751 + uploadHtm //+ '<span id="btnChangeImage" class="btnAdd"> <a onclick="GLO.Message.Bulk.changeImage()">Change Image</a> </span>' 47752 + '<span style="' + h1style + '">' + h1Text + '</span>' 47753 + '</h1>'; 47754 47755 var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>'); 47756 GLO.Mobile.formatExternalLinksForIos(jhtm); 47757 47758 var ojpop = new GLO.Popup.Custom(jhtm); 47759 var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" }); 47760 47761 jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons); 47762 jpop.find('.msg').css({ "max-width": "900px" }); 47763 47764 var h1 = jpop.find('h1'); 47765 h1.find('form').css({ "float": "left" }); 47766 h1.find('input'); 47767 47768 SA.Uploader.init(jpop, GLO.Message.Bulk.imageUploadComplete); 47769 47770 if (!GLO.Info.isMobile()) { 47771 var jscroll = jpop.find('.msg'); 47772 var width = jscroll.width() + 12; 47773 47774 if (width < 500 && innerWidth >= 500) { 47775 width = 500; 47776 } 47777 47778 jscroll.width(width); 47779 } 47780 47781 setTimeout(ojpop.realign, 800); //= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout). 47782 } 47783 47784 _conBMsg.initMMSIndicators = function() { 47785 //character count display for mms content 47786 $('#mms_text_vc').keyup(function() { 47787 47788 var characterCount = $('#mms_text_vc').val().length, 47789 current = $('#mms-current'), 47790 maximum = $('#mms-maximum'), 47791 theCount = $('#mms-char-count'); 47792 47793 current.text(characterCount); 47794 47795 //800 characters mms limit, warn after 600 chars 47796 if (characterCount >= 600) { 47797 maximum.css('color', '#8f0001'); 47798 current.css('color', '#8f0001'); 47799 theCount.css('font-weight','bold'); 47800 } else { 47801 current.css('color', '#666'); 47802 maximum.css('color','#666'); 47803 theCount.css('font-weight','bold'); 47804 } 47805 47806 GLO.Message.Bulk.replaceMmsWithGsmEquivalent(); 47807 GLO.Message.Bulk.displayMmsPartsAndPrice(); 47808 }); 47809 } 47810 47811 _conBMsg.destroyMMSIndicators = function() { 47812 47813 $('#mms_text_vc').unbind(); 47814 } 47815 47816 _conBMsg.launchMMSPreview = function(event) { 47817 47818 //validate if message is present 47819 var fmt = $('#Message_Format_cd').find('li.selected').attr('value'); 47820 var subject = null, up = null; 47821 var body = UTIL.htmlEncode($('#mms_text_vc').val()); 47822 if (!_isValidSend(subject, body, fmt)) { 47823 return; 47824 } 47825 47826 mmsPreviewModal = $('#mms-preview-iphone-container').modal(); 47827 // var jModal = $('#simplemodal-container #mms-preview-iphone-container'); 47828 var h = $(window).height() * 0.8; 47829 var w = $(window).width() * 0.8; 47830 47831 $.modal.update(h,w); 47832 $(window).resize(); 47833 $('.modalCloseImg').css("margin-top","20px"); 47834 $('.modalCloseImg').css("margin-right","20px"); 47835 $('.modalCloseImg').on("click",function() { GLO.Message.Bulk.closeMMSImageUpload(); }); 47836 47837 //set the preview image 47838 var img_path = $('#mms-image-path').val(); 47839 if (img_path) { 47840 $('#mms-preview-image').removeClass('hide'); 47841 //assign image path to mms preview image 47842 document.querySelector('#mms-preview-image').src = img_path; 47843 } 47844 else { 47845 $('#mms-preview-image').addClass('hide'); 47846 } 47847 //set the preview message 47848 var message = $('#mms_text_vc').val(); 47849 //get message text from text area 47850 $('#mms-preview-message').text(message); 47851 47852 if (GLO.Info.isMobile()) { 47853 $('#simplemodal-container').draggable({disable:true}); 47854 } 47855 $('#simplemodal-container').css("overflow-y","auto"); 47856 47857 // GLO.Mobile.formatExternalLinksForIos(jhtm); 47858 } 47859 47860 47861 _conBMsg.deleteClients = function() { 47862 var j = $('#be-client-list'); 47863 var cnt = j.find('input:checkbox:checked').length; 47864 47865 if (cnt === 0) { 47866 var fn = null, h1 = 'No Client Selected'; 47867 var msg = 'To delete clients please first check the box to the left of the client\'s name'; 47868 } else { 47869 var h1 = 'Confirm Delete'; 47870 var msg = 'Delete ' + UTIL.makePlural(cnt, 'Client') + '?'; 47871 var fn = GLO.Message.Bulk.deleteClientsConfirmed; 47872 } 47873 47874 GLO.Popup.Confirm.open(msg, h1, fn); 47875 } 47876 47877 _conBMsg.deleteClientsConfirmed = function() { 47878 var j = $('#be-client-list'); 47879 var uri = GLO.Link.WebsiteDomain + 'message/ClientDelete'; 47880 var cnt = 0, xml = '<table>', trs = j.find('tbody tr'); 47881 47882 for (var i=0; i < trs.length; i++) {
47883 if (trs.eq(i).find('input:checkbox').prop('checked')) { 47884 xml += '<tr client_id="' + trs.eq(i).attr('client_id') + '"/>'; 47885 } 47886 } 47887 47888 var jd = { "client_xml": UTIL.htmlEncode(xml + '</table>') }; 47889 GLO.UI.Form.beginProcessing(j.find('.btnDelete')); 47890 47891 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 47892 .success(function(data, textStatus, jqXHR) { 47893 var msg = UTIL.pluralLabel(cnt, 'Client') + ' Deleted'; 47894 47895 GLO.Popup.Success.open(msg, 'Clients Deleted'); 47896 GLO.UI.Form.resetProcessing(); 47897 GLO.Message.Bulk.filter(); 47898 }) 47899 .error(function(jqXHR, textStatus, errorThrown) { 47900 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 47901 }); 47902 } 47903 47904 _conBMsg.launchMMSImageUpload = function(event) { 47905 47906 mmsImageUploadModal = $('#mms-manage-image-container').modal(); 47907 var jModal = $('#simplemodal-container #mms-manage-image-container'); 47908 var h = $(window).height() * 0.8; 47909 var w = $(window).width() * 0.8; 47910 47911 $.modal.update(h,w); 47912 $(window).resize(); 47913 $('.modalCloseImg').css("margin-top","20px"); 47914 $('.modalCloseImg').css("margin-right","20px"); 47915 $('.modalCloseImg').on("click",function() { GLO.Message.Bulk.closeMMSImageUpload(); }); 47916 47917 if (GLO.Info.isMobile()) { 47918 $('#simplemodal-container').draggable({disable:true}); 47919 } 47920 $('#simplemodal-container').css("overflow-y","auto"); 47921 47922 $('#mms-file-upload-controls').removeClass('hide'); 47923 $('#mms-uploaded-file-container').addClass('hide'); 47924 47925 } 47926 47927 _conBMsg.closeMMSImageUpload = function() { 47928 47929 //clear the image display 47930 document.querySelector('#mms-image').src =''; 47931 // close the modal 47932 $.modal.close(); 47933 47934 } 47935 47936 _conBMsg.removeMMSUploadedImage = function() { 47937 47938 //reset MMS upload controls 47939 $('#mms-image-path').val(''); 47940 $('#mms-uploaded-file-name').text(''); 47941 $('#mms-file-upload-controls').removeClass('hide'); 47942 $('#mms-uploaded-file-container').addClass('hide'); 47943 47944 } 47945 47946 _conBMsg.uploadMMSImageAndResize = function () { 47947 //define the width to resize e.g 180px 47948 var resize_width = 600;//without px 47949 47950 //get the image selected 47951 var item = document.querySelector('#uploader').files[0]; 47952 47953 //create a FileReader 47954 var reader = new FileReader(); 47955 47956 //image turned to base64-encoded Data URI. 47957 reader.readAsDataURL(item); 47958 reader.name = item.name;//get the image's name 47959 reader.size = item.size; //get the image's size 47960 reader.onload = function(event) { 47961 var img = new Image();//create a image 47962 img.src = event.target.result;//result is base64-encoded Data URI 47963 img.name = event.target.name;//set name (optional) 47964 img.size = event.target.size;//set size (optional) 47965 img.onload = function(el) { 47966 var elem = document.createElement('canvas');//create a canvas 47967 47968 //scale the image to 600 (width) and keep aspect ratio 47969 var scaleFactor = resize_width / el.target.width; 47970 elem.width = resize_width; 47971 elem.height = el.target.height * scaleFactor; 47972 47973 //draw in canvas 47974 var ctx = elem.getContext('2d'); 47975 ctx.drawImage(el.target, 0, 0, elem.width, elem.height); 47976 47977 //get the base64-encoded Data URI from the resize image 47978 var srcEncoded = ctx.canvas.toDataURL('image/jpeg', 1); 47979 47980 //clear the image display 47981 document.querySelector('#mms-image').src =''; 47982 47983 //assign it to thumb src 47984 document.querySelector('#mms-image').src = srcEncoded; 47985 47986 GLO.Message.Bulk.saveMMSImage(srcEncoded,resize_width); 47987 } 47988 } 47989 } 47990 47991 _conBMsg.saveMMSImage = function(data,width) { 47992 47993 //remove the attached handler 47994 $('#btnSaveMMSImage').off("click"); 47995 47996 var jcontainer = $('#uploader'); 47997 47998 //reset error 47999 $('#mmsImageUploadErrorMessage').addClass('hide'); 48000 48001 var fnCallback = function(jcontainer, fileName, imgId, imgSize) { 48002 if (fileName!=null && fileName.length > 0) { 48003 var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName; 48004 // console.log(img_path); 48005 48006 $('#mms-image-path').val(img_path); 48007 $('#mms-file-upload-controls').addClass('hide'); 48008 $('#mms-uploaded-file-container').removeClass('hide'); 48009 //display the file name 48010 $('#mms-uploaded-file-name').text(fileName); 48011 48012 //close the modal 48013 // $('.simplemodal-close').click(); 48014 } 48015 else { 48016 //display error 48017 $('#mmsImageUploadErrorMessage').removeClass('hide'); 48018 } 48019 } 48020 48021 if (SA.Uploader.uploadImage(data, 'jpg', width, jcontainer, fnCallback)) { 48022 return true; 48023 } 48024 } 48025 48026 //replace common non-GSM characters with GSM equivalents 48027 _conBMsg.replaceMmsWithGsmEquivalent = function() { 48028 let messageBody = $('#mms_text_vc').val(); 48029 var result = UTIL.mmsReplaceNonGsmWithGsmChars(messageBody); 48030 $('#mms_text_vc').val(result); 48031 } 48032 48033 //calculates no. of segments in mms message and approx. price 48034 _conBMsg.calcMmsPartsAndPrice = function(messageBody) { 48035 48036 const mmsBasePrice = 0.035; //in dollars 48037 // parts, price 48038 let resultTuple = { item1: 1, item2: mmsBasePrice }; 48039 let numOfParts = 1; 48040 let mmsPostFix = 'Reply STOP to opt out'; 48041 48042 if (!UTIL.isUnicodeMms(messageBody)) { //gsm 48043 numOfParts = (messageBody.length + mmsPostFix.length) <= 160 ? 1 : Math.ceil((messageBody.length + mmsPostFix.length) / 153); 48044 } 48045 else { //unicode 48046 numOfParts = (messageBody.length + mmsPostFix.length) <= 70 ? 1 : Math.ceil((messageBody.length + mmsPostFix.length) / 67); 48047 } 48048 48049 resultTuple = { item1: numOfParts, item2: (numOfParts * mmsBasePrice) }; 48050 48051 return resultTuple; 48052 } 48053 48054 _conBMsg.displayMmsPartsAndPrice = function() { 48055 48056 let messageBody = $('#mms_text_vc').val(); 48057 var resultTuple = GLO.Message.Bulk.calcMmsPartsAndPrice(messageBody); 48058 48059 var result = resultTuple.item1 + " SMS / " + (resultTuple.item2 * 100).toFixed(2) + '\u00A2 cents per message'; //to cents 48060 $('#mms-price').text(result); 48061 } 48062 48063 return _conBMsg; 48064})(); 48065 48066 48067GLO.Message.Marketing = (function() { 48068 function _conMarketing() { } 48069 48070 _conMarketing.initUpgradeEmail = function(hasValidCreditCard) { 48071 if (!hasValidCreditCard) { 48072 var j = $('#email-option-container'); 48073 48074 //Override save functions 48075 j.find('#Text_Package_fl').attr('onchange', 'GLO.Message.Marketing.displayPleaseAddCreditCard(this)'); 48076 j.find('#email-option-list').find('.btnSave > a').attr('onclick', 'GLO.Message.Marketing.displayPleaseAddCreditCard(this)'); 48077 } 48078 48079 //$('#text-package-edit-container').find(':radio').on('click', GLO.Message.Marketing.changeTextPackage); 48080 _initOptIn(); 48081 _initMessagePlan(); 48082 _initUrlActions(); 48083 } 48084 48085 function _initOptIn() { 48086 var plan = $('#Message_Plan_cd').val(); 48087 var j = $('#text-package-edit-container').addClass('message-plan-' + plan); 48088 48089 if ($('#text-optin-phoneco-optional').length) { //= has valid cc or is VAR 48090 j.addClass('is-paid-account'); 48091 } else { 48092 j.addClass('is-not-paid-account'); 48093 } 48094 } 48095 function _initMessagePlan() { 48096 var j = $('#message-opt-in-and-plan'); 48097 var jplan = j.find('#Message_Plan_cd'); 48098 var trpackage = j.find('#message-plan-body-package tr.is-current-package'); 48099 //var textPackage = j.find(':radio[name="Text_Package_cd"]:checked').val(); 48100 48101 if (trpackage.length) { 48102 var emailCount = trpackage.find('.email-option-email').text(); 48103 var textCount = trpackage.find('.email-option-text').text(); 48104 var htmOption = '<option class="current-plan" value="package" selected="selected">Package: ' + emailCount + ' Email / ' + textCount + ' Text</option>'; 48105 48106 jplan.find('option[value="package"]').replaceWith(htmOption); 48107 } 48108 48109 $('#message-plan-tab-' + jplan.val() + ' > a').click(); 48110 } 48111 48112 _conMarketing.displayPleaseAddCreditCard = function() { 48113 var fn = function() { document.location = GLO.Link.WebsiteDomain + 'provider/profile/6'; }; 48114 var msg = '<div class="friendly-msg2">Please add a valid credit card before adding an email blast package</div>'; 48115 new GLO.Popup.Warning(msg, fn); 48116 } 48117 48118 function _initUrlActions() { 48119 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 48120 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 48121 48122 if (!UTIL.isEmpty(open)) { 48123 if (open === 'help') { 48124 var page = UTIL.coalesceInt(GLO.Uri.hash('page'), 0); 48125 GLO.Message.Marketing.openHelp(page); 48126 } 48127 } 48128 48129 if (highlight.toLowerCase() === 'message-plan') { 48130 _conMarketing.gotoMessagePlan(); 48131 } else if (highlight.toLowerCase() === 'message-package') { 48132 _conMarketing.gotoMessagePackage(); 48133 } else if (highlight.toLowerCase() === 'text-option') { 48134 var jtext = $('#email-option-help-extra-text-package'); 48135 UI.highlight(jtext, 1200, 6400, true); 48136 } else if (!UTIL.isEmpty(highlight)) { 48137 var jhighlight = $('#' + highlight + ', .' + highlight); 48138 48139 if (jhighlight.length > 0) { 48140 UI.highlight(jhighlight, 800, 6400, true); 48141 } 48142 } 48143 48144 GLO.Info.displayHelloBarBackToAdvanced(); 48145 } 48146 48147 _conMarketing.setMessagePlan = function(msgPlanValue) { 48148 $('#Message_Plan_cd').val(msgPlanValue).change(); 48149 } 48150 _conMarketing.changeMessagePlan = function(selectElement) { 48151 var jPlanCurrent = $('#Message_Plan_cd').find('option.current-plan'); 48152 48153 if (selectElement.value == 'package') { 48154 $('#message-plan-tab-package > a').click(); 48155 48156 function fn() { 48157 var jhigh = $('#email-option-list'); 48158 UI.highlight(jhigh, 600, 5000, true); 48159 } 48160 48161 GLO.Popup.Info.openSimple('Select a Message Package', 'Change Message Plan', fn); 48162 var textPackage = null, emailPackage = null; //, isRemovePackage = false; 48163 } else { 48164 if (selectElement.value == 'free') { 48165 var emailPackage = 0; 48166 48167 if (_canTurnOnTextPackage()) { 48168 var textPackage = 20; 48169 } else { 48170 var textPackage = 0; 48171 } 48172 } else if (selectElement.value == 'pay-as-use') { 48173 var textPackage = 50, emailPackage = 100; 48174 } 48175 48176 //var isRemovePackage = (jPlanCurrent.val() == 'package'); 48177 } 48178 48179 jPlanCurrent.prop('selected', true); 48180 48181 /* if (isRemovePackage) { 48182 $('#email-option-list').find('tbody tr:first .btnSave > a').click(); 48183 //_conMarketing.changeTextPackage(textPackage); 48184 } */ 48185 48186 if (textPackage && textPackage != $('#message-opt-in').find(':radio[name="Text_Package_cd"]').val()) { 48187 //$('#message-opt-in').find(':radio[name="Text_Package_cd"][value="' + textPackage + '"]').click(); 48188 GLO.Message.Marketing.changeTextPackage(textPackage); 48189 } 48190 48191 if (!UTIL.isEmpty(emailPackage) && _canChangeMessagePackage()) { 48192 GLO.Message.Marketing.changeEmailPackageConfirmed(emailPackage); 48193 } 48194 } 48195 48196 function _canTurnOnTextPackage() { 48197 var epackage = $.trim($('#email-option-list').find('.check-mark').closest('tr').attr('package_upgrade_cd')); 48198 48199 if (!GLO.Provider.isPaidAccount()) { 48200 var fn = function() { document.location = document.location.protocol + '//' + location.host + '/provider/profile/6'; }; 48201 48202 var h1 = '<h1 class="friendly-msg2">Requires Paid Package</h1>'; 48203 48204 if (GLO.Data.provider.signupDetail > 499) { 48205 var msg = '<p>To enable this option please use a valid credit card</p>'; 48206 } else { 48207 var msg = '<p>To enable this option please select a paid ' + GLO.Info.getScheduleAnyoneHtm(
48207) + ' package</p>'; 48208 } 48209 48210 new GLO.Popup.Info('<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>', fn); 48211 return false; 48212 /* Mar 2019: only requires paid package 48213 } else if (epackage === '' && !GLO.Provider.isValidGoldPackage()) { 48214 var fn = function() { GLO.Message.Marketing.gotoMessagePackage(true); }; 48215 var h1 = '<h1 class="friendly-msg2">Requires Paid Message Package</h1>'; 48216 var msg1 = '<p>To enable this option please select a paid message package</p>'; 48217 var msg2 = '<p>' + GLO.Info.getScheduleAnyoneHtm() + ' offers paid email from $5/month - $125/month</p>'; 48218 48219 new GLO.Popup.Info('<div>' + h1 + '<div class="friendly-msg2">' + msg1 + msg2 + '</div></div>', fn); 48220 return false; 48221 */ 48222 } else { 48223 return true; 48224 } 48225 } 48226 48227 _conMarketing.saveTextPackage = function(textPackage) { 48228 var url = GLO.Link.Page.Provider.Home + 'manage/TextPackage?textPackage=' + textPackage; 48229 48230 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 48231 .success(function(data, textStatus, jqXHR) { 48232 new GLO.Popup.Success('Text Configuration Changed'); 48233 var rdo = $('#text-package-edit-container :radio'); 48234 48235 for (var i=0; i < rdo.length; i++) { 48236 if (rdo.eq(i).val() == textPackage) { 48237 rdo.eq(i).attr('checked', 'checked'); 48238 } else { 48239 rdo.eq(i).removeAttr('checked'); 48240 } 48241 } 48242 48243 if (textPackage > 0) { 48244 $('#Text_Package_fl').prop('checked', true); 48245 } else { 48246 $('#Text_Package_fl').prop('checked', false); 48247 } 48248 48249 var htm = '<div id="pop-processing-save-text"> <p>Your change has been saved</p> <p>Re-loading your new settings...</p> </div>'; 48250 GLO.Popup.Processing.open(htm, 'Text Configuration Changed'); 48251 48252 setTimeout(function() { 48253 location.reload(); 48254 }, 800); 48255 }) 48256 .error(function(jqXHR, textStatus, errorThrown) { 48257 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48258 }); 48259 } 48260 48261 _conMarketing.changeTextFlag = function(element, event) { 48262 var isYes = $(element).is(':checked'); 48263 48264 if (isYes) { 48265 if (_canTurnOnTextPackage()) { 48266 var textPackage = $('#text-package-edit-container').attr('original_text_package_cd'); 48267 48268 if (textPackage == 0) { textPackage = 20; } 48269 48270 _conMarketing.saveTextPackage(textPackage); 48271 } else { 48272 $(element).prop('checked', false); 48273 } 48274 } else { 48275 _conMarketing.saveTextPackage(0); 48276 } 48277 } 48278 48279 _conMarketing.selectTextPackage = function(radioElement) { 48280 var j = $('#text-package-edit-container'); 48281 var originalPackage = UTIL.coalesceInt(j.attr('original_text_package_cd'), 0); 48282 var textPackage = radioElement.value; 48283 48284 j.find(':radio[name="Text_Package_cd"][value="' + originalPackage + '"]').prop('checked', true); 48285 48286 setTimeout(function() { 48287 $('#text-package-edit-container').find(':radio[name="Text_Package_cd"][value="' + originalPackage + '"]').prop('checked', true); 48288 }, 800); 48289 48290 _conMarketing.openTextOptInHelp(textPackage, originalPackage, true); 48291 } 48292 _conMarketing.changeTextPackage = function(textPackage) { 48293 //var textPackage = element.value; 48294 48295 if (textPackage == 0 || _canTurnOnTextPackage()) { 48296 _conMarketing.saveTextPackage(textPackage); 48297 } 48298 } 48299 48300 _conMarketing.gotoMessagePlan = function() { 48301 GLO.Popup.close(); 48302 UI.highlight($('#message-plan-container'), 1200, 4800, true); 48303 } 48304 _conMarketing.gotoMessagePackage = function(ignoreFreeOption) { //great animation example! 48305 GLO.Popup.close(); 48306 $('#message-plan-tab-package > a').click(); //=open tab 48307 48308 var tblPackages = $('#email-option-list'); 48309 UI.highlight(tblPackages, 1200, 4800, true); 48310 } 48311 48312 function _canChangeMessagePackage() { 48313 if (GLO.Provider.isPaidAccount()) { 48314 return true; 48315 } 48316 48317 if (GLO.Data.provider.signupDetail > 499) { 48318 var upgradeLabel = 'Update Credit Card'; 48319 } else { 48320 var upgradeLabel = 'Upgrade Now'; 48321 } 48322 48323 var upgradeButton = '<span style="position: absolute; left: 4px; bottom: 12px; min-height: 20px;" class="btnAdd">
48323<a onclick="GLO.Uri.gotoUri(\'/provider/profile/6\')">' + upgradeLabel + '</a></span>'; 48324 48325 var h1 = '<h1 class="friendly-msg2">Paid Package Required to Send Marketing Message</h1>'; 48326 var msg = '<div>You must have an active paying account to send marketing messages</div>'; 48327 var htm = '<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>'; 48328 48329 var jpop = new GLO.Popup.Info(htm).getPopup(); 48330 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 48331 48332 jbtns.find('.btnOk').css({ "padding-top": "7px" }).find('>a').text('Close').css({ "padding-top": "4px", "padding-bottom": "3px" }); 48333 jbtns.prepend(upgradeButton); 48334 48335 return false; 48336 } 48337 48338 _conMarketing.changeEmailPackage = function(btn) { 48339 if (!_canChangeMessagePackage()) { return false; } 48340 48341 var btn = $(btn).parent(); 48342 var j = $('#email-option-list'); 48343 var jcurrent = j.find('.check-mark').closest('tr'); 48344 var jnew = btn.closest('tr'); 48345 48346 var currentPrice = UTIL.coalesceMoney(jcurrent.find('.email-option-price').text().replace('$', ''), 0); 48347 var newPrice = UTIL.coalesceMoney(jnew.find('.email-option-price').text().replace('$', ''), 0); 48348 var package_upgrade_cd = jnew.attr('package_upgrade_cd'); 48349 48350 var emailCount = '<b class="narrow-text" style="color: inherit;">' + jnew.find('.email-option-email').text() + ' Email Blast / Normal Texts</b>'; 48351 var textCount = '<b class="narrow-text" style="color: inherit;">' + jnew.find('.email-option-text').text() + ' Text Blast</b></p>'; 48352 var newPlan = '<p style="margin-left: 12px; line-height: 1.4; font-size: larger;">' + emailCount + ' or ' + textCount + '</p>'; 48353 var combo = '<p style="margin-left: 24px; line-height: 1.4; letter-spacing: 0;">(or combination of Normal Texts / Email Blasts and Text Blasts)</p>'; 48354 48355 if (newPrice > currentPrice) { 48356 var msg = '<p style="line-height: 1.4;">Do you want to upgrade your <b>Message Package</b> to:</p>' + newPlan + combo 48357 + '<p style="margin-top: 24px; margin-bottom: 12px;">You will be billed ' + UTIL.displayMoney(newPrice - currentPrice) + ' today</p>' 48358 + '<p>Your monthly price will be ' + UTIL.displayMoney(newPrice) + '</p>'; 48359 } else if (newPrice < currentPrice) { 48360 var msg = '<p style="line-height: 1.4;">Do you want to downgrade your <b>Message Package</b> to:</p>' + newPlan + combo; 48361 48362 if (newPrice != 0) { 48363 msg += '<p style="margin-top: 24px;">Your new monthly price will be ' + UTIL.displayMoney(newPrice) + '</p>'; 48364 } 48365 } 48366 48367 var htm = '<div id="pop-email-package-confirm" package_upgrade_cd="' + package_upgrade_cd + '" style="margin-bottom: 24px;">' + msg + '</div>'; 48368 var jpop = GLO.Popup.Confirm.open(htm, 'Change Monthly Message Package', GLO.Message.Marketing.changeEmailPackageConfirmed).getPopup(); 48369 jpop.find('.msg').css({ "margin-top": "0", "line-height": "200%" }); 48370 } 48371 48372 _conMarketing.changeEmailPackageConfirmed = function(package_upgrade_cd) { 48373 var jpop = $('#pop-email-package-confirm'); 48374 48375 if (jpop.length) { 48376 package_upgrade_cd = jpop.attr('package_upgrade_cd'); 48377 } 48378 48379 var url = GLO.Link.Page.Provider.Home + 'manage/UpdateEmailPackage'; 48380 var jsave = $('#email-option-list').find('tr[package_upgrade_cd = "' + package_upgrade_cd + '"] .btnSave'); 48381 48382 GLO.UI.Form.beginProcessing(jsave); 48383 48384 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "email_package_cd": package_upgrade_cd } }) 48385 .success(function(data, textStatus, jqXHR) { 48386 //GLO.UI.Form.resetProcessing(jsave); 48387 48388 GLO.Popup.close(jpop.closest('.glopop')); 48389 new GLO.Popup.Success('Email Package Changed'); 48390 setTimeout(function() { location.reload(); }, 600); 48391 }) 48392 .error(function(jqXHR, textStatus, errorThrown) { 48393 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48394 }); 48395 } 48396 48397 _conMarketing.lookupStaffAlertHelp = function() { 48398 var loadUrl = GLO.Link.Object.Provider.Wiz5StaffConfig + '?dt=' + UTIL.getDateString(); 48399 var pop = $('#wiz5-popupStaffConfig'); 48400 48401 pop.load(loadUrl, function() { 48402 jhtm = pop.find('#wiz5-popupStatus-alert-help > div'); 48403 _conMarketing.openStaffAlertHelp(jhtm); 48404 }); 48405 } 48406 48407 _conMarketing.openStaffAlertHelp = function(jhtm) { 48408 if (UTIL.isEmpty(jhtm)) { 48409 jhtm = $('#wiz5-popupStatus-alert-help > div').clone(); 48410 } 48411 48412 var ojpop = new GLO.Popup.Custom(jhtm); 48413 var jpop = ojpop.getPopup(); 48414 var h1 = jpop.find('h1').css({ "margin-bottom": "0" }); 48415 48416 var jbtns = jpop.find('.pop-buttons-parent'); 48417 jbtns.find('.btnSave').remove(); 48418 jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "auto", "padding": 0 }).find('>a').text('Close'); 48419 48420 _addMoreHelpButton(jpop, h1); 48421 _customizeStaffAlertHelp(jpop); 48422 ojpop.realign(); 48423 } 48424 48425 function _addMoreHelpButton(jpop, h1) { 48426 if (GLO.Info.roleType < 210) { return; } 48427 48428 var jmsg = jpop.find('.msg').addClass('help-post').css({ "padding-top": "0" }); 48429 var htmButtonText = 'More on Notifications sent from <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span>'; 48430 var btnCss = 'btnAdd'; 48431 48432 if (innerWidth < 400) { 48433 btnCss += ' btn3lines'; 48434 } else if (innerWidth < 600) { 48435 btnCss += ' btn2lines'; 48436 } else { 48437 h1.css({ "letter-spacing": "1px" }); 48438 } 48439 48440 var htmButton = '<span class="' + btnCss + '">
48440<a onclick="GLO.Message.Marketing.openStaffAlertHelpMore(this, event)" style="background-color: #275264;">' + htmButtonText + '</a></span>'; 48441 var htmMore = '<div style="margin-top: 20px; margin-bottom: 12px; text-align: center;">' + htmButton + '</div>'; 48442 jmsg.append(htmMore); 48443 } 48444 48445 function _customizeStaffAlertHelp(jpop) { 48446 var jStaffConfig = $('#wiz5-popupStaffConfig'); 48447 var jsummary = jpop.find('#wiz5-popupStatus-alert-help-summary'); 48448 var jintro = jpop.find('#wiz5-popupStatus-alert-help-intro').css({ "padding-top": "6px" }); 48449 48450 if (jStaffConfig.length !== 1 || jsummary.length !== 1) { return; } 48451 48452 var sname = jStaffConfig.find('#wiz5-staffName').text(); 48453 var emailDays = UTIL.coalesceInt(jStaffConfig.find('#Email_Notify_Day_sr').val(), 0); 48454 // var textHours = UTIL.coalesceInt(jStaffConfig.find('#Text_Notify_Hr_sr').val(), 0); 48455 var textHours = 0; 48456 48457 if (!UTIL.isEmpty(sname)) { 48458 sname += ' is'; 48459 } else { 48460 sname = 'You are'; 48461 } 48462 48463 if (emailDays > 0 && textHours > 0) { 48464 var htm = '<b>' + sname + ' setup to get notified</b> <ul>' 48465 + '<li style="margin-bottom: 4px; color: #222;">by email for changes on appointments that start in ' + emailDays + ' days</li>' 48466 + '<li style="margin-bottom: 4px; color: #222;">by text for changes on appointments that start in ' + textHours + ' hours</li>' 48467 + '</ul>'; 48468 } else if (textHours > 0) { 48469 var htm = sname + ' setup to get notified by text for changes on appointments that start in ' + textHours + ' hours'; 48470 } else if (emailDays > 0) { 48471 var htm = sname + ' setup to get notified by email for changes on appointments that start in ' + emailDays + ' days'; 48472 } else { 48473 var htm = sname + ' <b>NOT</b> setup to get notified by email or push notifications for appointment changes'; 48474 } 48475 48476 var divCSS = 'padding-left: 20px; margin-bottom: 32px; padding-bottom: 8px; border-bottom: 1px solid black; font-weight: bold; color: #222;'; 48477 jsummary.replaceWith('<div style="' + divCSS + '">' + htm + '</div>'); 48478 48479 jintro.css({ "background-color": "pink" }); 48480 } 48481 48482 _conMarketing.openStaffAlertHelpMore = function(element, event) { 48483 GLO.UI.Form.beginProcessing( $(element) ); 48484 48485 setTimeout(function() { 48486 document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&helloback=profile#open=help&page=1'; 48487 }, 400); 48488 } 48489 48490 _conMarketing.openHelp = function(stepNumber, highlight) { 48491 SA.Help.openReportHelp('#message-help-pop-container', stepNumber, 'info/MessageHelp'); 48492 48493 if (!UTIL.isEmpty(highlight)) { 48494 var jhigh = $(highlight); 48495 UI.highlight(jhigh); 48496 } 48497 } 48498 48499 _conMarketing.openTextOptInHelp = function(textPackage, originalPackage, isConfirm) { 48500 if (textPackage == 20) { 48501 var labelId = '', jhtm = $('#client-message-default-opt-in'); 48502 } else if (textPackage == 50) { 48503 var jhtm = $('#client-message-direct-text'); 48504 } else { 48505 var jhtm = $('#client-message-default-opt-out'); 48506 } 48507 48508 var htm = jhtm.outerHTML(); 48509 var label = $('#message-text-package' + textPackage).html(); 48510 48511 if (!UTIL.isEmpty(label)) { 48512 htm = '<div id="pop-client-text-optin">' + htm + '<div id="text-optin-header-label">' + label + '</div> </div>'; 48513 } 48514 48515 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Text Opt-In Setting', null, null, true); 48516 var jpop = ojpop.getPopup().addClass('pop-text-opt-in'); 48517 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 48518 48519 if (isConfirm && originalPackage != textPackage) { 48520 var fnSave = function() { 48521 GLO.Message.Marketing.changeTextPackage(textPackage); 48522 }; 48523 48524 jbtns.find('.btnSave').find('> a').text('Change Text Setting').click(fnSave); 48525 } else { 48526 GLO.Popup.Custom.singleButton(jpop, 'Close'); 48527 } 48528 48529 ojpop.realign(); 48530 } 48531 48532 return _conMarketing; 48533})(); 48534 48535 48536GLO.Message.Marketing.NewClient = (function() { 48537 function _cNewClient() { } 48538 48539 _cNewClient.init = function() { 48540 var jcontainer = $('#welcome-email'); 48541 48542 jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() { 48543 jcontainer.find('.btnSave > a').addClass('unsaved'); 48544 }); 48545 jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() { 48546 jcontainer.find('.btnSave > a').addClass('unsaved'); 48547 }); 48548 48549 var jtext = jcontainer.find('.sa-text-editor'); 48550 SA.TextEditor.init(jtext, 'Welcome New Client Message'); 48551 } 48552 48553 _cNewClient.changeEnabled = function() { 48554 var j = $('#welcome-email'); 48555 var jenabled = j.find('#Message_New_Client_fl') 48556 48557 if (jenabled.prop('checked') && !UTIL.parseBool(j.attr('online_booking_fl'))) { 48558 var msg = '<p>Enabling <b class="narrow-text">Welcome New Client Email</b> requires enabling <b class="narrow-text">Oline Booking</b></p>'; 48559 var btn = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?highlight=aob-allow-online-booking\', this, event, true)">Go To Enable Online Booking</a>'; 48560 var htmWarn = '<div id="pop-warn-require-online-booking">' + msg + '<div style="margin: 24px auto;">' + btn + '</div></div>'; 48561 48562 jenabled.prop('checked', false); 48563 GLO.Popup.Warning.open(htmWarn, 'Requires Enabling Online Booking'); 48564 } 48565 } 48566 48567 _cNewClient.sendSample = function() { 48568 var jcontainer = $('#welcome-email'); 48569 var jsample = $('.btnSendSample'), jsave = jcontainer.find('.btnSave'); 48570 var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientMessageSample'; 48571 48572 if (!GLO.Staff.hasEmail(GLO.Info.StaffId)) { 48573 var aProfileMe = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/1\', this, event, true)">Profile -> Me</a>'; 48574 var htmWarn = '<p>Email required to send yourself a sample message</p> <p>Please go to ' + aProfileMe + ' and add your email address</p>'; 48575 48576 GLO.Popup.Warning.open(htmWarn, 'Email Missing'); 48577 return; 48578 } else if (jsave.hasClass('unsaved')) { 48579 _cNewClient.save(false, true); 48580 return; 48581 } 48582 48583 GLO.UI.Form.beginProcessing(jsample); 48584
48585 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 48586 .success(function(data, textStatus, jqXHR) { 48587 GLO.UI.Form.resetProcessing(); 48588 48589 if (UTIL.parseBool($(data).attr('error_fl'))) { 48590 GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview'); 48591 } else { 48592 var htmEmail = '<div style="margin: 8px 0; font-weight: bold;">' + SA.StaffContact[0].email + '</div>'; 48593 var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;'; 48594 var aProfileMe = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + GLO.Link.WebsiteDomain + 'provider/profile/1\', this, event, true)" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>'; 48595 var htmChangeEmail = '<div style="margin: 12px 0;"> <p>You can change your email by going to ' + aProfileMe + '</p></div>'; 48596 var htm = '<div id="pop-info-sample-sent" style="margin-bottom: 24px;"><p>' + SA.Resource.SendSampleSent + '</p>' + htmEmail + htmChangeEmail + '</div>' 48597 48598 GLO.Popup.Info.openSimple(htm, 'Welcome New Client Email'); 48599 } 48600 }) 48601 .error(function(jqXHR, textStatus, errorThrown) { 48602 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48603 }); 48604 } 48605 _cNewClient.preview = function() { 48606 var jcontainer = $('#welcome-email'); 48607 var jpreview = jcontainer.find('.btnPreview'), jsave = jcontainer.find('.btnSave'); 48608 var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientPreview'; 48609 48610 if (jsave.hasClass('unsaved')) { 48611 _cNewClient.save(true, false) 48612 return; 48613 } 48614 48615 GLO.UI.Form.beginProcessing(jpreview); 48616 48617 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 48618 .success(function(data, textStatus, jqXHR) { 48619 GLO.UI.Form.resetProcessing(); 48620 48621 if (UTIL.parseBool($(data).attr('error_fl'))) { 48622 GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview'); 48623 } else { 48624 _displayPreview(data); 48625 } 48626 }) 48627 .error(function(jqXHR, textStatus, errorThrown) { 48628 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48629 }); 48630 } 48631 48632 _cNewClient.save = function(isPreview, isSendSample) { 48633 var jcontainer = $('#welcome-email'); 48634 var msg = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML)); 48635 var subject = jcontainer.find('#Email_Subject_vc').val(); 48636 var isEnabled = jcontainer.find('#Message_New_Client_fl').prop('checked'); 48637 48638 var jd = { "subject": subject, "body": msg, "enable": isEnabled }; 48639 var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientMessage'; 48640 var jsave = jcontainer.find('.btnSave'); 48641 48642 GLO.UI.Form.beginProcessing(jsave); 48643 48644 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 48645 .success(function(data, textStatus, jqXHR) { 48646 GLO.UI.Form.resetProcessing(); 48647 jsave.find('>a').removeClass('unsaved'); 48648 GLO.Popup.Success.open('Welcome New Client Email Settings Saved', 'New Client Email'); 48649 48650 if (isPreview) { 48651 _cNewClient.preview(); 48652 } else if (isSendSample) { 48653 _cNewClient.sendSample(); 48654 } 48655 }) 48656 .error(function(jqXHR, textStatus, errorThrown) { 48657 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48658 }); 48659 } 48660 48661 function _displayPreview(data) { 48662 if (GLO.Info.isMobile() || innerWidth < 500) { 48663 var style = '', btnSample = 'Send Sample', btnSendAll = 'Send', h1Text = 'Preview'; 48664 var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;'; 48665 } else { 48666 var btnSample = 'Send Sample (to me)', btnSendAll = 'Send Message', h1Text = 'Email Preview'; 48667 var style = ''; //' style="width: ' + parseInt(innerWidth * .9) + 'px;"' 48668 var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;'; 48669 } 48670 48671 var htmlButtons = '<div id="pop-preview-message-buttons">' 48672 + '<span id="btnSendSample" class="btnSendSample btnAdd"> <a onclick="GLO.Message.Marketing.NewClient.sendSample()">' + btnSample + '</a> </span>' 48673 + '<span class="btnOk btn">
48673<a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>' 48674 + '</div'; 48675 48676 var h1 = '<h1 style="position: relative; margin-bottom: 0;">' + '<span style="' + h1style + '">' + h1Text + '</span>' + '</h1>'; 48677 var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>'); 48678 GLO.Mobile.formatExternalLinksForIos(jhtm); 48679 48680 var ojpop = new GLO.Popup.Custom(jhtm); 48681 var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" }); 48682 48683 jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons); 48684 jpop.find('.msg').css({ "max-width": "900px" }); 48685 48686 var h1 = jpop.find('h1'); 48687 h1.find('form').css({ "float": "left" }); 48688 h1.find('input'); 48689 48690 SA.Uploader.init(jpop, GLO.Message.Bulk.imageUploadComplete); 48691 48692 if (!GLO.Info.isMobile()) { 48693 var jscroll = jpop.find('.msg'); 48694 jscroll.width(jscroll.width() + 12); 48695 } 48696 48697 setTimeout(ojpop.realign, 800); //= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout). 48698 } 48699 48700 return _cNewClient; 48701})(); 48702 48703 48704GLO.Message.Marketing.Birthday = (function() { 48705 function _cBdayEmail() { } 48706 48707 _cBdayEmail.init = function() { 48708 var jcontainer = $('#birthday-email'); 48709 48710 jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() { 48711 $('#birthday-email').find('.btnSave > a').addClass('unsaved'); 48712 }); 48713 jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() { 48714 $('#birthday-email').find('.btnSave > a').addClass('unsaved'); 48715 }); 48716 48717 var jtext = jcontainer.find('.sa-text-editor'); 48718 SA.TextEditor.init(jtext, 'Birthday Email Message'); 48719 48720 _initDiscountButton(jcontainer); 48721 } 48722 function _initDiscountButton(jcontainer) { 48723 var btnNew = jcontainer.find('#btnNewBdayDiscount'); 48724 var existingProviderDiscountId = _getBirthdayDiscountId(); 48725 48726 if (!UTIL.isEmpty(existingProviderDiscountId)) { 48727 var url = 'provider/manage/discount?open=discount&id=' + existingProviderDiscountId; 48728 var btnUpdate = '<span id="btnUpdateBdayDiscount" class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)">Update Birthday Discount</a></span>'; 48729 btnNew.replaceWith(btnUpdate); 48730 } else { 48731 btnNew.removeClass('hide'); 48732 } 48733 } 48734 48735 function _getBirthdayDiscountId() { 48736 var arr = GLO.Data.DiscountList; 48737 48738 for (var i=0; i < arr.length; i++) { 48739 if (arr[i].discount_type1_cd == 70 || arr[i].discount_type2_cd == 70 || arr[i].discount_type3_cd == 70) { 48740 return arr[i].provider_discount_id; 48741 } 48742 } 48743 } 48744 48745 function _displayPreview(data) { 48746 if (GLO.Info.isMobile() || innerWidth < 500) { 48747 var style = '', btnSample = 'Send Sample', h1Text = 'Preview'; 48748 var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;'; 48749 } else { 48750 var btnSample = 'Send Sample (to me)', h1Text = 'Email Preview'; 48751 var style = ''; //' style="width: ' + parseInt(innerWidth * .9) + 'px;"' 48752 var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;'; 48753 } 48754 48755 var htmlButtons = '<div id="pop-preview-message-buttons">' 48756 + '<span id="btnSendSample" class="btnAdd"> <a onclick="GLO.Message.Marketing.Birthday.sendSample()">' + btnSample + '</a> </span>' 48757 + '<span class="btnOk btn"><a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>' 48758 + '</div'; 48759 48760 var h1 = '<h1 style="position: relative; margin-bottom: 0;"><span style="' + h1style + '">' + h1Text + '</span></h1>'; 48761 var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>'); 48762 GLO.Mobile.formatExternalLinksForIos(jhtm); 48763 48764 var ojpop = new GLO.Popup.Custom(jhtm); 48765 var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" }); 48766 48767 jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons); 48768 jpop.find('.msg').css({ "max-width": "900px" }); 48769 48770 var h1 = jpop.find('h1'); 48771 h1.find('form').css({ "float": "left" }); 48772 h1.find('input'); 48773 48774 if (!GLO.Info.isMobile()) { 48775 var jscroll = jpop.find('.msg'); 48776 jscroll.width(jscroll.width() + 12); 48777 } 48778 48779 setTimeout(ojpop.realign, 800); //= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout). 48780 } 48781 48782 function _canSendSample(messageFormat, isUseSmsGateway) { 48783 if (messageFormat == 3) { 48784 if (GLO.Staff.hasText(GLO.Info.StaffId, isUseSmsGateway)) { 48785 return true; 48786 } 48787 } else if (GLO.Staff.hasEmail(GLO.Info.StaffId)) { 48788 return true; 48789 } 48790 48791 return false; 48792 } 48793 48794 _cBdayEmail.preview = function() { 48795 var jcontainer = $('#birthday-email'); 48796 var jpreview = jcontainer.find('.btnPreview'), jsave = jcontainer.find('.btnSave'); 48797 var url = GLO.Link.WebsiteDomain + 'message/BirthdayPreview'; 48798 48799 if (jsave.hasClass('unsaved')) { 48800 _cBdayEmail.save(true, false) 48801 return; 48802 } 48803 48804 GLO.UI.Form.beginProcessing(jpreview); 48805
48806 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 48807 .success(function(data, textStatus, jqXHR) { 48808 GLO.UI.Form.resetProcessing(); 48809 48810 if (UTIL.parseBool($(data).attr('error_fl'))) { 48811 GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview'); 48812 } else { 48813 _displayPreview(data); 48814 } 48815 }) 48816 .error(function(jqXHR, textStatus, errorThrown) { 48817 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48818 }); 48819 } 48820 _cBdayEmail.sendSample = function() { 48821 var jcontainer = $('#birthday-email'); 48822 var jsample = $('.btnSendSample'), jsave = jcontainer.find('.btnSave'); 48823 var url = GLO.Link.WebsiteDomain + 'message/BirthdaySample'; 48824 48825 if (jsave.hasClass('unsaved')) { 48826 _cBdayEmail.save(true, false) 48827 return; 48828 } else if (!_canSendSample()) { 48829 return; 48830 } 48831 48832 GLO.UI.Form.beginProcessing(jsample); 48833 48834 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 48835 .success(function(data, textStatus, jqXHR) { 48836 GLO.UI.Form.resetProcessing(); 48837 48838 if (UTIL.parseBool($(data).attr('error_fl'))) { 48839 GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview'); 48840 } else { 48841 var htmEmail = '<div style="margin: 8px 0; font-weight: bold;">' + SA.StaffContact[0].email + '</div>'; 48842 var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;'; 48843 var aProfileMe = '<a href="' + GLO.Link.WebsiteDomain + 'provider/profile/1" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>'; 48844 var htmChangeEmail = '<div style="margin: 12px 0;"> <p>You can change your email by going to ' + aProfileMe + '</p></div>'; 48845 var htm = '<div id="pop-info-sample-sent" style="margin-bottom: 24px;"><p>' + SA.Resource.SendSampleSent + '</p>' + htmEmail + htmChangeEmail + '</div>' 48846 48847 GLO.Popup.Info.openSimple(htm, 'Birthday Email'); 48848 } 48849 }) 48850 .error(function(jqXHR, textStatus, errorThrown) { 48851 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48852 }); 48853 } 48854 _cBdayEmail.save = function(isPreview, isSendSample) { 48855 var jcontainer = $('#birthday-email'); 48856 var msg = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML)); 48857 var subject = jcontainer.find('#Email_Subject_vc').val(); 48858 var rdoWhenSend = jcontainer.find('input[type="radio"][name="rdoWhenSend"]:checked').val(); 48859 var jdays = jcontainer.find('#Send_Email_Day_Before_sr'); 48860 48861 if (rdoWhenSend == 'none') { 48862 var days = ''; 48863 } else if (rdoWhenSend == 'bday') { 48864 var days = 0; 48865 } else if (rdoWhenSend == 'before') { 48866 var days = jdays.val(); 48867 } 48868 48869 var jd = { "subject": subject, "body": msg, "days": days }; 48870 var url = GLO.Link.WebsiteDomain + 'message/birthday'; 48871 var jsave = jcontainer.find('.btnSave'); 48872 48873 jdays.val(days); 48874 GLO.UI.Form.beginProcessing(jsave); 48875 48876 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 48877 .success(function(data, textStatus, jqXHR) { 48878 GLO.UI.Form.resetProcessing(); 48879 jsave.find('>a').removeClass('unsaved'); 48880 GLO.Popup.Success.open('Birthday Email Settings Saved', 'Birthday Email'); 48881 48882 if (isPreview) { 48883 _cBdayEmail.preview(); 48884 } else if (isSendSample) { 48885 _cBdayEmail.sendSample(); 48886 } 48887 }) 48888 .error(function(jqXHR, textStatus, errorThrown) { 48889 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 48890 }); 48891 } 48892 48893 return _cBdayEmail; 48894})(); 48895 48896 48897GLO.Message.Marketing.Auto = (function() { 48898 function _conMMAuto() { } 48899 48900 _conMMAuto.init = function(fmtType) { 48901 GLO.Info.requireGoldOrIndependentPackage = true; 48902 UI.initTableSorter($('table.tablesorter:visible'));
48903 _initGrid(); 48904 _initUrlHelp(); 48905 } 48906 function _initUrlHelp() { 48907 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 48908 48909 if (open == 'help') { 48910 GLO.Message.Marketing.Auto.openHelp(); 48911 } 48912 } 48913 function _initGrid() { 48914 var trs = $('#auto-marketing-grid > tbody').find('tr'); 48915 var jdd = $('#auto-marketing-edit-service'); 48916 48917 _initServiceList(jdd); 48918 _resetServiceList(jdd, trs); 48919 _resetOtherService(jdd, trs); 48920 } 48921 48922 function _resetOtherService(jdd, trs) { 48923 if (trs.length > 1) { 48924 var firstOption = jdd.find('option:not(.no):first').text('(' + SA.Resource.any_other_service + ')'); 48925 48926 if (trs.length > 1) { 48927 for (var i=0; i < trs.length; i++) { 48928 if (UTIL.isEmpty(trs.eq(i).attr('service_group_id')) && UTIL.isEmpty(trs.eq(i).attr('service_id'))) { 48929 trs.eq(i).find('.auto-service').text(SA.Resource.any_other_service); 48930 _hideOtherService(jdd, firstOption); 48931 } 48932 } 48933 } else if (UTIL.isEmpty(trs.attr('service_group_id')) && UTIL.isEmpty(trs.attr('service_id'))) { 48934 trs.find('.auto-service').text(SA.Resource.AnyService.toLowerCase()); 48935 _hideOtherService(jdd, firstOption); 48936 } 48937 } else if (trs.length === 0) { 48938 jdd.find('option[value=""]').text(SA.Resource.AnyService.toLowerCase()) 48939 } 48940 } 48941 48942 function _hideOtherService(jdd, firstOption) { 48943 firstOption.addClass('hide'); 48944 48945 var blankOption = jdd.find('option.no').removeClass('hide'); 48946 48947 if (blankOption.length === 0) { 48948 jdd.prepend('<option class="no" value="no"></option>'); 48949 } 48950 } 48951 48952 function _displayOtherService(jdd, firstOption) { 48953 firstOption.removeClass('hide'); 48954 jdd.find('option.no').remove(); //.addClass('hide'); 48955 } 48956 48957 function _resetServiceList(jdd, trs) { 48958 var svc, sg, opt; 48959 48960 for (var i=0; i < trs.length; i++) { 48961 svc = trs.eq(i).attr('service_id'); 48962 sg = trs.eq(i).attr('service_group_id'); 48963 48964 if (!UTIL.isEmpty(svc)) { 48965 opt = jdd.find('option[value="' + svc + '"]'); 48966 } else if (!UTIL.isEmpty(sg)) { 48967 opt = jdd.find('option[value="' + sg + '"]'); 48968 } 48969 48970 if (opt) { 48971 opt.addClass('hide'); 48972 opt = null; 48973 } 48974 } 48975 } 48976 48977 function _initServiceList(jdd) { 48978 var j = jdd.find('.hide'); 48979 48980 for (var i=0; i < j.length; i++) { 48981 j.eq(i).removeClass('hide'); 48982 } 48983 } 48984 48985 _conMMAuto.openHelp = function(onDiffPage) { 48986 var h1 = 'Follow-up Emails'; 48987 48988 if (onDiffPage) { 48989 var url = '\'message/AutoMarketing?helloback=advanced&tabback=client\''; 48990 var btn = '<span class="btnAdd" onclick="GLO.Uri.gotoUri(' + url + ')"> <a style="background-color: blue; border-radius: 4px;">Follow-up Setup</a></span>'; 48991 } else { 48992 var btn = '<span class="btnAdd" onclick="GLO.Message.Marketing.Auto.openEdit()"> <a>New <span>Follow-up Message</span><i class="fa fa-envelope"></i></a></span>'; 48993 } 48994 48995 var msg1 = '<p>Setup ' + GLO.Info.getScheduleAnyoneHtm() + ' to automatically send follow-up messages to clients who have not scheduled their next appointment</p>'; 48996 var msg2 = '<p>Just press ' + btn + ' and select the number of days or weeks after the appointment you want the follow-up to be sent</p>' 48997 var msg3 = '<p>You can create custom messages for different types of services and have them set at different times</p>'; 48998 48999 var ojInfo = GLO.UI.openHelp2(h1, msg1 + msg2 + msg3, 'pop-help-followup'); 49000 var jpop = ojInfo.getPopup().addClass('pop-info2'); 49001 } 49002 49003 _conMMAuto.info = function() { 49004 var ulstyle = 'text-align: left;', style = 'white-space: pre-wrap; line-height: 170%;'; 49005 var p = '<p style="margin-bottom: 12px;">'; 49006 49007 if (GLO.Info.isMobile()) { 49008 ulstyle = 'margin-left: -36px; margin-right: 0;'; 49009 style += ' padding-right: 8px;'; 49010 } 49011 49012 var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.HowMessageIsCreatedUsingAutofills + '</h1>' 49013 +'<div>' 49014 + '<div class="friendly-msg" style="' + style + '">' 49015 + p + 'You can change the subject and message as desired. Some information in the message can be populated for you. </p>' 49016 + p + 'For example, <i><b>{client-name}</b></i> indicates that the client\'s name will be placed there in the message.</p>' 49017 + p + 'Below are some other auto-fills:</p>' //If you preview the message your name will be used as both the client name and staff name. 49018 + '<ul style="' + ulstyle + '">' 49019 + '<li><i style="padding-right: 6px;"><b>{first-name}</b></i> Client First Name</li>' 49020 + '<li><i style="padding-right: 6px;"><b>{client-name}</b></i> Client Name</li>' 49021 + '<li><i style="padding-right: 6px;"><b>{staff-name}</b></i> Staff Name</li>' 49022 + '<li><i style="padding-right: 6px;"><b>{service-name}</b></i> Service Name</li>' 49023 + '<li><i style="padding-right: 6px;"><b>{last-visit}</b></i> Date of Last Visit for this service</li>' 49024 + '<li><i style="padding-right: 6px;"><b>{last-visit-days}</b></i>
49024 Number of days since the Last Visit for this service</li>' 49025 //+ '<li><i style="padding-right: 6px;"><b>{client-username}</b></i> Client\'s Username</li>' 49026 //+ '<li><i style="padding-right: 6px;"><b>{client-password}</b></i> Client\'s Password</li>' 49027 + '</ul>' 49028 + '</div>' 49029 + '<div style="margin-left: -32px; margin-top: 20px; margin-bottom: 24px;"> <i style="padding-right: 8px;">Have More Questions?</i> <a href="/contact">Contact Us</a></div>' 49030 + '</div>' 49031 + '</div>'); 49032 var oj = new GLO.Popup.Info(htm); 49033 49034 if (GLO.Info.isMobile()) { 49035 oj.getPopup().find('.msg').css({ "padding-right": "4px" }); 49036 } 49037 49038 return oj 49039 } 49040 49041 _conMMAuto.openEdit = function(element) { 49042 GLO.Popup.close( $('#pop-help-followup').closest('.glopop') ); 49043 49044 if (!GLO.Info.isRequireGold()) { 49045 return false; 49046 } 49047 49048 _initGrid(); 49049 49050 if (element) { 49051 var tr = $(element).closest('tr'); 49052 var id = tr.attr('message_auto_marketing_id'); 49053 } else { 49054 var tr = null; 49055 } 49056 49057 var jpop = $('#auto-marketing-edit'); 49058 49059 if (!GLO.Info.isMobile(true) && innerHeight > 720) { 49060 jpop.addClass('tall-auto-marketing-edit'); 49061 } 49062 49063 jpop = new GLO.Popup.Custom(jpop, GLO.Message.Marketing.Auto.save).getPopup(); 49064 jpop.find('.pop-buttons').remove(); 49065 49066 jpop.find('input, select, textarea').keyup( function() { 49067 $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" }); 49068 }); 49069 49070 if (tr !== null) { 49071 jpop.find('h1').attr('message_auto_marketing_id', id); 49072 jpop.find('#Days_After_sr').val(tr.attr('days_after_sr')); 49073 49074 var svc = tr.attr('service_id'); 49075 var sg = tr.attr('service_group_id'); 49076 49077 if (UTIL.isEmpty(svc) && !UTIL.isEmpty(sg)) { svc = 'sg' + sg; } 49078 49079 var img = tr.attr('banner_image_vc'); 49080 var msg = tr.find('.message').text(); 49081 49082 var subject = tr.find('.auto-subject'); 49083 subject = UTIL.coalesce(subject.attr('title'), subject.text()); 49084 49085 var jsvc = jpop.find('#auto-marketing-edit-service').val(svc); 49086 jsvc.find('[value="' + svc + '"]').removeClass('hide'); 49087 49088 jpop.find('#Subject_vc').val(subject); 49089 jpop.find('#Body_vc').val(msg); 49090 49091 if (UTIL.parseBool(tr.attr('default_subject_fl'))) { 49092 jpop.find('#Default_Subject_fl').prop('checked', true); 49093 } else { 49094 jpop.find('#Default_Subject_fl').prop('checked', false); 49095 } 49096 49097 if (UTIL.parseBool(tr.attr('default_body_fl'))) { 49098 jpop.find('#Default_Body_fl').prop('checked', true); 49099 } else { 49100 jpop.find('#Default_Body_fl').prop('checked', false); 49101 } 49102 } else { 49103 var jdefaults = $('#auto-marketing-defaults'); 49104 var subject = UTIL.coalesce(jdefaults.find('#auto-marketing-service-subject').text(), jdefaults.find('#auto-marketing-class-subject').text()); 49105 var msg = UTIL.coalesce(jdefaults.find('#auto-marketing-service-body').text(), jdefaults.find('#auto-marketing-class-body').text()); 49106 49107 jpop.find('#Subject_vc').val(subject); 49108 jpop.find('#Body_vc').val(msg); 49109 jpop.find('#Days_After_sr').val(28) 49110 } 49111 } 49112 49113 function _hasDuplicate(sgid, svcid, id) { 49114 if (UTIL.isEmpty(sgid)) { sgid = ''; } 49115 if (UTIL.isEmpty(svcid)) { svcid = ''; } 49116 49117 var trs = $('#auto-marketing-grid > tbody > tr[service_group_id="' + sgid + '"]'); 49118 49119 for (var i=0; i < trs.length; i++) { 49120 if (trs.attr('service_id') == svcid && trs.attr('message_auto_marketing_id') != id) { 49121 return true; 49122 } 49123 } 49124 49125 return false; 49126 } 49127 49128 function _hasFollowup(joption, popid) { 49129 var val = joption.val(); 49130 49131 if (val.substring(0,2) === 'sg') { 49132 var trs = $('#auto-marketing-grid > tbody > tr[service_group_id="' + val.substring(2) + '"]'); 49133 } else { 49134 var trs = $('#auto-marketing-grid > tbody > tr[service_id="' + val + '"]'); 49135 } 49136 49137 if (trs.length > 0) { 49138 var tr_id = trs.attr('message_auto_marketing_id'); 49139 49140 if (tr_id != popid) { 49141 var selectedText = $.trim(joption.text()); 49142 49143 var div1 = '<div style="margin-bottom: 8px;">', div2 = '</div>'; 49144 var msg1 = 'Followup Message for ' + selectedText + ' already exists'; 49145 var msg2 = 'Please select a different service / service group or edit the existing followup'; 49146 var h1 = 'Followup Exists for ' + selectedText; 49147 var htm = div1 + msg1 + div2 + div1 + msg2 + div2; 49148 var fnOk = function() { UI.highlight(joption.closest('select'), 1200, 4800, true); }; 49149 49150 GLO.Popup.Warning.open(htm, h1, fnOk); 49151 return true; 49152 } 49153 } 49154 49155 return false; 49156 } 49157 49158 _conMMAuto.changeService = function(element, event) { 49159 var joption = $(element).find(':selected'); 49160 var accessType = joption.attr('min_access_type'); 49161 var hasClass = UTIL.parseBool(joption.attr('has_class_fl')); 49162 return; 49163 /* 49164 var jpop = $('#auto-marketing-edit').closest('.glopop'); 49165 var id = jpop.find('h1').attr('message_auto_marketing_id'); 49166 49167 if (_hasFollowup(joption, id)) { 49168 return false; 49169 } 49170 49171 var jdefaults = $('#auto-marketing-defaults'); 49172 49173 if (hasClass) { 49174 var subject = jdefaults.find('#auto-marketing-class-subject').text(); 49175 var msg = jdefaults.find('#auto-marketing-class-body').text() 49176 } else { 49177 var subject = jdefaults.find('#auto-marketing-service-subject').text(); 49178 var msg = jdefaults.find('#auto-marketing-service-body').text(); 49179 } 49180 49181 if (jpop.find('#Default_Subject_fl').prop('checked')) { 49182 jpop.find('#Subject_vc').val(subject); 49183 } 49184 49185 if (jpop.find('#Default_Body_fl').prop('checked')) { 49186 jpop.find('#Body_vc').val(msg); 49187 } 49188 */ 49189 } 49190 49191 _conMMAuto.changeSubject = function(element, event) { 49192 $('#Default_Subject_fl').prop('checked', false); 49193 } 49194 49195 _conMMAuto.changeBody = function(element, event) { 49196 $('#Default_Body_fl').prop('checked', false); 49197 } 49198 49199 _conMMAuto.remove = function() { 49200 GLO.Popup.Confirm('Are you sure you want to delete this automatic message?', function() { GLO.Message.Marketing.Auto.removeConfirmed(); }); 49201 } 49202 49203 _conMMAuto.removeConfirmed = function() { 49204 var jpop = $('#auto-marketing-edit').closest('.glopop'); 49205 var id = jpop.find('h1').attr('message_auto_marketing_id'); 49206 49207 var url = GLO.Link.WebsiteDomain + 'message/AutoDelete'; 49208 var jsave = jpop.closest('.glopop').find('.btnDelete'); 49209 49210 GLO.UI.Form.beginProcessing(jsave); 49211
49212 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "id": id } }) 49213 .success(function(data, textStatus, jqXHR) { 49214 $('#auto-marketing-grid').find('tr[message_auto_marketing_id="' + id + '"]').remove(); 49215 _initGrid(); 49216 GLO.Popup.close(jpop); 49217 }) 49218 .error(function(jqXHR, textStatus, errorThrown) { 49219 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 49220 }); 49221 } 49222 49223 function _getShortSubject(subject) { 49224 if (GLO.Info.isMobile()) { var max = 20; } else { var max = 60; } 49225 return UTIL.maxString(subject, max, false); 49226 } 49227 49228 function _getSubjectTitle(subject, shortSubject) { 49229 var subjectTitle = ''; 49230 49231 if (shortSubject.length !== subject.length) { 49232 return subject; 49233 } else { 49234 return ''; 49235 } 49236 } 49237 49238 function _insertGridRow(data, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody) { 49239 var id = $(data).attr('id'); 49240 var shortSubject = _getShortSubject(subject); 49241 var subjectTitle = _getSubjectTitle(subject, shortSubject); 49242 49243 var tr = '<tr message_auto_marketing_id="' + id + '" days_after_sr="' + days + '" service_id="' + svc + '" service_group_id="' + sg 49244 + '" create_dt="' + new Date() + '" create_by_staff_id="' + GLO.Info.StaffId + '" banner_image_vc="' + UTIL.cleanString(img) 49245 + '" default_subject_fl="' + isDefaultSubject + '" default_body_fl="' + isDefaultBody + '">' 49246 + '<td class="auto-range">' + daysText + '</td>' 49247 + '<td class="auto-service">' + svcText + '</td>' 49248 + '<td class="auto-subject" title="' + subjectTitle + '">' + subject + '</td>' 49249 + '<td class="auto-edit">' 49250 + '<span class="btnAdd btnAction2"> <a onclick="GLO.Message.Marketing.Auto.openEdit(this)">Edit</a> </span>' 49251 + '<span class="message hide">' + msg + '</span>' 49252 + '</td>' 49253 + '</tr>'; 49254 49255 $('#auto-marketing-grid').removeClass('hide').find('> tbody').prepend(tr); 49256 } 49257 49258 function _updateGrid(data, id, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody) { 49259 if (UTIL.isEmpty(id)) { 49260 _insertGridRow(data, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody); 49261 return; 49262 } 49263 49264 var tr = $('#auto-marketing-grid > tbody').find('tr[message_auto_marketing_id="' + id + '"]'); 49265 tr.attr('update_dt', new Date()); 49266 tr.attr('days_after_sr', days); 49267 tr.attr('service_id', svc); 49268 tr.attr('service_group_id', sg); 49269 tr.attr('banner_image_vc', UTIL.cleanString(img)); 49270 49271 var shortSubject = _getShortSubject(subject); 49272 var subjectTitle = _getSubjectTitle(subject, shortSubject); 49273 49274 tr.find('.auto-range').text(daysText); 49275 tr.find('.auto-service').text(svcText); 49276 tr.find('.auto-subject').attr('title', subjectTitle).text(shortSubject); 49277 tr.find('.message').text(msg); 49278 49279 if (isDefaultSubject === undefined) { isDefaultSubject = true; } 49280 if (isDefaultBody === undefined) { isDefaultBody = true; } 49281 tr.find('#Default_Subject_fl').prop('checked', isDefaultSubject); 49282 tr.find('#Default_Body_fl').prop('checked', isDefaultBody); 49283 } 49284 49285 function _displayPreview(data) { 49286 if (GLO.Info.isMobile()) { 49287 var style = '', btnSample = SA.Resource.SendSample, h1Text = SA.Resource.Preview; 49288 var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;'; 49289 } else { 49290 var style = ' style="width: ' + parseInt(innerWidth * .9) + 'px;"', btnSample = SA.Resource.SendSample + ' (' + SA.Resource.to_me + ')', h1Text = SA.Resource.EmailPreview; 49291 var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;'; 49292 } 49293 49294 var htmlButtons = '<div id="pop-preview-message-buttons">' 49295 + '<span class="btnOk btn"><a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>' 49296 + '<span id="btnSendSample" class="btnAdd"> <a onclick="GLO.Message.Marketing.Auto.sendSample()">' + btnSample + '</a> </span>' 49297 + '</div'; 49298 49299 var uploadHtm = $('#be-message-widgets .sa-upload').outerHTML(); 49300 49301 var h1 = '<h1 style="position: relative; margin-bottom: 0;">' 49302 + uploadHtm //+ '<span id="btnChangeImage" class="btnAdd"> <a onclick="GLO.Message.Bulk.changeImage()">Change Image</a> </span>' 49303 + '<span style="' + h1style + '">
49303' + h1Text + '</span>' 49304 + '</h1>'; 49305 49306 var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>'); 49307 GLO.Mobile.formatExternalLinksForIos(jhtm); 49308 var jpop = new GLO.Popup.Custom(jhtm).getPopup().addClass('no-persist').css({ "top": "10px" }); 49309 49310 jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons); 49311 jpop.find('.msg').css({ "max-width": "900px" }); 49312 49313 var h1 = jpop.find('h1'); 49314 h1.find('form').css({ "float": "left" }); 49315 h1.find('input'); 49316 49317 SA.Uploader.init(jpop, GLO.Message.Marketing.Auto.imageUploadComplete); 49318 49319 if (!GLO.Info.isMobile()) { 49320 var jscroll = jpop.find('.msg'); 49321 jscroll.width(jscroll.width() + 12); 49322 } 49323 } 49324 49325 _conMMAuto.imageUploadComplete = function(jupload, fileName, imgId, imgSize) { 49326 var jbanner = $('#pop-preview-message .banner img'); 49327 jbanner.attr('src', GLO.Data.cdnDirectory + 'upload-folder/' + fileName); 49328 } 49329 49330 _conMMAuto.sendSample = function() { 49331 if (!GLO.Message.Bulk.canSendSample()) { return; } 49332 49333 var j = $('#auto-marketing-edit').closest('.glopop'); 49334 var sg = '', svc = j.find('#auto-marketing-edit-service').val(); 49335 49336 if (svc.indexOf('sg') !== -1) { sg = svc.substring(2); svc = ''; } 49337 49338 var jd = { "service_group_id": sg, "service_id": svc }; 49339 var url = GLO.Link.WebsiteDomain + 'message/AutoSendSample'; 49340 var jbtn = $('.glopop #btnSendSample'); 49341 49342 GLO.UI.Form.beginProcessing(jbtn); 49343 49344 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 49345 .success(function(data, textStatus, jqXHR) { 49346 GLO.UI.Form.resetProcessing(); 49347 new GLO.Popup.Info(SA.Resource.SendSampleSent); 49348 }) 49349 .error(function(jqXHR, textStatus, errorThrown) { 49350 GLO.UI.Form.resetProcessing(); 49351 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 49352 }); 49353 } 49354 49355 _conMMAuto.preview = function() { 49356 _conMMAuto.save(true); 49357 } 49358 49359 _conMMAuto.save = function(isPreview) { 49360 var j = $('#auto-marketing-edit').closest('.glopop'); 49361 var days = j.find('#Days_After_sr').val(); 49362 var daysText = j.find('#Days_After_sr :selected').text(); 49363 var id = j.find('h1').attr('message_auto_marketing_id'); 49364 var existingFollowupCount = $('#auto-marketing-grid > tbody > tr').length; 49365 49366 var jsvc = j.find('#auto-marketing-edit-service'); 49367 var sg = '', svc = jsvc.val(), joption = jsvc.find(':selected'); 49368 var svcText = $.trim(j.find('#auto-marketing-edit-service :selected').text()); 49369 49370 if (existingFollowupCount > 0) { 49371 if ((svc === '' && _hasDuplicate('', '', id)) || svc == 'no') { 49372 var msgWarn = '<div style="text-align: left;">' 49373 + '<div>Only one automatic follow-up message can be sent per service</div>' 49374 + '<div style="margin-top: 8px;">Please select the service (or service group) for this follow-up message</div>' 49375 + '</div>'; 49376 49377 GLO.Popup.Warning.open(msgWarn, SA.Resource.PleaseSelectService, function() { $('#auto-marketing-edit-service').focus(); }); 49378 return; 49379 } else if (svc !== '' && _hasFollowup(joption, id)) { 49380 return false; 49381 } 49382 } 49383 49384 var msg = j.find('#Body_vc').val(); 49385 var subject = j.find('#Subject_vc').val(); 49386 49387 if (svc.indexOf('sg') !== -1) { sg = svc.substring(2); svc = ''; } 49388 49389 var url = GLO.Link.WebsiteDomain + 'message/AutoEdit'; 49390 var jsave = j.closest('.glopop').find('.btnSave'); 49391 49392 var jd = { "service_group_id": sg, "service_id": svc, "days_after_sr": days, "subject_vc": subject, "message_vcm": msg }; 49393 49394 if (j.find('#Default_Subject_fl').prop('checked')) { jd.default_subject_fl = 1; } else { jd.default_subject_fl = 0; } 49395 if (j.find('#Default_Body_fl').prop('checked')) { jd.default_body_fl = 1; } else { jd.default_body_fl = 0; } 49396 49397 if (isPreview) { jd.preview_fl = true; } 49398 //if (isSendSample) { jd.send_sample_fl = true; } 49399 if (!UTIL.isEmpty(id)) { jd.message_auto_marketing_id = id; } 49400 49401 GLO.UI.Form.beginProcessing(jsave); 49402
49403 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 49404 .success(function(data, textStatus, jqXHR) { 49405 var jdata = $(data); 49406 49407 if (!UTIL.isEmpty(jdata.attr('warning'))) { 49408 GLO.Popup.Warning.open(jdata.outerHTML(), 'Unable to Save'); 49409 return; 49410 } 49411 49412 _updateGrid(data, id, days, daysText, sg, svc, svcText, subject, msg, null, jd.default_subject_fl, jd.default_body_fl); 49413 _initGrid(); 49414 49415 if (isPreview) { 49416 GLO.UI.Form.resetProcessing(); 49417 _displayPreview(data); 49418 } else { 49419 GLO.Popup.close(j); 49420 } 49421 }) 49422 .error(function(jqXHR, textStatus, errorThrown) { 49423 GLO.UI.Form.resetProcessing(); 49424 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 49425 }); 49426 } 49427 49428 return _conMMAuto; 49429})(); 49430 49431GLO.Image = (function() { 49432 function _constructor() { } 49433 49434 var repressClick = false; 49435 _constructor.current; 49436 49437 _constructor.init = function() { 49438 if (GLO.Info.isIPad) { //= <img onload=''> --> does NOT reliably fire on the iPad. 49439 GLO.Image.resizeLargeImage(); 49440 } 49441 } 49442 49443 _constructor.initTouch = function() { 49444 var j = $('#frmEditImg'); 49445 49446 if (j.length > 0) { 49447 var jbtns = j.find('.cancelButton, .btnSave > a, .btnDelete > a'); 49448 } else { 49449 var j = $('#frmPhotoEditor'); 49450 var jbtns = j.find('.btnCancel > a, .btnSave > a'); 49451 } 49452 49453 _changeOnClickToOnTouchStart(jbtns); 49454 49455 if (GLO.Info.isMobile(true)) { 49456 $('#hd-parent').remove(); 49457 } 49458 49459 if (j.find('#noImage').length > 0) { 49460 j.find('#btnDelete').remove(); 49461 $('#buttonRow').css({ "margin-top": "120px" }); 49462 49463 j.find('#buttonRow .left').addClass('center'); 49464 } else if (GLO.Info.isMobile()) { 49465 j.find('#buttonRow .btnDelete').css({ "position": "relative", "display": "block", "right": "inherit", "margin": "auto" }); 49466 } 49467 } 49468 49469 function _changeOnClickToOnTouchStart(jbtns) { 49470 return; 49471 /* 49472 if (!GLO.Info.isMobile(true)) { return; } 49473 49474 for (var i=0; i < jbtns.length; i++) { 49475 var fn = jbtns.eq(i).attr('onclick'); 49476 jbtns.eq(i).removeAttr('onclick') 49477 jbtns.eq(i).attr('ontouchstart', fn); 49478 } 49479 */ 49480 } 49481 49482 _constructor.gotoUrl = function(element, url) { 49483 var jbtn = $(element).parent(); 49484 GLO.UI.Form.beginProcessing(jbtn); 49485 49486 if (url.indexOf('http') !== 0) { url = GLO.Info.http + document.location.host + url; } 49487 49488 setTimeout(function() { document.location = url }, 100); 49489 } 49490 49491 _constructor.resizeLargeImage = function() { 49492 return; 49493 /* 49494 var max = 760; 49495 var img = $('#photoEdit-main img')[0]; 49496 49497 if (IMAGE_WIDTH_SCALE !== null) { 49498 if (img.width < max) { return; } 49499 49500 IMAGE_WIDTH_SCALE = (img.width * IMAGE_WIDTH_SCALE)/max 49501 var iwidth = max; 49502 } else { 49503 var iwidth = img.width; 49504 } 49505 49506 if ((iwidth / max) > 1) { 49507 IMAGE_WIDTH_SCALE = iwidth / max; //parseInt(img.width / max); 49508 } else { 49509 IMAGE_WIDTH_SCALE = 1; 49510 } 49511 49512 iwidth /= IMAGE_WIDTH_SCALE; 49513 img.onload = null; 49514 49515 if ($('#doc3').width() > max) { 49516 $('#doc3').width(max + 50); 49517 } 49518 49519 //alert('GLO.Image: iwidth = ' + iwidth + '; IMAGE_WIDTH_SCALE = ' + IMAGE_WIDTH_SCALE + '; max = ' + max); 49520 */ 49521 } 49522 49523 _constructor.close = function() { 49524 if (window.opener) { window.opener.location.reload(); } 49525 window.close(); 49526 } 49527 49528 _constructor.setSelection = function(jcropAPI) { 49529 var rw = $('#ResizeWidth').val(); 49530 var rh = $('#ResizeHeight').val(); 49531 var dim = jcropAPI.getBounds(); 49532 49533 if (UTIL.isNumber(rw) && UTIL.isNumber(rh)) { 49534 rw = parseInt(rw); 49535 rh = parseInt(rh); 49536 49537 if (rw > dim[0] || rh > dim[1]) { 49538 jcropAPI.setSelect(getRandomSelection(dim)); 49539 } else { 49540 jcropAPI.setSelect([0, 0, rw, rh]); 49541 } 49542 } else { 49543 jcropAPI.setSelect(getRandomSelection(dim)); 49544 } 49545 } 49546 49547 function getRandomSelection(dim) { 49548 //var dim = jcropAPI.getBounds(); 49549 49550 return [ 49551 Math.round(Math.random() * dim[0]), 49552 Math.round(Math.random() * dim[1]), 49553 Math.round(Math.random() * dim[0]), 49554 Math.round(Math.random() * dim[1]) 49555 ]; 49556 } 49557 49558 _constructor.gotoTemplateHome = function() { 49559 document.location = GLO.Link.WebsiteDomain + $('#Uri_Key_vc').val() + '/home/edit'; 49560 } 49561 49562 _constructor.uploadComplete = function(imgName) { 49563 var frm = $('form#OrganizePhotoForm'); 49564 49565 if (frm.length === 1) { 49566 frm.find('#Image_Uri_vc').val(imgName); 49567 frm.submit(); 49568 } else { 49569 $('#Image_Path_vc').val(imgName); 49570 $('form#file_upload, #btnDelete').remove(); 49571 $('#frmEditImg').find('.jcrop-holder').remove(); 49572 GLO.UI.Form.beginProcessing($('#frmEditImg .btnSave')); 49573 49574 var jmain = $('#photoEdit-main'); 49575 var imgHtm = '<img src="' + imgName + '" style="max-width: ' + jmain.width() + 'px;">'; 49576 49577 jmain.css({ "max-width": jmain.width() + "px", "height": "auto" }); 49578 jmain.find('img:first').replaceWith(imgHtm); 49579 49580 setTimeout(function() { 49581 var frm = $('#frmEditImg'); 49582 frm.find('#dbAction').val('insert'); 49583 UTIL.DefaultText.deInit(frm); 49584 frm.attr('action', '').submit(); 49585 }, 100); 49586 } 49587 } 49588 49589 _constructor.goToEditor = function(img) { 49590 if (repressClick) { repressClick = false; return false; } 49591 //alert('goToEditor'); 49592 document.location.href = GLO.Link.Page.Provider.WebTemplate + 'photoEditor?img=' + $(this).attr('id'); 49593 } 49594 49595 _constructor.remove = function(ev, dropObj) { 49596 dropObj.helper.remove(); 49597 //alert('GLO.Image.remove()'); 49598 49599 var uri = GLO.Link.Page.Provider.WebTemplate + 'DeletePhoto'; 49600 var id = dropObj.helper.attr('id'); 49601
49602 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { Template_Home_Image_id: id } }) 49603 .success(function(data, textStatus, jqXHR) { 49604 //alert("success:" + data + '\n\ndivID = ' + jDiv.html()); 49605 }) 49606 .error(function(jqXHR, textStatus, errorThrown) { 49607 //alert("error: remove()\n" + textStatus); 49608 }) 49609 } 49610 49611 _constructor.removeAsk = function() { 49612 var msg = '<div id="pop-confirm-image-delete" style="letter-spacing: 1px;">' + SA.Resource.DeleteImageConfirm + '?</div>'; 49613 GLO.Popup.Confirm(msg, GLO.Image.removeConfirmed); 49614 49615 if (GLO.Info.isMobile(true)) { 49616 var jpop = $('.pop-confirm.glopop'); 49617 49618 setTimeout(function() { 49619 var btnClose = jpop.find('a.modalClose, .btnNo > a'); 49620 49621 for (var i=0; i < btnClose.length; i++) { 49622 btnClose.eq(i).removeAttr('onclick'); 49623 btnClose.eq(i).attr('ontouchstart', 'GLO.Popup.close()'); 49624 } 49625 49626 jpop.find('.btnYes > a').attr('ontouchstart', 'GLO.Image.removeConfirmed()').removeAttr('onclick'); 49627 }, 400); 49628 } 49629 } 49630 49631 _constructor.removeConfirmed = function() { 49632 $('#Image_Path_vc').val(''); 49633 49634 var frm = $('#frmEditImg'); 49635 frm.find('#dbAction').val('delete'); 49636 //UTIL.DefaultText.deInit(frm); 49637 49638 var jbtn = $('#frmEditImg').find('.btnDelete'); 49639 var path = document.location.pathname.toLowerCase(); 49640 49641 GLO.UI.Form.beginProcessing(jbtn); 49642 GLO.UI.Form.beginProcessing( $('#pop-confirm-image-delete').closest('.glopop').find('.btnYes') ); 49643 49644 if ((path === '/provider/aboutphoto/' || path === '/provider/emailimage') && UTIL.isEmpty(GLO.Uri.query('staff'))) { 49645 if (path === '/provider/emailimage') { 49646 var url = GLO.Link.Object.Provider.Ajax + 'RemoveEmailBannerImage'; 49647 } else { 49648 var url = GLO.Link.Object.Provider.Ajax + 'RemoveAboutImage'; 49649 } 49650 49651 $.ajax({ "type": "POST", "url": url, "cache": false }) 49652 .success(function(data, textStatus, jqXHR) { 49653 GLO.Popup.Success.open('Image Deleted'); 49654 49655 setTimeout(function() { 49656 location.reload(); //GLO.UI.Form.resetProcessing(jbtn); 49657 }, 150); 49658 }).error(function(jqXHR, textStatus, errorThrown) { 49659 GLO.UI.Form.resetProcessing(jbtn); 49660 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 49661 }); 49662 } else { 49663 var jqxhr = $.ajax({ type: "POST", url: document.location.href, "cache": false, data: frm.serialize() }) 49664 .success(function(data, textStatus, jqXHR) { 49665 GLO.Popup.Success.open('Image Deleted'); 49666 49667 setTimeout(function() { 49668 var backUrl = GLO.Uri.query('back'); 49669 49670 if (!UTIL.isEmpty(backUrl)) { 49671 document.location = GLO.Info.http + document.location.host + backUrl; 49672 } else if (path.startsWith('/provider/giftcardimage')) { 49673 document.location.href = document.location.origin + '/' + GLO.Data.provider.urikey + '/GiftCard?IsEdit=1'; 49674 } else { 49675 document.location.href = document.location.origin + '/wizard/website'; 49676 } 49677 }, 150); 49678 }) 49679 .error(function(jqXHR, textStatus, errorThrown) { 49680 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 49681 }); 49682 49683 //frm.attr('action', '').submit(); 49684 } 49685 } 49686 49687 _constructor.updateSortOrder = function(ev, dropObj) { 49688 repressClick = true; 49689 49690 var id = dropObj.item.attr('id'); 49691 var old_sort_sr = parseInt(dropObj.item.attr('order_sr')); 49692 49693 if (dropObj.item.prev().length > 0) { 49694 var new_sort_sr = UTIL.coalesceInt(dropObj.item.prev().attr('order_sr')) + 1; 49695 } else if (dropObj.item.next().length > 0) { 49696 var new_sort_sr = UTIL.coalesceInt(dropObj.item.next().attr('order_sr')) - 1; 49697 if (new_sort_sr < 0) { new_sort_sr = 0; } 49698 } else { 49699 return; //= drop in trash-bin 49700 } 49701
49702 if ( UTIL.isEmpty(new_sort_sr) || new_sort_sr == old_sort_sr ) { return; } 49703 49704 var imgid, new_sort_sr, row, xml = ''; 49705 var imgList = $('#sortable li'); 49706 49707 for (var i=0; i < imgList.length; i++) { 49708 imgid = imgList.eq(i).attr('id'); 49709 imgList.eq(i).attr('order_sr', (i + 1)); 49710 49711 xml += '<li image_id="' + imgid + '" order_sr="' + (i + 1) + '"/>'; 49712 } 49713 49714 var uri = GLO.Link.Page.Provider.WebTemplate + 'ReOrderPhotos'; 49715 var ol = UTIL.htmlEncode('<ol>' + xml + '</ol>'); //var jd = { Template_Home_Image_id: id, Old_Order_sr: old_sort_sr, New_Order_sr: new_sort_sr }; 49716 49717 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": ol } }) 49718 .success(function(data, textStatus, jqXHR) { 49719 //alert("success:" + data + '\n\ndivID = ' + jDiv.html()); 49720 }) 49721 .error(function(jqXHR, textStatus, errorThrown) { 49722 //alert("error: updateSortOrder()\n" + textStatus); 49723 var abc = 123; 49724 }); 49725 } 49726 49727 return _constructor; 49728})(); 49729 49730 49731GLO.Image.Crop = (function() { 49732 function _conCrop() { } 49733 49734 _conCrop.current; 49735 _conCrop.jcrop_api; _conCrop.boundx; _conCrop.boundy; // Create variables (in this scope) to hold the API and image size 49736 49737 _conCrop.init = function(aspectRatio, target) { 49738 //_initPageWidth(); 49739 49740 if (target === undefined) { target = $('#target'); } 49741 if (target.length === 0) { target = $('#crop-image'); } 49742 49743 target.Jcrop({ 49744 onChange: GLO.Image.Crop.updatePreview, onSelect: GLO.Image.Crop.updatePreview, 49745 allowResize: true, allowSelect: true, 49746 aspectRatio: aspectRatio, 49747 bgFade: true, bgOpacity: .3, //outerImage: '/_framework/ref-design/jCrop/demos/demo_files/sagomod.jpg', 49748 setSelect: [0, 0, 700, 420] //the home page's Slicebox image rotator --> width: 700px; height: 420px; 49749 }, function() { 49750 var bounds = this.getBounds(); // Use the API to get the real image size 49751 _conCrop.boundx = bounds[0]; 49752 _conCrop.boundy = bounds[1]; 49753 49754 _conCrop.jcrop_api = this; // Store the API in the jcrop_api variable 49755 49756 if (aspectRatio === 0) { 49757 var aRatio = $('#AspectRatio').val(); //Set aspect ratio 49758 if (UTIL.isNumber(aRatio)) { 49759 aRatio = parseFloat(aRatio); 49760 //alert('aRatio = ' + aRatio); 49761 //jcrop_api.setOptions( { aspectRatio: 2/5 } ); 49762 _conCrop.jcrop_api.setOptions( { aspectRatio: aRatio } ); 49763 } 49764 49765 GLO.Image.setSelection(_conCrop.jcrop_api); 49766 //_initPageWidth(); 49767 } else { 49768 //_initPageWidth2(); 49769 } 49770 49771 UI.setAccessKey(document, null, GLO.Image.Crop.save); 49772 } 49773 ); 49774 } 49775 49776 function _initPageWidthMobile() { 49777 $('#doc3').css({ "width": "98%" }); 49778 //$('#photoEdit-main').css('margin-left', marginLeft + 'px'); 49779 } 49780 49781 function _initPageWidth() { 49782 if (GLO.Info.isMobile()) { 49783 //_initPageWidthMobile(); 49784 return; 49785 } 49786 49787 var tmpWidth = $('#target').css('width'); 49788 if (UTIL.isEmpty(tmpWidth)) { tmpWidth = $('#crop-image').css('width'); } 49789 49790 if (tmpWidth) { 49791 tmpWidth = parseInt(tmpWidth.replace('px', '')) + 60; //set the width of #doc3 49792 49793 if (tmpWidth < 750) { 49794 tmpWidth = 750; 49795 } else if (GLO.Info.isIPad && tmpWidth > 760) { 49796 tmpWidth = 760; 49797 } 49798 49799 $('#doc3').css('width', tmpWidth + 'px'); 49800 } 49801 } 49802 49803 function _initPageWidth2() { 49804 if (GLO.Info.isMobile()) { 49805 _initPageWidthMobile(); 49806 return; 49807 } 49808 49809 var marginLeft = 20; 49810 var tmpWidth = parseInt($('#target').css('width').replace('px', '')); 49811 if (UTIL.isEmpty(tmpWidth)) { parseInt($('#target').css('width').replace('px', '')); } 49812 49813 if (tmpWidth < 750) { 49814 marginLeft = parseInt((750 - 25 - tmpWidth) / 2); 49815 //alert('tmpWidth = ' + tmpWidth + '; marginLeft = ' + marginLeft); 49816 tmpWidth = 750; 49817 } else { 49818 //alert('tmpWidth = ' + tmpWidth); 49819 tmpWidth += 50; 49820 } 49821 49822 $('#doc3').css('width', tmpWidth + 'px'); 49823 $('#photoEdit-main').css('margin-left', marginLeft + 'px'); 49824 } 49825 49826 _conCrop.updatePreview = function(c) { 49827 _conCrop.current = c; 49828 49829 if (parseInt(c.w) > 0) { 49830 var rx = 100 / c.w; 49831 var ry = 100 / c.h; 49832 49833 $('#preview').css({ 49834 width: Math.round(rx * _conCrop.boundx) + 'px', 49835 height: Math.round(ry * _conCrop.boundy) + 'px', 49836 marginLeft: '-' + Math.round(rx * c.x) + 'px', 49837 marginTop: '-' + Math.round(ry * c.y) + 'px' 49838 }); 49839 } 49840 } 49841 49842 _conCrop.save = function() { 49843 $('#x').val(parseInt(_conCrop.current.x * IMAGE_WIDTH_SCALE)); 49844 $('#y').val(parseInt(_conCrop.current.y * IMAGE_WIDTH_SCALE)); 49845 $('#width').val(parseInt(_conCrop.current.w * IMAGE_WIDTH_SCALE)); 49846 $('#height').val(parseInt(_conCrop.current.h * IMAGE_WIDTH_SCALE)); 49847 49848 var frm = $('#frmEditImg, #frmPhotoEditor'); 49849 frm.find('#dbAction').val('update'); 49850 49851 UTIL.DefaultText.deInit(frm); 49852 GLO.UI.Form.beginProcessing(frm.find('.btnSave:visible'));
49853 49854 //alert('GLO.Image.Crop.save(), _conCrop.current .x/.y + width/height = ' + _conCrop.current.x + ' / ' + _conCrop.current.y + ' + ' + _conCrop.current.w + ' / ' + _conCrop.current.h); 49855 window.setTimeout(function() { frm.attr('action', '').submit(); }, 200); 49856 } 49857 49858 _conCrop.rotate = function(element, fnSave) { 49859 var degrees = 90; 49860 var img = $('.jcrop-holder:visible img:last'); 49861 49862 if (img.length === 0) { 49863 img = $('img#crop-preview'); 49864 if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.save; } 49865 } 49866 49867 SA.Uploader.Crop.rotate(img[0], degrees); 49868 } 49869 49870 _conCrop.preview = function(element, fnSave) { 49871 var img = $('.jcrop-holder:visible img:last'); 49872 49873 if (img.length === 0) { 49874 img = $('img#crop-preview'); 49875 if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.save; } 49876 } 49877 49878 var xOld = 0, yOld = 0; 49879 var wOld = img.width(); 49880 var hOld = img.height(); 49881 49882 if (!_isValidImage()) { return; } 49883 49884 var xNew = parseInt(_conCrop.current.x * IMAGE_WIDTH_SCALE); 49885 var yNew = parseInt(_conCrop.current.y * IMAGE_WIDTH_SCALE); 49886 var wNew = parseInt(_conCrop.current.w * IMAGE_WIDTH_SCALE); 49887 var hNew = parseInt(_conCrop.current.h * IMAGE_WIDTH_SCALE); 49888 49889 //alert('GLO.Image.Crop.save(), _conCrop.current .x/.y + width/height = ' + _conCrop.current.x + ' / ' + _conCrop.current.y + ' + ' + _conCrop.current.w + ' / ' + _conCrop.current.h); 49890 //fnSave(xOld, yOld, wOld, hOld, xNew, yNew, wNew, hNew); 49891 49892 if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.preview; } 49893 49894 fnSave(img[0], xNew, yNew, wNew, hNew); 49895 } 49896 49897 function _isValidImage() { 49898 if (_conCrop.current !== undefined && _conCrop.current.w > 0 && _conCrop.current.h > 0) { return true; } 49899 if (GLO.Info.isMobile(true)) { 49900 var click = 'Please touch the image and drag your finger to select the section of the image you would like'; 49901 } else { 49902 var click = 'Please click the image and drag your mouse to select the section of the image you would like'; 49903 } 49904 49905 var h1 = '<h1 class="friendly-msg2">Select Section of Image to Crop</h1>'; 49906 var msg = '<div class="friendly-msg4" style="max-width: 520px;">' + click + '</div>'; 49907 49908 new GLO.Popup.Info('<div>' + h1 + msg + '</div>'); 49909 return false; 49910 } 49911 49912 return _conCrop; 49913})(); 49914 49915 49916if (typeof GLO === 'undefined') { GLO = {}; } 49917if (GLO.Template === undefined) { GLO.Template = {}; } 49918 49919GLO.Template.CustomizeNewClientForm = (function() { 49920 function _cCustomizeNewClientForm() { } 49921 49922 _cCustomizeNewClientForm.init = function() { 49923 var jcontainer = $('#customize-form'); 49924 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 49925 49926 jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() { 49927 jcontainer.find('.btnSave > a').addClass('unsaved'); 49928 }); 49929 jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() { 49930 jcontainer.find('.btnSave > a').addClass('unsaved'); 49931 }); 49932 49933 var jtext = jcontainer.find('.sa-text-editor'); 49934 SA.TextEditor.init(jtext, 'New Client Form Message'); 49935 49936 _cCustomizeNewClientForm.changeType(); 49937 49938 if (!UTIL.isEmpty(highlight)) { 49939 var jhigh = $('#' + highlight); 49940 UI.highlight(jhigh, 100, 9500, true); 49941 } 49942 49943 _initFieldTable(jcontainer); 49944 49945 jcontainer.find('input:checkbox').on('change', GLO.Template.CustomizeNewClientForm.changeFieldBox); 49946 } 49947 function _initFieldTable(jcontainer) { 49948 _setConfigRow('new-client-full-name', GLO.Data.provider.new_client_full_name_cd); 49949 _setConfigRow('new-client-mobile-phone', GLO.Data.provider.new_client_mobile_phone_cd); 49950 _setConfigRow('new-client-opt-in', GLO.Data.provider.new_client_optin_cd); 49951 _setConfigRow('new-client-other-phone', GLO.Data.provider.new_client_other_phone_cd); 49952 _setConfigRow('new-client-email', GLO.Data.provider.new_client_email_cd); 49953 49954 _setConfigRow('new-client-zip', GLO.Data.provider.new_client_zip_cd); 49955 _setConfigRow('new-client-address', GLO.Data.provider.new_client_address_cd); 49956 49957 _setConfigRow('new-client-birthday', GLO.Data.provider.new_client_birthday_cd); 49958 _setConfigRow('new-client-refer-type', GLO.Data.provider.new_client_refer_type_cd); 49959 _setConfigRow('new-client-refer-by', GLO.Data.provider.new_client_refer_by_cd); 49960 } 49961 function _setConfigRow(rowId, value) { 49962 var tr = $('#customize-form-display-fields').find('tbody > tr#' + rowId); 49963 49964 if (value == 0 || value == 99) { 49965 tr.find('.new-client-form-hide :checkbox').prop('checked', true); 49966 } 49967 49968 if (value == 10 || value == 19 || value == 26) { 49969 tr.find('.new-client-form-display-staff :checkbox').prop('checked', true); 49970 } 49971 if (value == 15 || value == 19 || value == 21) { 49972 tr.find('.new-client-form-display-client :checkbox').prop('checked', true); 49973 } 49974 49975 if (value == 20 || value == 21 || value == 29) { 49976 tr.find('.new-client-form-require-staff :checkbox').prop('checked', true); 49977 } 49978 if (value == 25 || value == 26 || value == 29) { 49979 tr.find('.new-client-form-require-client :checkbox').prop('checked', true); 49980 } 49981 } 49982 49983 _cCustomizeNewClientForm.changeFieldBox = function() { 49984 var td = $(event.currentTarget).closest('td'); 49985 var tr = td.closest('tr'); 49986 49987 if (td.hasClass('new-client-form-hide')) { 49988 tr.find('.new-client-form-display :checkbox, .new-client-form-require :checkbox').prop('checked', false); 49989 return; 49990 49991 } else if (td.hasClass('new-client-form-display-staff')) { 49992 tr.find('.new-client-form-require-staff :checkbox').prop('checked', false); 49993 } else if (td.hasClass('new-client-form-display-client')) { 49994 tr.find('.new-client-form-require-client :checkbox').prop('checked', false); 49995 49996 } else if (td.hasClass('new-client-form-require-staff')) { 49997 tr.find('.new-client-form-display-staff :checkbox').prop('checked', false); 49998 } else if (td.hasClass('new-client-form-require-client')) { 49999 tr.find('.new-client-form-display-client :checkbox').prop('checked', false); 50000 } 50001 50002 tr.find('.new-client-form-hide :checkbox').prop('checked', false); 50003 } 50004 _cCustomizeNewClientForm.changeType = function() { 50005 var jcontainer = $('#customize-form'); 50006 var formType = jcontainer.find('#New_Client_Form_cd').val(); 50007 50008 if (formType == 0) { 50009 jcontainer.find('.customize-form-simple').addClass('hide'); 50010 jcontainer.find('.customize-form-standard').removeClass('hide'); 50011 } else { 50012 jcontainer.find('.customize-form-standard').addClass('hide'); 50013 jcontainer.find('.customize-form-simple').removeClass('hide'); 50014 } 50015 } 50016 50017 _cCustomizeNewClientForm.helpReferType = function() { 50018 var header = 'Referral Type'; 50019 var fnNote = 'GLO.Uri.gotoUri2(\'help?helloback=advanced&tabback=help#tab=appointment&id=calendar-appt-add-note\')'; 50020 var bNote = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnNote + '">Appointment Staff Note popup</a>'; 50021 50022 var bReferType = '<b class="narrow-text">Referral Type</b>'; 50023 var bForm = '<b class="narrow-text">New Client Form</b>'; 50024 50025 var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')'; 50026 var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>' 50027 50028 var fnTicketHistory = 'GLO.Uri.gotoUri2(\'reports/TicketHistory?highlight=group-by-column\')'; 50029 var bTicketHistory = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnTicketHistory + '">Ticket History <small>report</small></a>' 50030 50031 var msg1 = '<p>Can use ' + bReferType + ' to view reports of how new clients are finding you</p>'; 50032 var msg2 = '<p>When ' + bReferType + ' is displayed to staff on the ' + bForm + ', then it is also dis
50032played on the' + bNote + '</p>'; 50033 var msg3 = '<p>Can filter the ' + bClientList + ' + ' + bTicketHistory + ' by ' + bReferType + '</p>'; 50034 50035 var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>'; 50036 GLO.Popup.Info.openSimple(htm, header); 50037 } 50038 _cCustomizeNewClientForm.helpZip = function() { 50039 var header = 'Zip Code'; 50040 var fnNote = 'GLO.Uri.gotoUri2(\'help?helloback=advanced&tabback=help#tab=appointment&id=calendar-appt-add-note\')'; 50041 var bNote = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnNote + '">Appointment Staff Note popup</a>'; 50042 50043 if (GLO.Data.provider.country == 'CA') { 50044 header = 'Post Code'; 50045 } 50046 50047 var bZip = '<b class="narrow-text">' + header + '</b>'; 50048 var bForm = '<b class="narrow-text">New Client Form</b>'; 50049 50050 var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')'; 50051 var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>' 50052 50053 var fnTicketHistory = 'GLO.Uri.gotoUri2(\'reports/TicketHistory?highlight=group-by-column\')'; 50054 var bTicketHistory = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnTicketHistory + '">Ticket History <small>report</small></a>' 50055 50056 var msg1 = '<p>Can use ' + bZip + ' to view reports of where clients are coming from</p>'; 50057 var msg2 = '<p>When ' + bZip + ' is displayed to staff on the ' + bForm + ', then it is also displayed on the' + bNote + '</p>'; 50058 var msg3 = '<p>Can filter the ' + bClientList + ' + ' + bTicketHistory + ' by ' + bZip + '</p>'; 50059 50060 var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>'; 50061 GLO.Popup.Info.openSimple(htm, header); 50062 } 50063 _cCustomizeNewClientForm.helpBirthday = function() { 50064 var header = 'Birthday'; 50065 50066 var fnCommunicate = 'GLO.Uri.gotoUri2(\'message/Birthday\')'; 50067 var bCommunicate = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnCommunicate + '">Happy Birthday Emails</a>'; 50068 50069 var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')'; 50070 var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>' 50071 50072 var bBirthday = '<b class="narrow-text">Birthday</b>'; 50073 var bForm = '<b class="narrow-text">New Client Form</b>'; 50074 var bArrow = '<b class="html-arrow"></b>'; 50075 50076 var msg1 = '<p>Can use ' + bBirthday + ' as a marketing feature to run birthday discounts and send ' + bCommunicate + '</p>'; 50077 var msg2 = '<p>Can require birthday when have age restricted services, classes, or events ' + bBirthday + ' ' + bArrow + ' this will require clients enter birthday day, month, and year</p>'; 50078 var msg3 = '<p>Can filter the ' + bClientList + ' by ' + bBirthday + '</p>'; 50079 50080 var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>'; 50081 GLO.Popup.Info.openSimple(htm, header); 50082 } 50083 _cCustomizeNewClientForm.helpEmail = function() { 50084 var header = 'Automatic Login Link'; 50085 var fnCommunicate = 'GLO.Uri.gotoUri2(\'provider/manage/message?highlight=email-to-client-list\')'; 50086 var bCommunicate = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnCommunicate + '">free ways you can communicate with clients</a>'; 50087 50088 var bEmail = '<b class="narrow-text">Email</b>'; 50089 var bForm = '<b class="narrow-text">New Client Form</b>'; 50090 50091 var msg1 = '<p>By default, ' + bEmail + ' is required on the ' + bForm + ' filled out by clients + optional when filled out by staff</p>'; 50092 var msg2 = '<p>We recommend using the default settings because of all the ' + bCommunicate + ' by ' + bEmail + '</p>'; 50093 50094 var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + '</div>'; 50095 GLO.Popup.Info.openSimple(htm, header); 50096 } 50097 _cCustomizeNewClientForm.helpAutoLoginLink = function() { 50098 var header = 'Automatic Login Link'; 50099 var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&popup=how-to-guide-online-booking&step=15\')'; 50100 var blink = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnAutoLink + '">Automatic Login Link</a>'; 50101 50102 var msg1 = '<p>' + blink + ' sent to client is a unique link specific to that client'; 50103 var msg2 = '<p>Client can simply click ' + blink + ' to automatically login <i class="narrow-text">(without needing to enter a Username or Password)</i></p>'; 50104 50105 var htm = '<div id="pop-info-auto-login-link">' + msg1 + msg2 + '</div>'; 50106 GLO.Popup.Info.openSimple(htm, header); 50107 } 50108 _cCustomizeNewClientForm.helpOptin = function() { 50109 var iconMkt = '<span class="be-unsubscribe-text" onclick="GLO.UI.openHelp(this)" header="Blocked Text Marketing Messages" title="Client unsubscribed from marketing text messages">' 50110 + '<img src="http://www.testcdn.com/image/icon/commons-emblem/hand-orange-icon-large.png">' 50111 + '</span>'; 50112 50113 var iconAppt = '<span class="be-unsubscribe-text-appt" onclick="GLO.UI.openHelp(this)" header="Blocked Text Appointment Messages" title="Client unsubscribed from appointment text messages like confirmations, reminders, and follow-ups">' 50114 + '<img src="http://www.testcdn.com/image/icon/knob/RemoveRed.png" style="margin-left: 4px; margin-bottom: 2px; cursor: pointer;">' 50115 + '</span>'; 50116 50117 var msg1 = '<p>By default clients are opted-in to text reminders and text marketing</p>'; 50118 var msg2 = '<p style="margin: 20px 0;">When a client unchecks the opt-in box, only the client can re-check it ' 50119 + '<span class="narrow-text">(i.e. if a client opts-out, a staff member cannot opt-in the client | only the client can do that)</span></p>'; 50120 var msg3 = '<p>You can tell if the client opted out of text messages if you see either of these icons on their profile ' + iconMkt + iconAppt + '</p>'; 50121 50122 var htm = '<div id="pop-info-text-optin">' + msg1 + msg2 + msg3 + '</div>'; 50123 var ojpop = GLO.Popup.Info.openSimple(htm, 'Text Message Opt-In', null, true); 50124 } 50125 _cCustomizeNewClientForm.helpCompleteLogin = function() { 50126 var arrow = '<span class="arrow-right">➜
50126</span>'; 50127 var EasyLogin = '<b class="narrow-text">Easy Login</b>'; 50128 50129 var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&popup=how-to-guide-online-booking&step=15\')'; 50130 var aAutoLink = '<a class="narrow-text" onclick="' + fnAutoLink + '" style="font-weight: bold; color: #139ad2;">Automatic Login Link</a>'; 50131 50132 var msg1 = '<p>If a client tries to create a duplicate account (using the same email or phone number)</p>'; 50133 50134 var list1 = '<li>For clients that have never logged in ' + arrow + ' client automatically logged into existing profile</li>'; 50135 var list2 = '<li>When ' + EasyLogin + ' is enabled ' + arrow + ' client automatically logged into existing profile</li>'; 50136 var list3 = '<li>Otherwise client sees message to check their email to complete login ' + arrow + ' client immediately sent email with ' + aAutoLink + '</li>'; 50137 var msg2 = '<ul>' + list1 + list2 + list3 + '</ul>'; 50138 50139 var img = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/client/new-client/client-signup-check-email.png" style="max-width: 480px;"/></div>'; 50140 var msg3 = '<p style="margin-bottom: 24px;">Client can simply click the ' + aAutoLink + ' in the email to login</p>'; 50141 50142 var awesomeList = '<ul class="checkmark-list">' 50143 + '<li>Avoid Duplicate Client Profiles' + arrow + ' easier to manage + important for <b>Marketing!</b></li>' 50144 + '<li>Simple Login' + arrow + ' No Need for Username + Password</li>' 50145 + '</ul>'; 50146 50147 var htm = '<div id="pop-info-complete-login">' + awesomeList + msg1 + msg2 + img + msg3 + '</div>'; 50148 var ojpop = GLO.Popup.Info.openSimple(htm, 'Complete Login with Automatic Login Link', null, true); 50149 ojpop.realign(); 50150 setTimeout(ojpop.realign, 500); 50151 setTimeout(ojpop.realign, 1500); 50152 setTimeout(ojpop.realign, 2500); 50153 } 50154 _cCustomizeNewClientForm.helpFields = function() { 50155 var msg1 = '<p>You can setup what fields you want displayed/required when staff create a new client and when a client submits their inforamtion</p>'; 50156 var msg2 = '<p style="margin-bottom: 0; padding-bottom: 0;">This setup determines the fields on</p>'; 50157 50158 var web = GLO.Link.WebsiteDomain + GLO.Data.provider.urikey; 50159 var fn1 = 'SA.App.openLinkInBrowser(\'' + web + '/login/NewUser\', true)'; 50160 var fn2 = 'SA.Menu.createClient()'; 50161 var fn3 = 'SA.App.openLinkInBrowser(\'' + web + '/RequestAppt\', true)'; 50162 50163 var list1 = '<li><a onclick="' + fn1 + '">New Client Form <i class="narrow-text">(client view)</i></a></li>'; 50164 var list2 = '<li><a onclick="' + fn2 + '">New Client Form <i class="narrow-text">(staff view)</i></a></li>'; 50165 var list3 = '<li><a onclick="' + fn3 + '">Request Appointment</a></li>'; 50166 var list4 = '<li>Required fields when update <b class="narrow-text">Existing Client Profile</b> <i class="narrow-text">(both client + staff)</i></li>'; 50167 var ul = '<ul>' + list1 + list2 + list3 + list4 + '</ul>'; 50168 50169 var aQuick = '<a onclick="GLO.ClientProfile.openSimpleAdd()">Quick Add Client popup</a>'; 50170 var hasMerchant = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) < 40; 50171 50172 if (GLO.Info.isGold()) { 50173 var uriSignin = location.origin + '/' + GLO.Data.provider.urikey + '/Signin'; 50174 var aSignin = '<a onclick="SA.App.openLinkInBrowser(\'' + uriSignin + '\', true)">Client Self Sign-In Screen</a>'; 50175 50176 if (hasMerchant) { 50177 var footer = 'by new clients on your <b>buy gift card</b>, <b>buy membership</b>, + <b>shopping cart</b> web pages;' 50178 + ' it also does not affect the ' + aQuick + ' or the ' + aSignin; 50179 } else { 50180 var footer = 'using the ' + aQuick + ' or the ' + aSignin; 50181 } 50182 } else { 50183 if (hasMerchant) { 50184 var footer = 'by new clients on your buy gift card web page + ' + aQuick; 50185 } else { 50186 var footer = 'using the ' + aQuick; 50187 } 50188 } 50189 50190 footer = '<div class="help-footer">These settings do not affect how new client profiles are created ' + footer + '</div>'; 50191 50192 var htm = '<div id="pop-info-new-client-fields">' + msg1 + msg2 + ul + footer + '</div>'; 50193 var ojpop = GLO.Popup.Info.openSimple(htm, 'Client Field Setup', null, true); 50194 } 50195 50196 _cCustomizeNewClientForm.save = function() { 50197 var jcontainer = $('#customize-form'); 50198 var ftype = jcontainer.find('#New_Client_Form_cd').val(); 50199 var note = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML)); 50200 var trs = jcontainer.find('#customize-form-display-fields').find('tbody > tr'); 50201 50202 var url = GLO.Link.WebsiteDomain + 'wizard/website/CustomizeNewClientForm'; 50203 var jd = { "ftype": ftype, "note": note } 50204 50205 for (var i=0; i < trs.length; i++) { 50206 var tr = trs.eq(i); 50207 var isHide = tr.find('.new-client-form-hide :checkbox').prop('checked'); 50208 var isDisplayClient = tr.find('.new-client-form-display-client :checkbox').prop('checked') || tr.find('.new-client-form-display-client .checkmark-icon').length; 50209 var isDisplayStaff = tr.find('.new-client-form-display-staff :checkbox').prop('checked') || tr.find('.new-client-form-display-staff .checkmark-icon').length; 50210 50211 var isRequireClient = tr.find('.new-client-form-require-client :checkbox').prop('checked') || tr.find('.new-client-form-require-client .checkmark-icon').length; 50212 var isRequireStaff = tr.find('.new-client-form-require-staff :checkbox').prop('checked') || tr.find('.new-client-form-require-staff .checkmark-icon').length; 50213 50214 if (isHide) { 50215 var displayClientCode = 99; 50216 } else if (isRequireClient && isRequireStaff) { 50217 var displayClientCode = 29; 50218 50219 } else if (isRequireClient) { 50220 if (isDisplayStaff) { 50221 var displayClientCode = 26; 50222 } else { 50223 var displayClientCode = 25; 50224 } 50225 } else if (isRequireStaff) { 50226 if (isDisplayClient) { 50227 var displayClientCode = 21; 50228 } else { 50229 var displayClientCode = 20; 50230 } 50231 } else if (isDisplayClient && isDisplayStaff) { 50232 var displayClientCode = 19; 50233 } else if (isDisplayClient) { 50234 var displayClientCode = 15; 50235 } else if (isDisplayStaff) { 50236 var displayClientCode = 10; 50237 } else { 50238 var displayClientCode = 0; 50239 } 50240 50241 jd[trs.eq(i).attr('column')] = displayClientCode; 50242 } 50243 50244 var jsave = jcontainer.find('.btnSave'); 50245 GLO.UI.Form.beginProcessing(jsave); 50246
50247 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 50248 .success(function(data, textStatus, jqXHR) { 50249 GLO.Popup.Success.open('Changes Saved', 'New Client Form'); 50250 GLO.UI.Form.resetProcessing(); 50251 jcontainer.find('.btnSave .unsaved').removeClass('unsaved'); 50252 }) 50253 .error(function(jqXHR, textStatus, errorThrown) { 50254 GLO.Popup.Error.open('<div id="pop-error-customize-new-client-form"><p>Unable to Save</p></p>Please Try Again Later</p></div>', 'New Client Form'); 50255 GLO.UI.Form.resetProcessing(); 50256 }) 50257 } 50258 50259 return _cCustomizeNewClientForm; 50260})(); 50261 50262 50263SA.Admin = (function() { 50264 function _conAdmin() { } 50265 50266 _conAdmin.init = function() { 50267 _conAdmin.initSearch(); 50268 50269 UI.initTableSorter( $('#provider-config-body-table') ); 50270 UI.initTableSorter( $('#provider-config-message-table') ); 50271 UI.initTableSorter( $('#provider-config-session-table') ); 50272 UI.initTableSorter( $('#provider-config-service-group-table') ); 50273 50274 var jQueryFields = $('#sa-only-fields').find('input, select, textarea'); 50275 var saveUrl = GLO.Link.Page.Provider.Home + 'manage/ConfigNotes'; 50276 new UI.AutoSave(jQueryFields, saveUrl); 50277 } 50278 _conAdmin.initRecentlyCreatedProviders = function() { 50279 _conAdmin.initSearch(); 50280 50281 var jrpt = $('#recently-created-providers'); 50282 var tbl = jrpt.find('table.tablesorter') 50283 50284 UI.initTableSorter(tbl); 50285 GLO.Report.CellSummary.initReport(jrpt, true, true); 50286 } 50287 _conAdmin.initSearch = function() { 50288 $('#hd-parent').remove(); 50289 $('#bd').css({ "margin-top": "0" }); 50290 $('.shadow-content0').css({ "padding": "0" }); 50291 50292 var j = $('#provider-config'); 50293 var pid = j.find('h1').attr('provider_id'); //j.find('#Provider_id').val(); 50294 var urlClientLookup = GLO.Link.Object.Provider.Ajax + 'ClientAdminSearch?pid=' + pid; 50295 50296 $('#client-admin-search').autocomplete({ 50297 source: urlClientLookup, minLength: 2, 50298 select: function(event, ui) { 50299 SA.Admin.openClient(ui.item); 50300 }, 50301 open: function(){ 50302 //$(this).autocomplete('widget').css("z-index", "5900 !important"); 50303 //return false; 50304 }, 50305 }); 50306 50307 UI.initAutoComplete2($('#Staff_or_Provider_Name_vc'), GLO.Link.Object.Provider.Ajax + 'LookupProvider', SA.Admin.lookupProviderSelected); 50308 } 50309 50310 _conAdmin.lookupProviderSelected = function(event, ui) { 50311 new GLO.Popup.Processing('Loading ' + ui.item.label + '...'); 50312 50313 setTimeout(function() { 50314 document.location = document.location.protocol + '//' + location.host + '/provider/manage/config?provider=' + ui.item.id; 50315 }, 400); 50316 } 50317 50318 _conAdmin.changeProviderDD = function(element) { 50319 new GLO.Popup.Processing('Loading Provider...'); 50320 50321 setTimeout(function() { 50322 document.location = document.location.protocol + '//' + location.host + '/provider/manage/config?provider=' + element.value; 50323 }, 400); 50324 } 50325 50326 _conAdmin.openClient = function(item) { 50327 var j = $('#provider-config'); 50328 var pid = j.find('h1').attr('provider_id'); //j.find('#Provider_id').val(); 50329 50330 var url = GLO.Link.Object.Provider.Ajax + 'ClientAdminSummary?cid=' + item.id + '&pid=' + pid; 50331 50332 $.ajax({ type: "GET", url: url, "cache": false }) 50333 .success( function(data, textStatus, jqXHR) { 50334 var jdata = $(data); 50335 var jpop = new GLO.Popup.Custom(jdata).getPopup().addClass('no-persist'); 50336 50337 jpop.find('.btnSave').remove(); 50338 jpop.find('.btnCancel').css({ "float": "none", "letter-spacing": "1px" }).find('>a').text(SA.Resource.Close); 50339 }) 50340 .error( function(jqXHR, textStatus, errorThrown) { 50341 //GLO.UI.Form.resetProcessing(); 50342 }); 50343 } 50344 50345 _conAdmin.changeStaffPassword = function(element) { 50346 var tr = $(element).closest('tr').addClass('highlight'); 50347 var fnCancel = function() { 50348 $('#provider-config').find('#provider-config-body-table').find('tr.highlight').removeClass('highlight'); 50349 } 50350 50351 var jpop = new GLO.Popup.Prompt('<div id="pop-update-password">' + SA.Resource.EnterNewPassword + '</div>', SA.Admin.saveStaffPassword, fnCancel).getPopup().addClass('no-persist'); 50352 jpop.find('textarea').css({ "height": "24px", "letter-spacing": "2px" }); 50353 jpop.find('.modalClose, .btnCancel > a').click(fnCancel); 50354 } 50355 50356 _conAdmin.saveStaffPassword = function(password) { 50357 var j = $('#provider-config'); 50358 var tr = j.find('#provider-config-body-table').find('tr.highlight').removeClass('highlight').addClass('highlightPink'); 50359 var sid = tr.attr('staff_id'); 50360 var pid = j.find('h1').attr('provider_id'); //j.find('#Provider_id').val(); 50361 var url = GLO.Link.Object.Provider.Ajax + "UpdatePassword"; 50362 50363 var jpop = $('#pop-update-password').closest('.glopop'); 50364 var jbtnEnter = jpop.find('.btnYes').css({ "padding-top": "0" }); 50365 GLO.UI.Form.beginProcessing(jbtnEnter); 50366
50367 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_id": pid, "sid": sid, "password": password } }) 50368 .success(function(data, textStatus, jqXHR) { 50369 tr.removeClass('highlightPink').addClass('highlightSuccess').find('.column-password').text(password); 50370 50371 setTimeout(function() { tr.removeClass('highlightSuccess'); }, 2500); 50372 50373 GLO.Popup.close(jpop); 50374 }) 50375 .error(function(jqXHR, textStatus, errorThrown) { 50376 }) 50377 } 50378 50379 _conAdmin.changeClientPassword = function() { 50380 var jpop = new GLO.Popup.Prompt('<div id="pop-update-password">' + SA.Resource.EnterNewPassword + '</div>', SA.Admin.saveClientPassword).getPopup().addClass('no-persist'); 50381 jpop.find('textarea').css({ "height": "24px", "letter-spacing": "2px", "font-size": "larger" }); 50382 } 50383 50384 _conAdmin.saveClientPassword = function(password) { 50385 var j = $('#pop-client-admin-summary'); 50386 var cid = j.attr('client_id'); 50387 var pid = $('#provider-config').find('h1').attr('provider_id'); //j.find('#Provider_id').val(); 50388 var url = GLO.Link.Object.Provider.Ajax + "UpdatePassword"; 50389 50390 var jpop = $('#pop-update-password').closest('.glopop'); 50391 var jbtnEnter = jpop.find('.btnYes').css({ "padding-top": "0" }); 50392 GLO.UI.Form.beginProcessing(jbtnEnter); 50393 50394 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_id": pid, "cid": cid, "password": password } }) 50395 .success(function(data, textStatus, jqXHR) { 50396 j.find('#admin-client-password').text(password); 50397 50398 GLO.Popup.close(jpop); 50399 }) 50400 .error(function(jqXHR, textStatus, errorThrown) { 50401 }) 50402 } 50403 50404 return _conAdmin; 50405})(); 50406 50407 50408GLO.Sale = (function() { 50409 function _conSale() { } 50410 50411 _conSale.init = function() { 50412 50413 } 50414 50415 return _conSale; 50416})(); 50417 50418 50419GLO.Sale.Keypad = (function() { 50420 function _conKeypad() { } 50421 var _includeTax = false, _hasInit = false; 50422 var _otherXml = null; 50423 50424 _conKeypad.init = function() { 50425 var jkeyboard = $('#sale-keyboard'); 50426 50427 if (false && GLO.Info.isMobile(true)) { //DEBUG ONLY --> !UTIL.debug && 50428 jkeyboard.find('.number-keypad').find('span').on('touchstart', GLO.Sale.Keypad.clickKey); 50429 } else { 50430 jkeyboard.find('.number-keypad').find('span').click(GLO.Sale.Keypad.clickKey); 50431 } 50432 50433 _initTax(jkeyboard); 50434 var amt = GLO.Uri.query('amount'); 50435 50436 if (!UTIL.isEmpty(amt)) { 50437 amt = UTIL.displayMoney(amt, true, true); 50438 50439 for (var i = 0; i < amt.length; i++) { 50440 var jkey = jkeyboard.find('.number-keypad').find('span.keypad-' + amt.substr(i, 1)); 50441 50442 if (GLO.Info.isMobile(true)) { //DEBUG ONLY --> !UTIL.debug && 50443 jkey.trigger('touchstart'); 50444 } else { 50445 jkey.click(); 50446 } 50447 } 50448 50449 if (GLO.Uri.query('paymethod') == 10) { 50450 _conKeypad.enterCardNumber(); 50451 } else if (UTIL.parseBool(GLO.Uri.query('createinvoice'))) { 50452 _conKeypad.openTicket(); 50453 } 50454 } 50455 50456 //_initShortcutKeys(); 50457 50458 if (GLO.Info.isMobile(true)) { 50459 new FastClick(document.body); 50460 //if (GLO.Info.isIPhone && GLO.Info.isIosApp) { GLO.Mobile.iosNativeBridge.call("ActivateSwiper", []); } 50461 50462 if (GLO.Info.isMobile()) { 50463 $('#mp-initial-menu').find('.fa-map-marker').closest('li').remove(); //= remove "Create Appointment" from mobile menu because this page doesn't allow scrolling height. 50464 //$('#wait-list-icon, #wait-list-icon-fixed').remove(); 50465 } 50466 50467 _initEmvReader(jkeyboard); 50468 } 50469 } 50470 50471 function _initEmvReader(jkeyboard) { 50472 if (!UserPortal.Price.Payment.supportsEmvReader()) { return; } 50473 50474 jkeyboard.find('#btnEnterCardNumber').click(GLO.Sale.Keypad.openTicketCredit).find('>a').text('Credit Payment'); 50475 } 50476 50477 _conKeypad.openTicketCredit = function() { 50478 GLO.Sale.Keypad.openTicket(); 50479 50480 setTimeout(function() { 50481 var jPricePop = $('#appt-price-popup').closest('.glopop'); 50482 jPricePop.find('#Mobile_Payment_Method_cd').find('li[value="10"]').click(); 50483 }, 900); 50484 } 50485 50486 _conKeypad.iosActivateSwiperComplete = function(hasSwiperConnected) { //return call from ios function "ActivateSwiper" 50487 hasSwiperConnected = UTIL.parseBool(hasSwiperConnected); 50488 50489 if (innerHeight > 500 && hasSwiperConnected) { 50490 $('#pop-generic-header').after('<div style="letter-spacing: 1px; font-style: italic;">' + SA.Resource.SwipeCardWhenReady + '</div>'); 50491 } 50492 } 50493 50494 function _initTax(jkeyboard) { 50495 if (UTIL.coalesceFloat(GLO.inventoryTax, GLO.serviceTax, 0) === 0) { 50496 if (GLO.Info.roleType > 219) { 50497 var href = GLO.Link.WebsiteDomain + 'provider/inventory#action=inventory-options'; 50498 jkeyboard.find('#btnIncludeTax').attr('id', 'btnAddTax').attr('href', href).removeAttr('onclick').find('a').text(SA.Resource.AddTax); 50499 } 50500 } 50501 50502 var includeTax = $.cookies.get("keypad-include-tax"); 50503 50504 if (UTIL.coalesceFloat(GLO.inventoryTax, 0) > 0 && UTIL.isEmpty(includeTax)) { 50505 _setIncludeTax(true); 50506 } else if (UTIL.parseBool(includeTax) && !jkeyboard.hasClass('include-tax')) { 50507 _setIncludeTax(true); 50508 } 50509 } 50510 50511 function _initShortcutKeys() { 50512 if (!GLO.Info.isMobile(true)) { return; } //swipe card on PC inserts numbers, so must disable. 50513 if (_hasInit) { return; } 50514 _hasInit = true; 50515 50516 $(document).on("keydown", function(e) { 50517 if ( ((e.keyCode > 47 && e.keyCode < 58) || e.keyCode === 46 || e.keyCode === 8 || e.keyCode === 187) && !(e.ctrlKey || e.altKey)) { //= 0-9, DEL, Backspace, '+' 50518 var j = $("#sale-keyboard:visible"); 50519 50520 if (j.length === 0) { 50521 return; 50522 } else { 50523 var jTopPop = GLO.Popup.getTopPopup(); 50524 if (jTopPop.find('#sale-keyboard:visible').length === 0 && ($('#simplemodal-container').length > 0 || jTopPop.length > 0) ) { return; } 50525 } 50526 50527 switch (e.keyCode) { 50528 case 8: var cssKey = 'DEL'; break; 50529 case 46: var cssKey = 'DEL'; break; 50530 case 187: var cssKey = 'PLUS'; break; 50531 50532 case 48: var cssKey = '0'; break; 50533 case 49: var cssKey = '1'; break; 50534 case 50: var cssKey = '2'; break; 50535 case 51: var cssKey = '3'; break; 50536 case 52: var cssKey = '4'; break; 50537 case 53: var cssKey = '5'; break; 50538 case 54: var cssKey = '6'; break; 50539 case 55: var cssKey = '7'; break; 50540 case 56: var cssKey = '8'; break; 50541 case 57: var cssKey = '9'; break; 50542 } 50543 50544 j.find('.number-keypad').find('span.keypad-' + cssKey).click(); //GLO.Sale.Keypad.clickKey 50545 } 50546 }); 50547 } 50548 50549 _conKeypad.openPOS = function() { 50550 if (GLO.Info.isMobile(true)) { 50551 GLO.UI.animate(2); 50552 50553 setTimeout(function() { 50554 document.location = GLO.Link.WebsiteDomain + 'pos'; 50555 }, 200); 50556 } else { 50557 document.location = GLO.Link.WebsiteDomain + 'pos'; 50558 } 50559 50560 return true; 50561 } 50562 50563 _conKeypad.openKeypad = function(apt) { 50564 var isVisible = ($('#sale-keyboard:visible').length > 0);
50565 var isMobile = GLO.Info.isMobile(true); 50566 50567 if (apt === 920 || ( (isMobile || isVisible) && (apt === 900 || apt === 910) ) ) { 50568 if (isMobile) { 50569 GLO.UI.animate(2); 50570 50571 setTimeout(function() { 50572 document.location = GLO.Link.Page.Provider.Home + 'saleKeypad'; 50573 }, 200); 50574 } else { 50575 document.location = GLO.Link.Page.Provider.Home + 'saleKeypad'; 50576 } 50577 50578 return true; 50579 } else if (apt === 900 || apt === 910) { 50580 GLO.Sale.Keypad.openAsPopup(); 50581 return true; 50582 } else { 50583 return false; 50584 } 50585 } 50586 50587 _conKeypad.mustOpenKeypad = function() { 50588 var apt = GLO.Data.Staff.allowedPaymentType; 50589 50590 /* 50591 if (false && GLO.Info.isIosApp && (apt === 900 || apt === 910 || apt === 920)) { //disabled to go use web view instead. 50592 var jd = { "token": $.cookies.get('session'), "min_signature_amount": 5 }; 50593 jd = { "simplesale": jd }; 50594 jd = [JSON.stringify(jd)]; 50595 50596 GLO.Mobile.iosNativeBridge.call("OpenSimpleSale", jd); 50597 return true; 50598 } else 50599 */ 50600 50601 if (apt === 930) { 50602 return _conKeypad.openPOS(); 50603 } else { 50604 return _conKeypad.openKeypad(apt); 50605 } 50606 } 50607 50608 _conKeypad.openAsPopup = function() { 50609 $("#sale-keyboard").modal(); 50610 50611 var jmodal = $("#simplemodal-container").addClass('is-keypad'); 50612 jmodal.css({ "max-height": "760px", "padding": "0" }); 50613 jmodal.find('.simplemodal-data').css({ "padding": "0" }); 50614 jmodal.find('#sale-keyboard-left, #sale-keyboard-right').remove(); 50615 50616 if (!GLO.Info.isMobile()) { 50617 jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" }); 50618 } 50619 50620 $.modal.update(720, 635); 50621 50622 _conKeypad.init(); 50623 } 50624 50625 _conKeypad.clickKey = function() { 50626 var jkey = $(this); 50627 var key = jkey.text(); 50628 50629 var jtotal = $('#keyboard-sub-total'); 50630 var usingSubTotal = false; 50631 50632 if (key !== '<') { 50633 if (UTIL.coalesceMoney($('#keyboard-running-total').text().replace('$', '')) > 99999) { return; } 50634 if (UTIL.coalesceMoney(jtotal.text().replace('$', '')) > 999 && key !== '+') { return; } 50635 } 50636 50637 if (jtotal.hasClass('hide')) { 50638 jtotal = $('#keyboard-running-total'); 50639 } else if (key === '<' && parseFloat(jtotal.find('span').text().replace('$', '')) === 0) { 50640 jtotal.addClass('hide'); 50641 jtotal = $('#keyboard-running-total'); 50642 } else { 50643 jtotal = jtotal.find('span'); 50644 usingSubTotal = true; 50645 } 50646 50647 var total = Math.round(jtotal.text().replace('$', '') * 100); //jtotal.text().replace('$', '').replace('.', ''); 50648 if (!usingSubTotal) { total = _getPreviousTotal(total); } 50649 var isNumber = UTIL.isNumber(key); 50650 50651 if (isNumber) { 50652 total = UTIL.coalesceMoney((total + key)/100, false, true); 50653 if (!usingSubTotal) { total += _updateTax(total); } 50654 } else if (key === '<') { 50655 total = String(total); 50656 total = UTIL.coalesceMoney(total.substring(0, (total.length - 1))/100, false, true); 50657 if (!usingSubTotal) { total += _updateTax(total); } 50658 } else if (key === '+') { 50659 _add(jkey); 50660 _animateKey(key, jkey, jtotal); 50661 return; 50662 } 50663 50664 _setTotal(jtotal, total); 50665 } 50666 50667 function _setTotal(jtotal, total) { 50668 total = UTIL.displayMoney(total, false, true); 50669 if (total === '') { total = '$0.00'; } 50670 jtotal.text(total); 50671 } 50672 50673 function _getPreviousTotal(total) { 50674 if (!_includeTax) { return total; } 50675 50676 return Math.round($('#keyboard-total-tax').find('i').text() * 100); 50677 //return $('#keyboard-total-tax').find('i').text().replace('.', ''); //total = String(Math.round(total - _getTax(total))); 50678 } 50679 50680 function _getTax(total) { 50681 if (!_includeTax) { return 0; } 50682 50683 //return UTIL.coalesceMoney($('#keyboard-total-tax').find('span').text()); 50684 return UTIL.coalesceMoney(total * UTIL.coalesceMoney(GLO.inventoryTax, GLO.serviceTax)/100); 50685 } 50686 50687 function _updateTax(total) { 50688 var tax = _getTax(total); 50689 _setTax(total, tax) 50690 return tax; 50691 } 50692 50693 function _setTax(total, tax) { 50694 tax = UTIL.displayMoney(tax, true, false); 50695 total = UTIL.displayMoney(total, true, false); 50696 50697 if (tax === '') { tax = '0.00'; } 50698 if (total === '') { total = '0.00'; } 50699 50700 var jtax = $('#keyboard-total-tax'); 50701 jtax.find('i').text(total); 50702 jtax.find('span').text(tax); 50703 } 50704 50705 _conKeypad.includeTax = function() { 50706 _includeTax = !_includeTax; 50707 _setIncludeTax();
50708 50709 _changeOtherTaxRate(); 50710 _setIncludeTaxCookie(); 50711 } 50712 50713 _conKeypad.isIncludeTax = function() { 50714 return _includeTax; 50715 } 50716 50717 function _setIncludeTax(mustIncludeTax) { 50718 if (mustIncludeTax) { _includeTax = true; } 50719 50720 var jtotal = $('#keyboard-running-total'); 50721 var total = UTIL.coalesceMoney(jtotal.text().replace('$', '')); 50722 var tax = UTIL.coalesceMoney(GLO.inventoryTax, GLO.serviceTax)/100; 50723 50724 var styleLabel = ' style="display: inline-block; margin: 0; margin-top: 2px; margin-right: 10px; font-size: 108%; color: white;"'; 50725 var pct = '<span style="margin-top: 4px; margin-left: 2px; font-size: 108%; color: white;">%</span>'; 50726 50727 if (GLO.Info.isMobile()) { 50728 var msg = '<div> <label for="inventory_tax_rate_pct"' + styleLabel + '>' + SA.Resource.TaxRate + '</label>' 50729 + '<input id="inventory_tax_rate_pct" type="number" step="0.01" max="5" maxlength="5" style="width: 60px; margin-left: 2px;">' + pct 50730 + '</div>'; 50731 } else { 50732 var msg = '<div style="margin-bottom: 24px;"> <label for="inventory_tax_rate_pct"' + styleLabel + '>' + SA.Resource.PleaseEnterTaxRate + '</label>' 50733 + '<input id="inventory_tax_rate_pct" type="text" maxlength="5" pattern="[0-9]*" onkeypress="UI.numberOnly(event)" style="width: 50px; margin-left: 2px;">' + pct 50734 + '</div>'; 50735 } 50736 50737 if (tax == 0) { 50738 var jpop = new GLO.Popup.Prompt(msg, GLO.Sale.Keypad.saveTax).getPopup().addClass('no-persist'); 50739 50740 jpop.find('#val').remove(); 50741 jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('a').text('Save'); 50742 jpop.find('#inventory_tax_rate_pct').focus(); 50743 50744 return; 50745 } 50746 50747 if (_includeTax) { 50748 tax = total * tax; 50749 50750 $('#sale-keyboard').addClass('include-tax'); 50751 _setTax(total, tax); 50752 total += tax; 50753 } else { 50754 var jsub = $('#keyboard-total-tax'); 50755 subtotal = UTIL.coalesceMoney($('#keyboard-total-tax').find('i').text()); 50756 50757 if (subtotal > 0) { //if has subtotal just use these values (then deal with JS floating point calculations). 50758 total = subtotal 50759 tax = UTIL.coalesceMoney(jsub.find('span').text()); 50760 } else if (total > 0) { 50761 total -= tax; 50762 } 50763 50764 $('#sale-keyboard').removeClass('include-tax'); 50765 } 50766 50767 total = UTIL.displayMoney(total, false, true); 50768 if (total === '') { total = '$0.00'; } 50769 jtotal.text(total); 50770 } 50771 50772 function _setIncludeTaxCookie() { 50773 if (_includeTax) { var includeTax = "1"; } else { var includeTax = "0"; } 50774 50775 //var expireDate = new Date(); 50776 //expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1)); 50777 //$.cookies.set("keypad-include-tax", includeTax, { "expiresAt": expireDate }); 50778 UTIL.setCookie("keypad-include-tax", includeTax); 50779 } 50780 50781 _conKeypad.saveTax = function() { 50782 var jpop = $('.pop-prompt').closest('.glopop'); 50783 var ptax = UTIL.coalesceMoney(jpop.find('#inventory_tax_rate_pct').val()); 50784 50785 //if (ptax == 0) { GLO.Popup.close(jpop); return; } 50786 50787 var url = GLO.Link.Object.Provider.Ajax + 'Tax'; 50788 50789 GLO.inventoryTax = ptax; 50790 _conKeypad.includeTax(); 50791 50792 GLO.UI.Form.beginProcessing(jpop.find('.btnSave:visible')); 50793 //var ojProcessing = new GLO.Popup.Processing('Setting tax rate...'); 50794 //ojProcessing.getPopup().find('.btnOk').remove(); 50795 50796 $.ajax({ type: "POST", url: url, "cache": false, data: { "inventory_tax_rate_pct": ptax } }) 50797 .success(function(data, textStatus, jqXHR) { 50798 GLO.Popup.close(jpop); 50799 }) 50800 .error(function(jqXHR, textStatus, errorThrown) { 50801 GLO.Popup.Error('Unable to change tax. Please try again later.'); 50802 GLO.UI.Form.resetProcessing(); 50803 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 50804 }); 50805 } 50806 50807 _conKeypad.animateMove = function(startElement, endElement, pixelsDown, pixelsRight, animateTime, bDoNotMove) { //to move left or up make # negative 50808 var wrapStartElement = startElement.contents().wrap($('<div>').css('position','absolute')).parent(); 50809 if (!UTIL.isNumber(animateTime)) { animateTime = 800; } 50810 50811 wrapStartElement.animate({ "top": pixelsDown, "left": pixelsRight }, animateTime, function() { 50812 if (!UTIL.parseBool(bDoNotMove)) { endElement.html(wrapStartElement.html()); } 50813 wrapStartElement.remove(); 50814 }); 50815 } 50816 50817 function _animateKey(key, jstart, jend) { 50818 var hgt = 50; 50819 50820 if (key === '1' || key === '2' || key === '3') { 50821 hgt += 60; 50822 } else if (key === '4' || key === '5' || key === '6') { 50823 hgt += 150; 50824 if (!GLO.Info.isMobile()) { hgt += 30; } 50825 } else if (key === '7' || key === '8' || key === '9') { 50826 hgt += 235; 50827 if (!GLO.Info.isMobile()) { hgt += 70; } 50828 } else if (key === '<' || key === '0') { 50829 hgt += 316; 50830 if (!GLO.Info.isMobile()) { hgt += 110; } 50831 } 50832 50833 var top = jstart.position().top; 50834 var left = jstart.position().left + jstart.outerWidth()/2 - jstart.width()/2; 50835 50836 if (GLO.Info.isMobile()) { 50837 var fsize = "200%", margin = "20px", fwgt = "normal"; 50838 } else { 50839 var fsize = "400%", margin = "0", fwgt = "bold"; 50840 } 50841 50842 var jcopy = $('<div>' + jstart.text() + '</div>').css({ "position": "absolute", "top": top, "left": left, "margin": margin, "font-size": fsize, "font-weight": fwgt, "color": "white" }); 50843 jcopy = jcopy.appendTo($('.number-keypad')); 50844 _conKeypad.animateMove(jcopy, jend, -hgt, 0, 300, true); 50845 } 50846 50847 function _animateSubtotal() { 50848 var jsub = $('#sale-keyboard-left #sale-subtotal').find('span'); 50849 50850 _conKeypad.animateMove($('#keyboard-total'), jsub, 220, -210); 50851 return; 50852 /* 50853 var jwrapTotal = $('#keyboard-total').contents().wrap($('<div>').css('position','absolute')).parent(); 50854 50855 jwrapTotal.animate({ "top": 220, "left": -210 }, 400, function() { 50856 var jthis = $(this); 50857 var text = UTIL.displayMoney(UTIL.coalesceMoney(jthis.text().replace('$', ''), 0) + UTIL.coalesceMoney(jsub.text().replace('$', ''), 0), false, true); 50858 50859 jsub.text(text); 50860 jwrapTotal.remove(); 50861 }); 50862 */ 50863 } 50864 50865 function _add(jkey) { 50866 var jsub = $('#keyboard-sub-total').find('span'); 50867 50868 var top = jkey.position().top; 50869 var left = jkey.position().left + jkey.outerWidth()/2; 50870
50871 var jstart = $('<div>' + jkey.text() + '</div>').css({ "position": "absolute", "top": top, "left": left, "font-size": "400%" }); 50872 jstart = jstart.appendTo($('.number-keypad')); 50873 50874 var jend = $('#keyboard-running-total'); 50875 50876 if (GLO.Info.isMobile()) { 50877 var a1right = 300; 50878 var a2top = -330; 50879 var a2right = -200; 50880 } else { 50881 var a1right = 520; 50882 var a2top = -485; 50883 var a2right = -530; 50884 } 50885 50886 if (UTIL.coalesceMoney(jsub.text().replace('$', ''), 0) > 0) { 50887 _conKeypad.animateMove(jsub, jend, 0, a1right, 500, true); 50888 setTimeout(GLO.Sale.Keypad.addToTotal, 400); 50889 } 50890 50891 _conKeypad.animateMove(jstart, jsub, a2top, a2right, 600, true); 50892 setTimeout(function() { $('#keyboard-sub-total').removeClass('hide'); }, 600); 50893 } 50894 50895 _conKeypad.addToTotal = function() { 50896 var sub = $('#keyboard-sub-total').find('span').text().replace('$', ''); 50897 50898 var prev = $('#keyboard-total-tax').find('i').text().replace('$', ''); 50899 //prev = _getPreviousTotal(prev); 50900 50901 var total = UTIL.coalesceMoney(UTIL.coalesceMoney(sub) + UTIL.coalesceMoney(prev)); 50902 total += _updateTax(total); 50903 50904 var jtotal = $('#keyboard-running-total'); 50905 _setTotal(jtotal, total); 50906 } 50907 50908 _conKeypad.openTicket = function(isEnterCardNumber, mobileCardData) { 50909 var price = $('#sale-keyboard.include-tax #keyboard-total-tax').find('i'); 50910 50911 if (price.length > 0) { 50912 price = price.text().replace('$', ''); 50913 } else { 50914 price = $('#keyboard-running-total').text().replace('$', ''); 50915 } 50916 50917 //$('#sale-keyboard .pop-generic-header').text('in OpenTicket'); 50918 50919 _conKeypad.openTicket2(isEnterCardNumber, price, mobileCardData); 50920 } 50921 50922 _conKeypad.openTicketEasy = function(payMethod, price) { 50923 if (GLO.Info.providerPackage == 1) { 50924 var msg = 'To test payment:<br/>1.Create Appointment<br/>2. Press price (in upper left corner of Appointment Popup)<br/>3. Press payment method <b>Credit</b>'; 50925 GLO.Popup.Info.openSimple(msg, 'Test Payment on Appointment'); 50926 } else { 50927 _conKeypad.openTicket2(false, price, null, payMethod); 50928 } 50929 } 50930 _conKeypad.openTicket2 = function(isEnterCardNumber, price, mobileCardData, payMethod) { 50931 UserPortal.Price.quit(); 50932 50933 if (_otherXml !== null) { 50934 _conKeypad.openTicket3(isEnterCardNumber, price, mobileCardData, payMethod); 50935 return; 50936 } 50937 50938 var url = GLO.Link.WebsiteDomain + 'provider/inventory/ItemOther'; 50939 var oj, ajaxRequest; 50940 50941 function fnCancelOpenTicket() { 50942 if (ajaxRequest && ajaxRequest.abort) { 50943 ajaxRequest.abort(); 50944 } 50945 50946 if (oj && oj.close) { 50947 oj.close(); 50948 } 50949 } 50950 50951 oj = new GLO.Popup.Processing(SA.Resource.CreatingTicket + '...', fnCancelOpenTicket); 50952 50953 ajaxRequest = $.ajax({ type: "GET", url: url, "cache": false }) 50954 .success(function(data, textStatus, jqXHR) { 50955 oj.close(); 50956 50957 var li = $('<ul>' + data + '</ul>').find('li') 50958 50959 if (li.length === 1) { 50960 _otherXml = li.outerHTML(); 50961 _changeOtherTaxRate(); 50962 _conKeypad.openTicket3(isEnterCardNumber, price, mobileCardData, payMethod); 50963 } else { 50964 GLO.Popup.Warning('Problem creating ticket. Please try again'); 50965 } 50966 }).error(function(jqXHR, textStatus, errorThrown) { 50967 GLO.Popup.Warning('Error creating ticket. Please try again'); 50968 }); 50969 } 50970 50971 _conKeypad.openTicket3 = function(isEnterCardNumber, price, mobileCardData, payMethod) { //warning -> must call 'UserPortal.Price.quit()' before calling this function 50972 //$('#sale-keyboard .pop-generic-header').text('in OpenTicket3'); 50973 50974 UserPortal.Price.inventoryXml = $(_otherXml).attr('price_mn', price).outerHTML(); 50975 UserPortal.Price.open(false, true); 50976 UserPortal.Price.isKeypad = true; 50977 50978 var jPricePop = $('#appt-price-popup').closest('.glopop'); 50979 jPricePop.find('#Is_Walkin_fl').prop('checked', true).change(); //if (isEnterCardNumber || GLO.Info.isRetail() || $('.shadow-content0 #sale-keyboard:visible').length > 0) { } 50980 50981 if (isEnterCardNumber) { 50982 if (UTIL.coalesceMoney(price, 0) > 0) { 50983 jPricePop.find('#Payment_Method_cd').val(10).change(); 50984 setTimeout(GLO.Sale.Keypad.openEnterCardManually, 200); 50985 } 50986 } else if (payMethod > 0) { 50987 jPricePop.find('#Payment_Method_cd').val(payMethod).change(); 50988 } 50989 50990 if ($('#simplemodal-container #sale-keyboard').length > 0) { 50991 $.modal.close(); 50992 } 50993 50994 if (mobileCardData) { 50995 UserPortal.Price.Payment.openMobileCC(jPricePop, mobileCardData); 50996 } 50997 } 50998 50999 _conKeypad.openEnterCardManually = function(interationCount) { 51000 var jlink = $('.glopop #enter-card-manually > a'); 51001 interationCount = UTIL.coalesceInt(interationCount, 0); 51002 51003 if (jlink.length > 0) { 51004 jlink.click(); //UserPortal.Price.Payment.openCreditCard() 51005 } else if (interationCount < 12) { 51006 setTimeout(function() { GLO.Sale.Keypad.openEnterCardManually(++interationCount); }, 200); 51007 } 51008 } 51009 51010 function _changeOtherTaxRate() { 51011 if (_otherXml === null) { return; } 51012 51013 if (_includeTax) { 51014 taxRate = GLO.inventoryTax; 51015 } else { 51016 taxRate = '0.00'; 51017 } 51018 51019 _otherXml = $(_otherXml).attr('tax_rate_pct', taxRate).outerHTML(); 51020 } 51021 51022 _conKeypad.enterCardNumber = function() { 51023 if (GLO.Info.isIosApp) { 51024 var amt = $('#keyboard-running-total').text().replace('$', ''); 51025 //alert('ShowManualCardEntryPage(' + amt + ')'); 51026 SA.App.showManualCardEntryPage(amt); //GLO.Mobile.iosNativeBridge.call("ShowManualCardEntryPage", [amt]); 51027 } else { 51028 _conKeypad.openTicket(true); 51029 } 51030 } 51031 51032 function _processMobileSwipe(mobileCardData) { 51033 GLO.Sale.Keypad.openTicket(); 51034 var jPricePop = $('#appt-price-popup').closest('.glopop'); 51035 UserPortal.Price.Payment.openMobileCC(jPricePop, mobileCardData); 51036 } 51037 51038 _conKeypad.saveSwipe = function(encrypted, mobileCardData) { 51039 if (GLO.Info.isIosApp) { 51040 GLO.Sale.Keypad.openTicket(false, mobileCardData); // _processMobileSwipe(mobileCardData); 51041 return; 51042 } 51043 51044 if (GLO.Info.providerPackage == 10) { var MIN_SIGNATURE_AMOUNT = 25; } else { var MIN_SIGNATURE_AMOUNT = 5; } 51045 51046 var pmt = $('#keyboard-running-total').text().replace('$', ''); 51047 var tax = $('#keyboard-total-tax:visible').find('span').text().replace('$', ''); 51048 var jsd = { "payment_event_cd": "9", "product_mn": pmt } 51049 51050 if (UTIL.isNumber(tax, true)) { 51051 jsd["product_tax_mn"] = tax; 51052 jsd.product_mn = UTIL.coalesceMoney(jsd.product_mn - tax); 51053 } 51054 51055 if (encrypted) { 51056 jsd.encrypted_card1_vc = encrypted; 51057 } else if (mobileCardData && mobileCardData.encrypted_card) { //= no longer used since mobile swipes are processed thru iOS. 51058 jsd.encrypted_card1_vc = mobileCardData.encrypted_card; 51059 jsd.encrypted1_hex = mobileCardData.encrypted_hex; 51060 } else { 51061 jsd.encrypted_card1_vc = mobileCardData; 51062 } 51063 51064 var url = GLO.Link.WebsiteDomain + 'payment/ProcessCreditCard'; 51065 var msg = '<div class="friendly-msg2" style="height: 48px; min-width: 140px; margin-top: -8px;">' 51066 + '<h1 class="friendly-msg" style="padding-top: 4px; padding-bottom: 0;">' + SA.Resource.ProcessingCard + '...</h1>' 51067 //+ '<div style="font-weight: bold; font-style: italic; color: #4F81BD;">' + SA.Resource.ProcessingCard + '...</div>' 51068 + '<span class="card_in_use-48 sa-sprite" style="margin-left: -30px;">' 51069 + '</div>'; 51070 51071 var ojProcessing = new GLO.Popup.Processing(msg); 51072 ojProcessing.getPopup().find('.pop-buttons-parent').remove(); 51073
51074 $.ajax({ type: "POST", url: url, "cache": false, data: jsd }) 51075 .success(function(data, textStatus, jqXHR) { 51076 ojProcessing.close(); 51077 var jdata = $(data); 51078 51079 if (!UTIL.isEmpty(jdata.attr('error_cd'))) { 51080 _saveCCerror(jdata, false); 51081 } else if (!UTIL.isEmpty(jdata.attr('warning_cd'))) { 51082 _saveCCerror(jdata, true); 51083 } else if (UTIL.isEmpty(jdata.attr('payment_card_id'))) { 51084 _saveCCerror(null, false, SA.Resource.UnableToProcessCreditCard); 51085 } else { 51086 var smid = jdata.attr('schedule_multi_id'); 51087 51088 if (UTIL.isEmpty(smid)) { 51089 _saveCCerror(null, false, SA.Resource.UnableToSaveTicket); 51090 } else { 51091 if (pmt >= MIN_SIGNATURE_AMOUNT && GLO.Info.isMobile(true)) { var bOpenSig = true; } else { var bOpenSig = false; } 51092 51093 _conKeypad.quitSwipe(); 51094 UserPortal.Price.get(smid, bOpenSig, { "isKeypad": true }); 51095 51096 if (!GLO.Info.isMobile()) { new GLO.Popup.Success(SA.Resource.PaymentSuccessfull); } 51097 } 51098 } 51099 }) 51100 .error(function(jqXHR, textStatus, errorThrown) { 51101 ojProcessing.close(); 51102 GLO.Popup.Error('Unable to process card. Please try again later.'); 51103 GLO.UI.Form.resetProcessing(); 51104 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 51105 }); 51106 } 51107 51108 function _saveCCerror(data, isWarning, errMessage) { 51109 GLO.UI.Form.resetProcessing(); 51110 51111 if (!UTIL.isEmpty(errMessage)) { 51112 new GLO.Popup.Error(errMessage); 51113 } else if (data && data.html) { 51114 if (isWarning) { 51115 new GLO.Popup.Warning(data.html()); 51116 } else { 51117 new GLO.Popup.Error(data.html()); 51118 } 51119 } else { 51120 new GLO.Popup.Error('Unable to process card at this time. Please try again'); 51121 } 51122 } 51123 51124 _conKeypad.quitSwipe = function() { 51125 if ($('#simplemodal-container #sale-keyboard').length > 0) { 51126 $.modal.close(); 51127 } 51128 51129 if ($('#report-main:visible').length > 0) { 51130 $('#report-main:visible').find('.btnSearch:visible>a').click() 51131 } 51132 51133 _conKeypad.quit(); 51134 } 51135 51136 _conKeypad.quit = function() { 51137 var j = $('#sale-keyboard'); 51138 j.find('#keyboard-running-total').text('$0.00'); 51139 51140 var jtax = j.find('#keyboard-total-tax'); 51141 jtax.find('i').text(''); 51142 jtax.find('span').text(''); 51143 } 51144 51145 _conKeypad.clear = function() { 51146 if (GLO.Info.isIosApp || $('.shadow-content0 #sale-keyboard:visible').length > 0 || $('#sale-keyboard').closest('.glopop').length > 0) { 51147 _conKeypad.quit(); 51148 } 51149 } 51150 51151 return _conKeypad; 51152})(); 51153 51154 51155SA.POS = (function() { //boxtype: 'i' = product, 'pl' = pline, 'v' = vendor, 'p' = prev, 'n' = next, 'u' = unit, 'c' = category, 'ct' = category type, 't' = (old type category) 51156 function _conPos() { } 51157 _conPos.jsonPos = {}; 51158 _conPos.boxArray = []; 51159 _conPos.sortType = 1; //1 = Category, 2 = Brand. 51160 var _boxesPerPage = 56, _lastEventRefresh = new Date(), _lastApptRefreshDate = null; 51161 var _compressStaffBoxesTimeout = null; 51162 51163 _conPos.init = function(jsonPosInput) { 51164 GLO.Info.init(); 51165 GLO.isPOS = true; 51166 UserPortal.Calendar.setStaffFilter(); 51167 51168 _conPos.inventory_json = jsonPosInput; 51169 _conPos.sortType = _conPos.inventory_json.sort_type_cd; 51170 51171 _initTicketPanel(); 51172 _initStaffScreen(); 51173 _initStaffScreenHeader(); 51174 _initOnScreenKeypad(); 51175 51176 _initLeftHandMode(); 51177 _boxCountChanged(); 51178 _initDisplayBoxes(); 51179 _setServiceGroupList(); 51180 51181 _initAutoComplete(); 51182 _initPosKeys(); 51183 _initSwitchToEditMode(); 51184 51185 //$('#pos-menu-button').click(SA.POS.toggleMenu); //GLO.UI.setClick($('#pos-menu-button'), null, SA.POS.toggleMenu); 51186 51187 _initMobilePOS(); 51188 _conPos.Edit.changeSortBy(); 51189 _initLoadImages(); 51190 jscolor.init(); 51191 51192 _initWelcomePopup(); 51193 _conPos.resize(); 51194 51195 window.onresize = function(event) { SA.POS.resize(event); }; 51196 51197 GLO.WaitList.setupRefresh(null, true); //GLO.WaitList.monitorFrontDesk(); 51198 _initUrlActionPOS(); 51199 _initApptRefresh();
51200 _initHeight(); 51201 _initQRCode(); 51202 51203 GLO.Info.setupFastClick(); 51204 51205 if (!GLO.Info.isMobile(true)) { 51206 $('#pos-staff-list-client:visible').focus(); 51207 } 51208 } 51209 function _initQRCode() { 51210 var jhead1 = $('#pos-staff-list-header1'); 51211 51212 if (GLO.Data.provider.traveler_cd > 0) { 51213 jhead1.find('#pos-staff-list-header1-qr').removeClass('hide'); 51214 UserPortal.Lookup.initMonitorQRScan(); 51215 } else { 51216 jhead1.find('#pos-staff-list-header1-divider, #pos-staff-list-header1-qr').remove(); 51217 } 51218 } 51219 function _initTicketPanel() { 51220 if (_conPos.inventory_json.hide_ticket_panel_fl || UTIL.parseBool($.cookies.get('hide_ticket_panel_fl'))) { 51221 $('#pos-panel-client').addClass('hideX'); 51222 } 51223 } 51224 function _initStaffScreen(isAlphabetical) { 51225 if (isAlphabetical) { 51226 var htm = '', staffList = UserPortal.getStaffDropDown().find('option'); 51227 51228 for (var i=0; i < staffList.length; i++) { 51229 var staffName = staffList.eq(i).text(), staffId = staffList.eq(i).attr('value'); 51230 var isFA = UTIL.parseBool(staffList.eq(i).attr('is_first_available_fl')); 51231 var thumb = staffList.eq(i).attr('thumbnail'); 51232 51233 htm += _createStaffBox(staffName, staffId, isFA, thumb); 51234 $('#pos-staff-screen #pos-staff-list').html(htm); 51235 } 51236 } else { 51237 var staffList = GLO.staffResources; 51238 _loadStaffBoxes(staffList, true); 51239 } 51240 } 51241 function _loadStaffBoxes(arrStaff, isInit) { 51242 var arrToday = [], arrPresent = [], htmPresent = '', htmToday = '', htmFA = '', htmOff = ''; 51243 51244 for (var i=0; i < arrStaff.length; i++) { 51245 if (UTIL.parseBool(arrStaff[i].is_first_available_fl)) { 51246 htmFA = _createStaffBoxSetup(arrStaff[i], 'staff-first-available'); 51247 } else if (_isCurrentlyWorking(arrStaff[i])) { 51248 arrPresent.push(arrStaff[i]); 51249 } else { 51250 arrToday.push(arrStaff[i]); 51251 } 51252 } 51253 51254 htmPresent += _createStaffBoxes(arrPresent, 'staff-present'); 51255 htmToday += _createStaffBoxes(arrToday, 'staff-today'); 51256 51257 for (var a=0; a < GLO.staffResources.length; a++) { 51258 var hasStaff = false; 51259 51260 for (var i=0; i < arrStaff.length; i++) { 51261 if (arrStaff[i].id == GLO.staffResources[a].id) { 51262 hasStaff = true; 51263 break; 51264 } 51265 } 51266 51267 if (!hasStaff) { 51268 htmOff += _createStaffBoxSetup(GLO.staffResources[a], 'staff-off'); 51269 } 51270 } 51271 51272 if (!UTIL.isEmpty(htmToday)) { 51273 htmPresent += '<li id="staff-working-today" class="staff-off-spacer"><b class="staff-off-curently">' + _getStaffOffLabel(null, null, htmToday) + '</b></li>' + htmToday; 51274 //htmFA = ''; 51275 } 51276 51277 if (!UTIL.isEmpty(htmFA) || !UTIL.isEmpty(htmOff)) { 51278 htmPresent += '<li id="staff-off-today" class="staff-off-spacer"><b class="staff-off-today">' + _getStaffOffLabel(htmFA, htmOff) + '</b></li>' + htmFA + htmOff; 51279 } 51280 51281 if (false) { //add fake staff for testing UI layout 51282 for (var i=1; i < 21; i++) { 51283 htmPresent += '<li class="staff-today pos-staff-cell" staff_id="123" onclick="SA.POS.openStaffPreview(this)"><b class="fa fa-user staff-thumbnail"></b>' 51284 + '<label class="pos-staff-name">Test Staff #' + i + '</label><div class="staff-normal-hours"><b>11:30 am - 8:30 pm</b></div></li>'; 51285 } 51286 } 51287 51288 $('#pos-staff-screen #pos-staff-list').html(htmPresent); 51289 } 51290 function _isCurrentlyWorking(staffObject) { 51291 var day = new Date(new Date().toGloDate()); 51292 var tmStart = staffObject.start_tm, tmEnd = staffObject.end_tm; 51293 var hasClockIn = false, hasClockOut = false; 51294 51295 if (UTIL.isDate(staffObject.clockin_dt)) { 51296 tmStart = new Date(staffObject.clockin_dt).toGloTime(); 51297 hasClockIn = true; 51298 } 51299 51300 if (UTIL.isDate(staffObject.clockout_dt)) { 51301 tmEnd = new Date(staffObject.clockout_dt).toGloTime(); 51302 hasClockOut = true 51303 } 51304 51305 var dtStart = UTIL.joinDateAndTime(day, tmStart); 51306 var dtEnd = UTIL.joinDateAndTime(day, tmEnd); 51307 51308 if (hasClockIn && !hasClockOut) { 51309 return true; 51310 } else if (dtStart < new Date() && dtEnd > new Date()) { 51311 var itmNow = UTIL.timeToInt(new Date().toGloTime()); 51312 51313 for (var b=0;
51313 b < staffObject.breaks.length; b++) { 51314 if (itmNow > staffObject.breaks[b].start_sr && staffObject.breaks[b].end_sr > itmNow) { 51315 staffObject.is_on_break_fl = staffObject.breaks[b].is_on_break_fl = true; 51316 return false; 51317 } 51318 } 51319 51320 return true; 51321 } else { 51322 return false; 51323 } 51324 } 51325 function _getStaffOffLabel(htmFA, htmOff, htmToday) { 51326 if (!UTIL.isEmpty(htmFA) && !UTIL.isEmpty(htmToday)) { 51327 return 'First Available + Not Clocked-In or Scheduled Now'; 51328 } else if (!UTIL.isEmpty(htmToday)) { 51329 return 'Not Clocked-In or Scheduled'; 51330 } 51331 51332 if (!UTIL.isEmpty(htmFA) && !UTIL.isEmpty(htmOff)) { 51333 return 'First Available + Off Today'; 51334 } else if (!UTIL.isEmpty(htmFA)) { 51335 return 'First Available'; 51336 } else if (!UTIL.isEmpty(htmOff)) { 51337 return 'Off Today'; 51338 } 51339 } 51340 51341 /* Sort By: 51342 1. clockin time 51343 2. start time 51344 3. normal calendar order 51345 4. alphabetical 51346 5. not working today 51347 */ 51348 function _sortStaffBoxes(box1, box2) { 51349 var iTime = UTIL.timeToInt(new Date().toGloTime()); 51350 51351 if (box1.has_clockin && !box2.has_clockin) { 51352 return -1; 51353 } else if (!box1.has_clockin && box2.has_clockin) { 51354 return 1; 51355 } else if (iTime > box1.end_sr && iTime > box2.end_sr) { //staff finished for the day 51356 if (box1.end_sr == box2.end_sr) { 51357 if (box1.order < box2.order) { //if (box1.name < box2.name) { 51358 return -1; 51359 } else { 51360 return 1; 51361 } 51362 } else if (box1.end_sr < box2.end_sr) { 51363 return -1; 51364 } else { 51365 return 1; 51366 } 51367 } else if (box1.start_sr == box2.start_sr) { 51368 if (box1.order < box2.order) { 51369 return -1; 51370 } else { 51371 return 1; 51372 } 51373 } else if (box1.start_sr < box2.start_sr) { 51374 return -1; 51375 } else { 51376 return 1; 51377 } 51378 } 51379 function _createStaffBoxes(arrStaff, cssClass) { 51380 var htm = ''; 51381 arrStaff.sort(_sortStaffBoxes); 51382 51383 for (var i=0; i < arrStaff.length; i++) { 51384 htm += _createStaffBoxSetup(arrStaff[i], cssClass); 51385 } 51386 51387 return htm; 51388 } 51389 function _createStaffBoxSetup(staffObject, cssClass) { 51390 var staffName = staffObject.name, staffId = staffObject.id; 51391 var isFA = UTIL.parseBool(staffObject.is_first_available_fl); 51392 var thumb = staffObject.thumbnail; 51393 51394 return _createStaffBox(staffName, staffId, isFA, thumb, cssClass, staffObject); 51395 } 51396 function _createStaffBox(staffName, staffId, isFA, thumb, cssClass, staffObject) { 51397 var styleName = ''; 51398 var onClick = ' onclick="SA.POS.openStaffPreview(this)"'; 51399 var cssName = 'pos-staff-name', shortStaffName = UTIL.maxString(staffName, 15, true); 51400 var htmLabel = _getLabelHtm(staffObject, isFA, cssClass); 51401 51402 cssClass = UTIL.cleanString(cssClass) + ' pos-staff-cell'; 51403 51404 if (shortStaffName.length > 10) { 51405 cssName += ' pos-staff-name-long'; 51406 } 51407 51408 if (!UTIL.isEmpty(staffObject.color)) { 51409 styleName = ' style="background-color: rgb(' + staffObject.color + ');"'; 51410 cssClass += ' pos-staff-has-color'; 51411 } 51412 51413 //var color = GLO.RunningTotal.getResourceStaffColor(staffId); 51414 var personIcon = '<b class="fa fa-user staff-thumbnail"></b>' 51415 var sname = '<label class="' + cssName + '"' + styleName + '>' + shortStaffName + '</label>'; 51416 var faAttribute = '', htmAttributes = '', htmUpcoming = '', htmNow = ''; 51417 51418 if (UserPortal.staffPerformsClientService(staffId) && sname != 'Anyone') { 51419 if (UTIL.parseBool(isFA)) { 51420 faAttribute = ' is_first_available_fl="1"'; 51421 //cssClass += ' is-first-available'; 51422 } 51423 51424 if (staffObject && (staffObject.start_sr > 0 || staffObject.service_count_sr)) { 51425 if (staffObject.is_on_break_fl) { 51426 for (var b=0; b < staffObject.breaks.length; b++) { 51427 if (staffObject.breaks[b].is_on_break_fl) { 51428 var start = staffObject.breaks[b].start_tm.replace(':00', ''), end = staffObject.breaks[b].end_tm.replace(':00', ''); 51429 var label = UTIL.maxString(staffObject.breaks[b].service_vc, 15, true); 51430 var htmService = '<div class="staff-break-name"><b>' + label + '</b></div>'; 51431 var htmHours = '<div class="staff-normal-hours staff-break-hours"><b>' + start + ' - ' + end + '</b></div>'; 51432 51433 htmAttributes += htmService + htmHours; 51434 cssClass += ' is-on-break'; 51435 } 51436 } 51437 } else if (staffObject.start_sr > 0 && staffObject.end_sr > 0) { 51438 var tmStart = UTIL.intToTime(staffObject.start_sr).replace(':00', ''), tmEnd = UTIL.intToTime(staffObject.end_sr).replace(':00', ''); 51439 var hasClockIn = false, hasClockOut = false, cssStart = '', cssEnd = ''; 51440 51441 if (UTIL.isDate(staffObject.clockin_dt)) { 51442 tmStart = new Date(staffObject.clockin_dt).toGloTime(); 51443 hasClockIn = true; 51444 cssStart = 'is-clock-in'; 51445 } 51446 51447 if (UTIL.isDate(staffObject.clockout_dt)) { 51448 tmEnd = new Date(staffObject.clockout_dt).toGloTime(); 51449 hasClockOut = true 51450 cssStart = 'is-clock-out'; 51451 } 51452 51453 if (hasClockIn && !hasClockOut) { 51454 cssClass += ' is-clocked-in'; 51455 } 51456 51457 htmAttributes += '<div class="staff-normal-hours"><b><b class="' + cssStart + '">' + tmStart + '</b> - <b class="' + cssEnd + '">' + tmEnd + '</b></b></div>'; 51458 } 51459 51460 htmAttributes += _staffBoxApptIcons(staffObject); 51461 } 51462 51463 if (!UTIL.isEmpty(thumb)) { 51464 cssClass += ' has-staff-icon'; 51465 personIcon = '<img class="staff-thumbnail" src="' + GLO.Data.cdnDirectory + "upload-folder/" + thumb + '"/>'; 51466 } 51467 51468 var htmClockInAndOut = _getClockInAndOut(staffObject); 51469 //if (currSID == sid) { css = ' selected'; } 51470 return '<li class="' + cssClass + '" staff_id="' + staffId + '"' + faAttribute + onClick + styleName + '>' + personIcon + sname + htmLabel + htmAttributes + htmClockInAndOut + '</li>'; 51471 } 51472 51473 return ''; 51474 } 51475 51476 function _getClockInAndOut(staffObject) { 51477 if (staffObject.clockInAndOut && staffObject.clockInAndOut.length > 0) { 51478 var tbl = '<table id="staff-prev-clock-out-list"> <thead> <tr> <th colspan="3">Clock-In/Out</th> </tr> </thead> <tbody>'; 51479 51480 for (var i=0; i < staffObject.clockInAndOut.length; i++) { 51481 var tdIn = '<td class="prev-clock-in">' + staffObject.clockInAndOut[i].clockin_dt.toGloTime() + '</td>'; 51482 var tdOut = '<td class="prev-clock-out">' + staffObject.clockInAndOut[i].clockout_dt.toGloTime() + '</td>'; 51483 51484 tbl += '<tr>' + tdIn + '<td>-</td>' + tdOut + '</tr>'; 51485 } 51486 51487 return tbl + '</tbody></table>'; 51488 } 51489 51490 return ''; 51491 } 51492 51493 function _getLabelHtm(staffObject, isFA, cssClass) { 51494 if (isFA || cssClass != 'staff-present') { 51495 return ''; 51496 } 51497 51498 if (staffObject.status && staffObject.status.label) { 51499 if (staffObject.walkin_signin_sr > 0 && staffObject.status.priority > 9) { 51500 var css = 'label-status-2', title = '', label = 'SIGN-In <i>WALK-In</i>'; 51501 return _conPos.getLabelHtm(css, title, 2, 2, label); 51502 } 51503 51504 var cssClass = _getLabelCss(staffObject); 51505 var title = UTIL.cleanString(staffObject.status.event.labelDescription); 51506 var priority = staffObject.status.priority, status = staffObject.status.appt_status_cd; 51507 51508 return _conPos.getLabelHtm(cssClass, title, priority, status, staffObject.status.label); 51509 } else { 51510 return '<b class="staff-box-label">AVAILABLE</b>'; 51511 } 51512 } 51513 _conPos.getLabelHtm = function(cssClass, title, priority, status, label) { 51514 return '<b class="staff-box-label ' + cssClass + '" title="' + title + '" priority_sr="' + priority + '" appt_status_cd="' + status + '">' + label + '</b>'; 51515 } 51516 function _getLabelCss(staffObject) { 51517 if (staffObject.status && staffObject.status.appt_status_cd) { 51518 var css = 'label-status-' + staffObject.status.appt_status_cd; 51519 51520 if (staffObject.status && staffObject.status.event) { 51521 css += _getLabelSoonCss(staffObject); 51522 } 51523 51524 return css; 51525 } else { 51526 return ''; 51527 } 51528 } 51529 function _getLabelSoonCss(staffObject) { 51530 var apptStatus = staffObject.status.appt_status_cd; 51531 51532 if (apptStatus == 21) {
51533 var endsIn = UTIL.coalesceInt( (new Date(staffObject.status.event.end) - new Date()) / (1000 * 60), 0); 51534 51535 if (endsIn < 5) { 51536 return ' very-soon'; 51537 } else if (endsIn < 15) { 51538 return ' soon'; 51539 } 51540 } else if (apptStatus == 2) { 51541 var signinWait = UTIL.coalesceInt( (new Date() - new Date(staffObject.status.event.signin_dt)) / (1000 * 60), 0); 51542 51543 if (signinWait > 5) { 51544 return ' waiting'; 51545 } else if (signinWait > 15) { 51546 return ' very-waiting'; 51547 } 51548 } else if (apptStatus == 39) { 51549 if (endsIn < 5) { 51550 return ' very-soon'; 51551 } else if (endsIn < 15) { 51552 return ' soon'; 51553 } 51554 } else if (apptStatus == 41) { 51555 var startsIn = UTIL.coalesceInt( (new Date(staffObject.status.event.start) - new Date()) / (1000 * 60), 0); 51556 51557 if (startsIn < 5) { 51558 return ' very-soon'; 51559 } else if (startsIn < 15) { 51560 return ' soon'; 51561 } 51562 } 51563 51564 return ''; 51565 } 51566 51567 _conPos.getSigninIcon = function(count) { 51568 var titleNow = UTIL.pluralLabel(count, 'client self sign-in'); 51569 51570 var htmIcon = '<span class="staff-appt-count staff-appt-signin "><b class="staff-appt-signin-count" title="' + titleNow + '">' + count + '</b></span>'; 51571 htmIcon += '<b class="staff-arrow-now-in" class="arrow-right">➜</b>'; 51572 51573 return htmIcon; 51574 } 51575 51576 function _staffBoxApptIcons(staffObject) { 51577 var htmIcons = ''; 51578 var signinCount = UTIL.coalesceInt(UTIL.coalesceInt(staffObject.walkin_signin_sr, 0) + UTIL.coalesceInt(staffObject.signin_count_sr, 0), 0); 51579 51580 if (signinCount) { 51581 //var jstaff = $('#pos-staff-screen').find('.pos-staff-cell[staff_id="' + staffObject.id + '"]'); 51582 //var signinCount = UTIL.coalesceInt(UTIL.coalesceInt(jstaff.attr('walkin_signin_sr'), 0) + staffObject.signin_count_sr); 51583 htmIcons += _conPos.getSigninIcon(signinCount); 51584 } 51585 51586 if (staffObject.checkin_count_sr > 0) { 51587 var titleIn = UTIL.pluralLabel(staffObject.checkin_count_sr, 'ticket') + ' checked-in'; 51588 var htmIn = '<b class="staff-appt-checkin-count" title="' + titleIn + '">' + staffObject.checkin_count_sr + '</b>'; 51589 51590 htmIcons += '<span class="staff-appt-count staff-appt-checkin">' + htmIn + '</span>'; 51591 htmIcons += '<b class="staff-arrow-in-out" class="arrow-right">➜</b>'; 51592 } 51593 51594 if (staffObject.checkout_count_sr > 0) { 51595 var titleOut = UTIL.pluralLabel(staffObject.checkout_count_sr, 'ticket') + ' checked-out'; 51596 var htmOut = '<b class="staff-appt-checkout-count" title="' + titleOut + '">' + staffObject.checkout_count_sr + '</b>'; 51597 51598 htmIcons += '<span class="staff-appt-count staff-appt-checkout">' + htmOut + '</span>'; 51599 } 51600 51601 if (staffObject.now_count_sr > 0) { 51602 var titleNow = UTIL.pluralLabel(staffObject.now_count_sr, 'now appointment (starts within 20 minutes)'); 51603 var htmNow = '<b class="staff-appt-now-count" title="' + titleNow + '">' + staffObject.now_count_sr + '</b>'; 51604 51605 htmIcons += '<span class="staff-appt-count staff-appt-now">' + htmNow + '</span>'; 51606 } 51607 51608 if (staffObject.late_count_sr > 0) { 51609 var titleLate = UTIL.pluralLabel(staffObject.late_count_sr, 'late appointment (start time more than 20 minutes after current time, but less than 90 minutes)'); 51610 var htmLate = '<b class="staff-appt-late-count" title="' + titleLate + '">' + staffObject.late_count_sr + '</b>'; 51611 51612 htmIcons += '<span class="staff-appt-count staff-appt-late">' + htmLate + '</span>'; 51613 } 51614 51615 if (staffObject.upcoming_count_sr > 0) { 51616 var titleUpcoming = UTIL.pluralLabel(staffObject.upcoming_count_sr, 'upcoming appointment'); 51617 var htmUpcoming = '<b class="staff-appt-upcoming-count" title="' + titleUpcoming + '">' + staffObject.upcoming_count_sr + '</b>'; 51618 51619 htmIcons += '<span class="staff-appt-count staff-appt-upcoming">' + htmUpcoming + '</span>'; 51620 } 51621 51622 if (staffObject.past_count_sr > 0) { 51623 var titlePast = UTIL.pluralLabel(staffObject.past_count_sr, 'past appointment'); 51624 var htmPast = '<b class="staff-appt-past-count" title="' + titlePast + '">' + staffObject.past_count_sr + '</b>'; 51625 51626 htmIcons += '<span class="staff-appt-count staff-appt-past">' + htmPast + '</span>'; 51627 } 51628 51629 return htmIcons; 51630 } 51631 51632 function _initStaffScreenHeader() { 51633 var jclient = $('#pos-staff-screen #pos-staff-list-client'); 51634 var uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1&InventorySearch=1'; 51635 var fnMultiLocation = UserPortal.importClientOpen; 51636 var fnOnSelect = SA.Ticket.addClientSelected; 51637 51638 UI.initAutoComplete(jclient, uriClientSearch, fnMultiLocation, fnOnSelect); 51639 51640 var jday = $('#Ticket_day'); 51641 var jtime = $('#Ticket_tm'); 51642 //var yearRange = GLO.UI.getYearRange(true); 51643 51644 jday.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 51645 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
51645atepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 51646 UI.timeMask('#Ticket_tm'); 51647 51648 jtime.click(function() { 51649 var h1 = 'Appointment Time', jelement = $(this), htm = '', cssStyle = '', fnAfterSave = null; 51650 51651 if ($.trim(this.value).length < 4) { 51652 UI.setTimeMaskValue(jelement, SA.Ticket.getTime()); 51653 } 51654 51655 UI.Keypad.openTime(h1, htm, jelement, fnAfterSave); 51656 }); 51657 51658 if (!GLO.Info.isMobile(true)) { 51659 jtime.attr('readonly', 'readonly'); 51660 } 51661 51662 if (UTIL.isEmpty(SA.POS.inventory_json.gift_card_type_id)) { 51663 $('#pos-quick-sell-header').remove(); 51664 } 51665 } 51666 function _initOnScreenKeypad() { 51667 $('#pos-staff-list-client').click(function() { 51668 var jclient = $(this); 51669 var h1 = 'Enter Client Name or Phone Number'; 51670 var htm = null, cssStyle = null; 51671 51672 var jkeypad = UI.Keypad.openKeypadCharacter(h1, htm, jclient, cssStyle).addClass('sa-keypad-name'); 51673 var jinput = jkeypad.find('input.sa-keypad').addClass('support-scan'); 51674 var fnOnSelect = SA.Ticket.addClientSelected, uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1&InventorySearch=1'; 51675 var btnAddClient = '<span id="btnAddNewClient" class="btnAdd btnLeftCorner"><a onclick="UserPortal.Create.addClientLink(false, true)">Add New Client</a></span>'; 51676 51677 UI.initAutoComplete(jinput, uriClientSearch, null, fnOnSelect); 51678 jkeypad.find('.pop-buttons2').append(btnAddClient); 51679 51680 if ($('#simplemodal-container:visible').length === 0) { 51681 jinput.bind('keydown', function(e) { 51682 if (e.which === 13) { // ENTER 51683 if ($('.pop-processing').closest('.glopop').length) { return; } 51684 51685 SA.TicketCard.enterTicketNumber(this); 51686 } 51687 }); 51688 } 51689 }); 51690 51691 $('#posTime_vc').click(function() { 51692 var h1 = 'Appointment Time', jelement = $(this), htm = '', cssStyle = '', fnAfterSave = null; 51693 UI.Keypad.openTime(h1, htm, jelement, fnAfterSave); 51694 }); 51695 } 51696 51697 function _initHeight() { 51698 if (innerHeight < 120 + 768 + 10) { 51699 $('#pos-container').addClass('compress-box'); 51700 } 51701 51702 /* if (innerHeight < 650) { 51703 $('#pos-container').addClass('short5'); 51704 $('#pos-container').addClass('compress-box'); 51705 } else if (innerHeight < 690) { 51706 $('#pos-container').addClass('short4'); 51707 $('#pos-container').addClass('compress-box'); 51708 } else if (innerHeight < 730) { 51709 $('#pos-container').addClass('short3'); 51710 $('#pos-container').addClass('compress-box'); 51711 } else if (innerHeight < 770) { 51712 $('#pos-container').addClass('short2'); 51713 } else if (innerHeight < 810) { 51714 $('#pos-container').addClass('short1'); 51715 } */ 51716 } 51717 function _initDisplayBoxes() { 51718 if (_conPos.inventory_json.service_groups.length === 0) { 51719 $('#pos-toggle-list').remove(); 51720 _conPos.displayBoxes(); 51721 } else { 51722 _conPos.toggleList('services'); 51723 _setLargeStaffBoxes(); 51724 } 51725 } 51726 function _setLargeStaffBoxes() { 51727 var jStaffList = $('#pos-staff-list'); 51728 var staffWidth = jStaffList.width(); 51729 var staffHeight = innerHeight - $('#pos-product-header').height() - $('#pos-staff-list-header').height() - $('#pos-footer-inner').height() - 60; //jStaffList.height(); 51730 51731 var staffBoxWide = parseInt(staffWidth / 240); 51732 var staffBoxTall = parseInt(staffHeight / 180); 51733 var staffBigCount = parseInt(staffBoxWide * staffBoxTall); 51734 var staffCount = jStaffList.find('.pos-staff-cell').length; 51735 51736 if (innerWidth >= 1120 && staffBigCount >= staffCount) { 51737 $('#pos-container').addClass('big-staff-card'); 51738 } else { 51739 $('#pos-container').removeClass('big-staff-card'); 51740 } 51741 } 51742 function _initMobilePOS() { 51743 if (GLO.Info.isIPad) { 51744 $(document).bind('touchmove', false); 51745 51746 var pos = document.getElementById('pos-container'); 51747 new FastClick(pos); 51748 } 51749 51750 if (GLO.Info.isMobile(true)) { 51751 $('#pos-ticket').on('focus', 'input', SA.Ticket.inputOnFocus); 51752 } 51753 } 51754 function _initUrlActionPOS() { 51755 var open = GLO.Uri.query('open'); 51756 51757 if (GLO.Uri.query('menu') === 'open' && !$('#pos-action-menu').is(':visible')) { 51758 SA.POS.toggleActionMenu(); 51759 } 51760 51761 if (open == 'manager-reports') { 51762 SA.POS.openManagerReport(); 51763 } else if (open == 'report-menu') {
51764 SA.POS.openReportMenu(); 51765 } else if (open == 'manage-profile') { 51766 SA.POS.openProfile(); 51767 } else if (open == 'edit-and-info') { 51768 SA.POS.Edit.openHelp(); 51769 } else if (open == 'quick-guide') { 51770 SA.POS.openHelpQuickGuide(); 51771 } else if (open == 'staff-summary') { 51772 $('#pos-staff-list .pos-staff-cell').click(); 51773 } 51774 51775 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 51776 51777 if (!UTIL.isEmpty(highlight)) { 51778 setTimeout(function() { 51779 var jhigh = $('#' + highlight); 51780 51781 if (jhigh.length) { 51782 UI.highlight(jhigh, 100, 9500, true); 51783 return true; 51784 } 51785 }, 1500); 51786 } 51787 } 51788 function _initSwitchToEditMode() { 51789 if (UTIL.parseBool(GLO.Uri.query('edit'))) { // || _conPos.inventory_json.products.length === 0 51790 if (!UTIL.parseBool(_conPos.inventory_json.no_toggle_menu_fl)) { 51791 _conPos.toggleActionMenu(); 51792 _conPos.Edit.changeMode(); 51793 } 51794 } 51795 51796 if (innerWidth < 860) { 51797 $('#pos-header-edit-option-table #sort-products-row').find('label[for="edit-pos-sortby"]').text('Sort'); 51798 } 51799 } 51800 function _initLeftHandMode() { 51801 var jpos = $('#pos-container'); 51802 51803 if (UTIL.parseBool(_conPos.inventory_json.left_hand_fl)) { 51804 $('#edit-pos-left-hand-mode').prop('checked', true); 51805 jpos.removeClass('left-ticket'); //'left-hand-mode' puts ticket on the right. 51806 } 51807 } 51808 function _initWelcomePopup() { 51809 return; 51810 if (!_displayWelcomePopup()) { return; } 51811 //if (!GLO.Info.isMobile(true)) { return; } 51812 51813 var h1 = '<h1 class="friendly-msg2">Point-of-Sale System (P.O.S.)</h1>'; 51814 var p1 = '<p>The <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span> P.O.S. is another way you can create tickets and invoices for product sales as well as manage your product list</p>'; 51815 var p2 = '<p style="margin-top: 20px; margin-bottom: 2px; text-align: center; text-transform: capitalize; font-weight: bold;">On this screen you can</p>'; 51816 var ul = '<ul>' 51817 + '<li>Select a product to add it to the ticket</li>' 51818 + '<li>Press View Ticket to open the ticket you have created</li>' 51819 + '<li>Press the menu button to navigate to another page or edit your product list</li>' 51820 + '</ul>'; 51821 51822 var jpop = new GLO.Popup.Info('<div id="pop-pos-welcome">' + h1 + '<div style="letter-spacing: 1px;">' + p1 + p2 + ul + '</div></div>').getPopup(); 51823 jpop.find('.msg').css({ "padding-top": "4px" }); 51824 } 51825 function _displayWelcomePopup() { 51826 if (UTIL.parseBool($.cookies.get('has-pos-welcome'))) { return false; } 51827 51828 UTIL.setCookieWithExpire('has-pos-welcome', '1'); //$.cookies.set('has-pos-welcome', '1'); 51829 return true; 51830 } 51831 51832 function _initLoadImages() { //= preload images so they are faster 51833 var preloader = $('#preload').append('<div id="preload-pos-images" style="display: none;"></div>'); 51834 51835 _initLoadImages2(preloader, SA.POS.inventory_json.products); 51836 _initLoadImages2(preloader, SA.POS.inventory_json.plines); 51837 _initLoadImages2(preloader, SA.POS.inventory_json.vendors); 51838 51839 _initLoadImages2(preloader, SA.POS.inventory_json.types); 51840 _initLoadImages2(preloader, SA.POS.inventory_json.categories); 51841 51842 _initLoadImages2(preloader, SA.POS.inventory_json.service_groups); 51843 _initLoadImages2(preloader, SA.POS.inventory_json.services); 51844 } 51845 51846 function _initLoadImages2(preloader, list) { 51847 if (list) { 51848 for (var i=0; i < list.length; i++) { 51849 51850 if (!UTIL.isEmpty(list[i].image_vc)) { 51851 var img = GLO.Data.cdnDirectory + "upload-folder/" + list[i].image_vc; 51852 $("<img/>").attr("src", img).appendTo(preloader); 51853 } 51854 } 51855 } 51856 } 51857 51858 function _initPosKeys() { 51859 $(document).on("keydown", function(e) { 51860 if (e.keyCode === 72) { //= h 51861 if (e.ctrlKey || e.altKey) { // || $(':focus:input').length === 0 51862 SA.POS.filterBoxesHome(); 51863 e.preventDefault(); 51864 return false; 51865 } 51866 } 51867 }); 51868 } 51869 51870 _conPos.searchProductList = function(requestObj, responseFn) { 51871 var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex(requestObj.term), "i"); 51872 var found = [], all = SA.POS.inventory_json.products; 51873 51874 for (var f=0; f < all.length; f++) { 51875 var item = all[f]; 51876 51877 if (matcher.test(item.label)) { 51878 found.push(item); 51879 } else if (requestObj.term.length > 4) { 51880 if (matcher.test(item.upc_vc) || matcher.test(item.sku_vc)) { 51881 var item2 = jQuery.extend({}, item); 51882 item2.is_sku_upc_match_fl = true; 51883 51884 found.push(item2); 51885 } 51886 } 51887 } 51888 51889 responseFn(found); 51890 } 51891 51892 function _initAutoComplete() { 51893 var jinput = $("#pos-enter-product-or-amount"); 51894 51895 jinput.autocomplete({ 51896 source: SA.POS.searchProductList, //SA.POS.inventory_json.products, 51897 minLength: 2, 51898 autoFocus: true, 51899 open: function(event, ui) { 51900 $('.ui-autocomplete.auto-select-first-item').find('li:first').click(); 51901 }, 51902 select: function( event, ui ) { 51903 SA.Ticket.addProductLine(ui.item.id); 51904 event.target.value = ''; 51905 return false; 51906 } 51907 }); 51908 /* .data( "ui-autocomplete" )._renderItem = function(ul, item) { 51909 var str = "<a><span style='color: #62BECB;'>" + item.label + "</span> "; 51910 if (item.size_vc && item.unit_abbreviation_vc) { str += item.size_vc + ' ' + item.unit_abbreviation_vc; } 51911 51912 if (!UTIL.isEmpty(item.price_mn)) { str += '<i>' + UTIL.displayMoney(item.price_mn, false, true) + '</i>'; } 51913 str += "</a>"; 51914 51915 return $("<li></li>").data("ui-autocomplete-item", item).append(str).appendTo(ul); 51916 }; */ 51917 51918 jinput.data("ui-autocomplete")._renderMenu = function(ul, items) { 51919 var that = this; 51920 51921 $.each(items, function(index, item) { 51922 that._renderItemData(ul, item); 51923 });
51924 51925 $(ul).find("li:odd").addClass("odd"); 51926 51927 if (items.length === 1 && items[0].is_sku_upc_match_fl == 1) { 51928 $(ul).addClass('auto-select-first-item', true); 51929 } 51930 }; 51931 } 51932 _conPos.toggleList = function(listType) { 51933 var j = $('#pos-container').removeClass('staff-screen'); 51934 var jtoggle = j.find('#pos-toggle-list'); 51935 51936 if (listType === 'services') { 51937 j.removeClass('products').addClass('services'); 51938 jtoggle.find('#btnDisplayProducts').removeClass('selected'); 51939 jtoggle.find('#btnDisplayServices').addClass('selected'); 51940 var svcSortType = $('#pos-header-service-sort').find('input[name = "service_sort_type_cd"]:checked'); 51941 51942 if (svcSortType.val() == 11) { 51943 j.addClass('service-sort-custom'); 51944 } 51945 } else { 51946 j.removeClass('services').removeClass('service-sort-custom').addClass('products'); 51947 jtoggle.find('#btnDisplayServices').removeClass('selected'); 51948 jtoggle.find('#btnDisplayProducts').addClass('selected'); 51949 } 51950 51951 _boxCountChanged(); 51952 SA.POS.filterBoxesHome(); //j.find('#pos-breadcrumb-home:visible').click(); 51953 _conPos.resize(); 51954 } 51955 _conPos.compressStaffBoxes = function() { 51956 var heightHeader = $('#pos-product-header').height(); 51957 var jscreen = $('#pos-staff-screen'); 51958 var heightScreen = jscreen.height(); 51959 var heightFooter = $('#pos-footer').height(); 51960 51961 if (heightHeader + heightScreen > innerHeight) { 51962 jscreen.find('#pos-staff-list').addClass('compress'); 51963 } else { 51964 jscreen.find('#pos-staff-list').removeClass('compress'); 51965 } 51966 51967 /* if (heightHeader + heightScreen + heightFooter > innerHeight) { 51968 $('#pos-footer').addClass('compress').addClass('float-footer'); 51969 } else { 51970 $('#pos-footer').removeClass('float-footer'); 51971 } */ 51972 } 51973 _conPos.resetPanelHeight = function(event) { 51974 var jpanel = $('#pos-panel-client'); 51975 var jscreen = $('#pos-staff-screen'); 51976 51977 var heightHeader = $('#pos-product-header').height(); 51978 var heightFooter = $('#pos-footer').height(); 51979 var heightPanel = jpanel.find('table').height(); 51980 51981 var panelHeight = innerHeight - heightHeader - 10; 51982 jpanel.css({ "height": panelHeight + "px" }); 51983 jpanel.find('#pos-panel-client-list').css({ "height": panelHeight + "px" }); 51984 51985 if (heightHeader + heightFooter + heightPanel > innerHeight) { 51986 var newWidth = jscreen.width(); 51987 51988 $('#pos-footer').addClass('compress').css({ "width": newWidth + "px" }); 51989 } else if (jscreen.height() + 50 <= innerHeight) { 51990 $('#pos-footer').removeClass('compress').css({ "width": "" }); 51991 } 51992 } 51993 _conPos.resize = function(event) { 51994 _setPosHeight(); 51995 _setTicketHeight(); 51996 51997 var posTicketWidth = _getPosTicketWidth(); 51998 var posCategoryWidth = _getPosCategoryWidth(); 51999 _setPosWindowWidth(posTicketWidth, posCategoryWidth); 52000 _setPosCategoryHeight(); 52001 52002 if (_boxCountChanged()) { 52003 SA.POS.Edit.clickBreadcrumbEnd(null, null, true); 52004 //SA.POS.displayBoxes(); 52005 //alert('innerWidth = ' + innerWidth + '; _boxesPerPage = ' + _boxesPerPage); 52006 } 52007 52008 _conPos.resetPanelHeight(); 52009 52010 clearTimeout(_compressStaffBoxesTimeout); 52011 _compressStaffBoxesTimeout = setTimeout(SA.POS.compressStaffBoxes, 500); 52012 } 52013 function _setTicketHeight() { 52014 var jticket = $('#pos-ticket'); 52015 52016 if (innerWidth > 632) { //if innerWidth > 1200 (because then footer is in the middle) -> can extend ticket height (base on innerHeight) 52017 var posHeaderHeight = $('#pos-product-header').height(); 52018 var posTicketTop = UTIL.coalesceInt(jticket.css('top').replace('px', '')); 52019 var posTicketFooter = jticket.find('#pos-ticket-total-line').height() + jticket.find('#pos-ticket-header').height() + jticket.find('#pos-ticket-footer').height(); 52020 52021 var jclient = $('#pos-ticket-client'); 52022 var clientExtra = UTIL.coalesceInt(jclient.css('margin-top').replace('px', '')); 52023 var clientHeight = jclient.height(); 52024
52025 var availableHeight = innerHeight - posHeaderHeight - posTicketTop - posTicketFooter - clientExtra - clientHeight - 20; 52026 var jticket2 = jticket.find('#pos-ticket-order'); 52027 52028 if (availableHeight < 370) { 52029 if (jticket2.height() < 370) { 52030 return; 52031 } else { 52032 jclient.css({ "height": "" }); 52033 availableHeight = 360; 52034 } 52035 } else if (availableHeight > 600) { 52036 clientHeight += availableHeight - 600; 52037 availableHeight = 600; 52038 52039 jclient.height(clientHeight); 52040 } 52041 52042 jticket2.height(availableHeight); 52043 } else if (jticket.css('height') != '100%') { 52044 jticket.css({ "height": "100%" }); 52045 } 52046 } 52047 function _setPosHeight() { 52048 var jpos = $('#pos-body'); 52049 var jfooter = $('#pos-footer'); 52050 52051 if (innerWidth > 632) { 52052 var posFooterHeight = 0; 52053 } else { 52054 var posFooterHeight = jfooter.height() + UTIL.coalesceInt(jfooter.css('padding-top').replace('px', '')); 52055 } 52056 52057 var posBodyMargin = UTIL.coalesceInt(jpos.css('margin-top').replace('px', '')); 52058 var posBodyHeight = jpos.height(); 52059 var posHeight = posBodyMargin + posBodyHeight + posFooterHeight; 52060 var newHeight = innerHeight - posBodyMargin - posFooterHeight; 52061 52062 var ticketHeader = $('#pos-quick-link-header').height() + $('#pos-header-staff-ticket').height(); 52063 var newTicketHeight = innerHeight - ticketHeader; 52064 52065 _setPosHeight2(jpos, posHeight, newHeight); 52066 52067 if (newTicketHeight < 768) { 52068 if (newHeight < 500) { 52069 newTicketHeight = 500 + (posBodyHeight + posFooterHeight - ticketHeader); 52070 } 52071 52072 var extraToRemove = parseInt(768 - newTicketHeight) + 2; 52073 $('#pos-ticket-order').height(360 - extraToRemove/2); 52074 $('#pos-ticket-client').height(240 - extraToRemove/2); 52075 } else { 52076 $('#pos-ticket-order').css({ "height": "" }); 52077 $('#pos-ticket-client').css({ "height": "" }); 52078 } 52079 } 52080 function _setPosHeight2(jpos, posHeight, newHeight) { 52081 if (innerHeight > posHeight) { 52082 jpos.height(newHeight); 52083 } else if (posHeight > innerHeight) { 52084 if (newHeight < 500) { 52085 newHeight = 500; 52086 } 52087 52088 jpos.height(newHeight); 52089 } 52090 } 52091 function _setPosWindowWidth(posTicketWidth, posCategoryWidth) { 52092 var jpos = $('#pos-body').removeClass('window-stretch6').removeClass('window-stretch12').removeClass('window-stretch18').removeClass('window-stretch24').removeClass('window-stretch30'); 52093 jpos.removeClass('window-stretch30').removeClass('window-stretch36').removeClass('window-stretch42').removeClass('window-stretch48'); 52094 52095 var boxWidth = _posGetBoxWidth(jpos); 52096 var posWindoWidth = $('body')[0].clientWidth - posTicketWidth - posCategoryWidth; //.clientWidth -> if html page taller than screen, clientWidth = innerWidth - scrollbar 52097 52098 var boxesPerRow = parseInt(posWindoWidth / boxWidth); 52099 var extraPerRow = parseInt(posWindoWidth - boxWidth * boxesPerRow); 52100 var extraPerBox = parseInt(extraPerRow / boxesPerRow) - 1; //-1 (to be safe) 52101 52102 if (innerWidth >= 632 && innerWidth <= 660) { 52103 // 52104 } else if (extraPerBox > 48) { 52105 jpos.addClass('window-stretch48'); 52106 } else if (extraPerBox > 42) { 52107 jpos.addClass('window-stretch42'); 52108 } else if (extraPerBox > 36) { 52109 jpos.addClass('window-stretch36'); 52110 52111 } else if (extraPerBox > 30) { 52112 jpos.addClass('window-stretch30'); 52113 } else if (extraPerBox > 24) { 52114 jpos.addClass('window-stretch24'); 52115 } else if (extraPerBox > 18) { 52116 jpos.addClass('window-stretch18'); 52117 } else if (extraPerBox > 12) { 52118 jpos.addClass('window-stretch12'); 52119 } else if (extraPerBox > 6) { 52120 jpos.addClass('window-stretch6'); 52121 } 52122 52123 jpos.find('#pos-product-window').css({ "width": posWindoWidth + "px", "margin-left": posCategoryWidth + "px" }); 52124 } 52125 function _setPosCategoryHeight() { 52126 var jlist = $('#pos-container.services #pos-service-group-list'); 52127 52128 if (jlist.length) { 52129 var headerHeight = $('#pos-product-header').height() + jlist[0].offsetTop; 52130 var listHeight = jlist.height(); 52131 52132 if (headerHeight + listHeight >
52132 innerHeight) { 52133 jlist.height(innerHeight - headerHeight); 52134 } else if (jlist[0].scrollHeight > listHeight) { 52135 if (headerHeight + jlist[0].scrollHeight > innerHeight) { 52136 jlist.height(innerHeight - headerHeight); 52137 } else { 52138 jlist.height(jlist[0].scrollHeight + 1); 52139 } 52140 } 52141 } 52142 } 52143 function _getPosCategoryWidth() { 52144 var screenWidth = innerWidth; //$('body')[0].clientWidth; 52145 var jlist = $('#pos-container.services #pos-service-group-list'); 52146 52147 if (jlist.length && screenWidth > 970) { 52148 if (screenWidth >= 1200) { 52149 return 200 + 4; 52150 } else if (screenWidth > 1030) { 52151 return 160 + 4; 52152 } else { 52153 return 140 + 2; 52154 } 52155 } else { 52156 return 0; 52157 } 52158 } 52159 function _getPosTicketWidth() { 52160 var screenWidth = innerWidth; //$('body')[0].clientWidth; 52161 52162 if (screenWidth >= 1680) { 52163 return 464; 52164 } else if (screenWidth > 1000) { 52165 return 340; 52166 } else if (screenWidth > 632) { 52167 return 320; 52168 } else { 52169 return 0; 52170 } 52171 } 52172 function _posGetBoxWidth(jpos) { 52173 var jbox1 = jpos.find('.pos-product-box:visible:first'); 52174 var screenWidth = innerWidth; //$('body')[0].clientWidth; 52175 52176 if (jbox1.length) { 52177 var style = jbox1[0].currentStyle || window.getComputedStyle(jbox1[0]); 52178 var boxMargin = parseFloat(style.marginLeft) + parseFloat(style.marginRight); 52179 return UTIL.coalesceInt(jbox1.outerWidth(), 166) + UTIL.coalesceInt(boxMargin, 2); 52180 } else { 52181 var boxWidth = 166; 52182 52183 if (screenWidth > 1000) { 52184 return boxWidth + 4; 52185 } else { 52186 return boxWidth + 2; 52187 } 52188 } 52189 } 52190 52191 _conPos.refreshFromUser = function(isBackground) { 52192 var seconds = parseInt((new Date() - _lastEventRefresh)/1000); 52193 var maxRefreshSeconds = 5; 52194 52195 GLO.Popup.closeIfExist($('#pop-pos-refresh').closest('.glopop')); 52196 52197 if ($('#cal-refresh-icon').hasClass('simple-spin')) { 52198 if (!isBackground) { 52199 var htm = '<div id="pop-cal-refresh">Currently Refreshing POS Tickets...</div>'; 52200 GLO.Popup.Processing.open(htm, 'Refreshing P.O.S.'); 52201 } 52202 } else if (seconds < maxRefreshSeconds) { 52203 if (!isBackground) { 52204 var msg1 = 'P.O.S. Refreshed ' + UTIL.pluralLabel(seconds, 'second') + ' ago'; 52205 var msg2 = 'Please wait ' + UTIL.pluralLabel(maxRefreshSeconds - seconds, 'second') + ' to refresh again'; 52206 var msg3 = '<span class="btnAdd"><a onclick="location.reload()">Full Screen Refresh</a></span>'; 52207 var htm = '<div id="pop-pos-refresh"><p>' + msg1 + '</p><p>' + msg2 + '</p><p style="margin: 24px; text-align: center;">' + msg3 + '</p></div>'; 52208 52209 GLO.Popup.Success.open(htm, 'P.O.S. Refresh'); 52210 } 52211 } else { 52212 GLO.Uri.removeHashKey('panel'); 52213 SA.POS.refreshEvents(true); 52214 //GLO.WaitList.monitorInBackground(); 52215 } 52216 52217 UserPortal.editPasswordRemove(); 52218 } 52219 function _initApptRefresh() { 52220 setInterval(function() { 52221 SA.POS.refreshEvents(); 52222 }, 45000); //runs every 45 seconds. 52223 52224 _conPos.refreshEvents(true); 52225 } 52226 _conPos.refreshEvents = function(override, threshold) { 52227 if (UTIL.isEmpty(threshold)) { 52228 threshold = 15; 52229 } 52230 52231 var dt = new Date(); 52232 dt.setMinutes(dt.getMinutes() - threshold); 52233 52234 if (override || _lastEventRefresh < dt) { 52235 _lastEventRefresh = new Date(); 52236 _resetWalkinSignins(); 52237 52238 _getApptJson(); 52239 SA.TicketCard.refreshSigninList(); 52240 } 52241 } 52242 function _resetWalkinSignins() { 52243 for (var i=0; i < GLO.resourceHours.length; i++) { 52244 delete GLO.resourceHours[i].walkin_signin_sr 52245 } 52246 } 52247 52248 function _getApptJson() { 52249 var url = GLO.Link.Object.AppointmentAjax + 'GetJson?cdn=' + GLO.Data.cdnVersion + '&timezone=' + -new Date().getTimezoneOffset()/60 + '&sfilter=' + UserPortal.staffFilter; 52250 52251 var day = new Date(new Date().toGloDate()); //toDo (later): support when user's timezone != salon timezone 52252 var startTimestamp = Math.round(+day / 1000); 52253 var endTimestamp = Math.round(+new Date(day).addDays(1) / 1000); 52254 52255 var jrefresh = $('#cal-refresh-icon').addClass('simple-spin'); 52256
52257 $.ajax({ "type": "GET", "url": url, "cache": false, "dataType": "json", "data": { "start": startTimestamp, "end": endTimestamp } }) 52258 .success(function(calEvents, textStatus, jqXHR) { 52259 //toDo (later): support when user's timezone != salon timezone -> for (var i=0; i< calEvents.length; i++) { normalizeEvent(calEvents[i]); } 52260 52261 var arrStaff = GLO.Staff.Filter.staffWorkingOnDay(day, calEvents); 52262 _adjustStaffObjectsForClockInAndOut(arrStaff); 52263 _loadStaffBoxes(arrStaff); 52264 52265 SA.TicketCard.loadAppointments(calEvents); 52266 _finishLoadJson(jrefresh); 52267 SA.TicketCard.refreshFilterPanel(); 52268 SA.TicketCard.loadExtraClockOutsOnStaffPreview(); 52269 }) 52270 .error(function(jqXHR, textStatus, errorThrown) { 52271 UserPortal.Calendar.processCalendarAjaxError(arguments[0]); 52272 UTIL.Validate.processLogoutWhenNeeded(); 52273 }); 52274 } 52275 52276 function _adjustStaffObjectsForClockInAndOut(arrStaff) { 52277 for (var i=0; i < arrStaff.length; i++) { 52278 if (UTIL.isDate(arrStaff[i].clockin_dt)) { 52279 arrStaff[i].has_clockin = true; 52280 arrStaff[i].clockin_tm = new Date(arrStaff[i].clockin_dt).toGloTime(); 52281 arrStaff[i].start_sr = UTIL.timeToInt(arrStaff[i].clockin_tm); 52282 } else { 52283 arrStaff[i].has_clockin = false; 52284 } 52285 52286 if (UTIL.isDate(arrStaff[i].clockout_dt)) { 52287 arrStaff[i].has_clockout = true; 52288 arrStaff[i].clockout_tm = new Date(arrStaff[i].clockout_dt).toGloTime(); 52289 arrStaff[i].end_sr = UTIL.timeToInt(arrStaff[i].clockout_tm); 52290 } else { 52291 arrStaff[i].has_clockout = false; 52292 } 52293 52294 _setMissingTime(arrStaff[i]); 52295 } 52296 } 52297 function _setMissingTime(staffObject) { //when adjust hours (drag open/close time up or down to open a day normall not working) sometimes open or close is empty 52298 if (GLO.ScheduleSummary) { 52299 var arr = GLO.ScheduleSummary; 52300 var isValidOpen = UTIL.isValidTime(staffObject.start_tm, true); 52301 var isValidClosed = UTIL.isValidTime(staffObject.end_tm, true); 52302 52303 if (isValidOpen && isValidClosed) { 52304 return false; 52305 } 52306 52307 for (var i=0; i < arr.length; i++) { 52308 if (staffObject.id == arr[i].staff_id) { 52309 if (isValidOpen && !isValidClosed) { 52310 staffObject.end_tm = new Date(arr[i].close_dt).toGloTime(); 52311 staffObject.end_sr = UTIL.timeToInt(staffObject.end_tm); 52312 return true; 52313 } else if (!isValidOpen && isValidClosed) { 52314 staffObject.start_tm = new Date(arr[i].open_dt).toGloTime(); 52315 staffObject.start_sr = UTIL.timeToInt(staffObject.start_tm); 52316 return true; 52317 } 52318 } 52319 } 52320 } 52321 } 52322 function _finishLoadJson(jrefresh) { 52323 _lastApptRefreshDate = new Date(); 52324 jrefresh.removeClass('simple-spin').attr('title', 'Last Refesh at ' + _lastApptRefreshDate.toGloTime()); 52325 52326 GLO.Popup.closeIfExist($('#pop-pos-refresh').closest('.glopop')); 52327 } 52328 52329 function _boxCountChanged() { 52330 var newBoxCount; 52331 var screenWidth = innerWidth; //$('body')[0].clientWidth; 52332 var jcontainer = $('#pos-container'); 52333 52334 if (screenWidth >= 1500 && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services')) { 52335 newBoxCount = 56; 52336 } else if (screenWidth <= 486) { 52337 newBoxCount = 16; 52338 } else if (screenWidth <= 632) { 52339 newBoxCount = 15; 52340 } else if (screenWidth <= 810) { 52341 newBoxCount = 8; 52342 } else if (screenWidth <= 970) { 52343 newBoxCount = 12; 52344 } else if (screenWidth <= 1200) { 52345 newBoxCount = 16; 52346 } else if (screenWidth <= 1364) { 52347 newBoxCount = 20; 52348 } else if (screenWidth <= 1530) { 52349 newBoxCount = 24; 52350 } else if (screenWidth <= 1700) { 52351 newBoxCount = 28; 52352 } else if (screenWidth <= 1900) { 52353 newBoxCount = 32; 52354 } else {
52355 newBoxCount = 36; 52356 } 52357 52358 if (newBoxCount != _boxesPerPage) { 52359 _boxesPerPage = newBoxCount; 52360 return true; 52361 } else { 52362 return false; 52363 } 52364 } 52365 52366 _conPos.displayBoxes = function(grandId, parentId) { 52367 var isEdit = $('#pos-container').hasClass('edit-pos'); 52368 var products = SA.POS.inventory_json.products; 52369 52370 if (_conPos.sortType === 2) { 52371 var vendorId = grandId; 52372 var productLineId = parentId; 52373 var vendors = SA.POS.inventory_json.vendors; 52374 var plines = SA.POS.inventory_json.product_lines; 52375 } else { 52376 var categoryId = grandId; 52377 var ctypeId = parentId; 52378 var categories = SA.POS.inventory_json.categories; 52379 var ctypes = SA.POS.inventory_json.types; 52380 } 52381 52382 if (productLineId) { 52383 _conPos.filterBoxesProductLine(productLineId, isEdit); 52384 } else if (vendorId) { 52385 _conPos.filterBoxesVendor(vendorId, isEdit); 52386 } else if (categoryId) { 52387 _conPos.filterBoxesCategory(categoryId, isEdit); 52388 } else if (ctypeId) { 52389 _conPos.filterBoxesCategoryType(ctypeId, isEdit); 52390 } else { 52391 _conPos.filterBoxesHome(isEdit); 52392 } 52393 } 52394 52395 function _isDisplayServices() { 52396 return $('#btnDisplayServices.selected').length; 52397 } 52398 _conPos.isDisplayServices = function() { 52399 return _isDisplayServices(); 52400 } 52401 _conPos.filterBoxesHome = function(isEdit, isSystemReset) { 52402 if (!GLO.isPOS) { return; } 52403 if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); } 52404 52405 var css, arr = []; 52406 52407 if (_isDisplayServices()) { 52408 _displayServiceGroupBoxes(isEdit); 52409 return; 52410 } else if (_conPos.sortType === 2) { 52411 var boxtype = 'v', grand = SA.POS.inventory_json.vendors; 52412 } else { 52413 var boxtype = 'c', grand = SA.POS.inventory_json.categories; 52414 } 52415 52416 for (var i=0; i < grand.length; i++) { 52417 if (isEdit || grand[i].total_product_count > 0) { 52418 arr.push(_getBox(boxtype, grand[i], isEdit)); 52419 } 52420 } 52421 52422 if (_conPos.sortType === 2) { 52423 var products = SA.POS.inventory_json.products; 52424 52425 for (var j=0; j < products.length; j++) { 52426 if (UTIL.isEmpty(products[j].vendor_id)) { 52427 arr.push(_getBox('i', products[j], isEdit)); 52428 } 52429 } 52430 } else { 52431 var products = SA.POS.inventory_json.products; 52432 52433 for (var j=0; j < products.length; j++) { 52434 if (UTIL.isEmpty(products[j].category_id) && UTIL.isEmpty(products[j].inventory_type_id)) { 52435 arr.push(_getBox('i', products[j], isEdit)); 52436 } 52437 } 52438 } 52439 52440 _displayBoxes(arr, null, null, isSystemReset); 52441 } 52442 52443 _conPos.filterBoxesCategory = function(categoryId, isEdit, isFromBreadcrumb) { 52444 var css, arr = [], products = SA.POS.inventory_json.products; 52445 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", categoryId); 52446 var categories = SA.POS.inventory_json.categories, ctypes = SA.POS.inventory_json.types; 52447 52448 if (UTIL.isEmpty(isEdit)) { var isEdit = $('#pos-container').hasClass('edit-pos'); } 52449 52450 if (!isEdit) { 52451 if ((category.type_count === 1 && category.product_count === category.total_product_count) || category.type_count === 0 || (category.product_count === 0 && category.type_count === 1)) { 52452 if (categories.length === 1) { //= all products in same category/type. 52453 _displayBoxesProducts(products, isEdit); 52454 return; 52455 } else if (category.type_count === 1 && category.product_count === 0) { //= all products in same type 52456 for (var i=0; i < ctypes.length; i++) { 52457 if (category.id === ctypes[i].category_id) { 52458 if (isEdit || ctypes[i].product_count > 0) { 52459 _conPos.filterBoxesCategoryType(ctypes[i].id); 52460 return; 52461 } 52462 } 52463 } 52464 } 52465 } 52466 } 52467 52468 for (var a=0; a < ctypes.length; a++) { 52469 if (categoryId == ctypes[a].category_id) { 52470 if (isEdit || ctypes[a].product_count > 0) { 52471 arr.push(_getBox('ct', ctypes[a], isEdit)); 52472 } 52473 } 52474 } 52475 52476 for (var b=0;
52476 b < products.length; b++) { 52477 if (categoryId == products[b].category_id && UTIL.isEmpty(products[b].inventory_type_id)) { 52478 arr.push(_getBox('i', products[b], isEdit)); 52479 } 52480 } 52481 52482 _displayBoxes(arr, category); 52483 } 52484 _conPos.filterBoxesVendor = function(vendorId, isEdit, isFromBreadcrumb) { 52485 var css, arr = [], vendors = SA.POS.inventory_json.vendors, plines = SA.POS.inventory_json.product_lines, products = SA.POS.inventory_json.products; 52486 var vendor = _conPos.getVendorObject(vendorId); 52487 52488 if (UTIL.isEmpty(isEdit)) { var isEdit = $('#pos-container').hasClass('edit-pos'); } 52489 52490 if ((vendor.product_line_count === 1 && vendor.product_count === vendor.total_product_count) || vendor.product_line_count === 0) { //= all products in same product line. 52491 if (vendors.length === 1 && vendors[0].total_product_count === products.length) { //= all products in same vendor/product line. 52492 _displayBoxesProducts(products, isEdit); 52493 return; 52494 } else if (vendor.product_line_count === 1 && vendor.product_count === 0) { 52495 for (var i=0; i < plines.length; i++) { 52496 if (vendor.id === plines[i].vendor_id) { 52497 if (isEdit || plines[i].product_count > 0) { 52498 _conPos.filterBoxesProductLine(plines[i].id, isEdit); 52499 return; 52500 } 52501 } 52502 } 52503 } 52504 } 52505 52506 for (var a=0; a < plines.length; a++) { 52507 if (vendorId == plines[a].vendor_id) { 52508 if (isEdit || plines[a].product_count > 0) { 52509 arr.push(_getBox('pl', plines[a], isEdit)); 52510 } 52511 } 52512 } 52513 52514 for (var b=0; b < products.length; b++) { 52515 if (vendorId == products[b].vendor_id && UTIL.isEmpty(products[b].product_line_id)) { 52516 arr.push(_getBox('i', products[b], isEdit)); 52517 } 52518 } 52519 52520 _displayBoxes(arr, vendor); 52521 } 52522 _conPos.filterBoxesProductLine = function(productLineId, isEdit, isFromBreadcrumb) { 52523 var css, arr = [], vendors = SA.POS.inventory_json.vendors, plines = SA.POS.inventory_json.product_lines, products = SA.POS.inventory_json.products; 52524 52525 if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); } 52526 52527 for (var i=0; i < products.length; i++) { 52528 if (productLineId == products[i].product_line_id) { 52529 arr.push(_getBox('i', products[i], isEdit)); 52530 } 52531 } 52532 52533 var productLine = _conPos.getPLineObject(productLineId); 52534 var vendor = _conPos.getVendorObject(productLine.vendor_id); 52535 52536 _displayBoxes(arr, vendor, productLine); 52537 } 52538 _conPos.filterBoxesCategoryType = function(ctypeId, isEdit, isFromBreadcrumb) { 52539 var css, arr = [], categories = SA.POS.inventory_json.categories, ctypes = SA.POS.inventory_json.types, products = SA.POS.inventory_json.products; 52540 52541 if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); } 52542 52543 for (var i=0; i < products.length; i++) { 52544 if (ctypeId == products[i].inventory_type_id) { 52545 arr.push(_getBox('i', products[i], isEdit)); 52546 } 52547 } 52548 52549 var categoryType = _conPos.getObject(SA.POS.inventory_json.types, "id", ctypeId); 52550 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", categoryType.category_id); 52551 52552 _displayBoxes(arr, category, categoryType); 52553 } 52554 52555 function _addEmptyBoxes(arr, box, expectedOrder, isEditPos) { 52556 var order = box.order; 52557 52558 if (expectedOrder != order) { 52559 for (; expectedOrder < order; expectedOrder++) { 52560 _addEmptyBox(arr, expectedOrder, isEditPos); 52561 } 52562 } 52563 52564 return expectedOrder; 52565 } 52566 function _addEmptyBox(arr, order, isEditPos) { 52567 if (isEditPos) { 52568 var htmDragText = 'Drag Service Box Here'; //_getBoxDragHandle(isEditPos, true); 52569 } else { 52570 var htmDragText = ''; 52571 } 52572 52573 var htmEmpty = '<div class="pos-product-box pos-product-box-empty" order_sr="' + order + '">' + htmDragText + '</div>'; 52574 52575 arr.push(htmEmpty); 52576 } 52577 function _getBoxDragHandle(isEditPos, isIncludeText) { 52578 var htmDragHandle = ''; 52579 52580 if (isEditPos) { 52581 htmDragHandle = '<b class="pos-box-drag"></b>'; 52582 52583 if (isIncludeText) { 52584 htmDragHandle += '<div class="pos-box-drag-text"><i>Drag Service</i> <i>Box Here</i></div>'; 52585 } 52586 } 52587 52588 return htmDragHandle; 52589 } 52590 52591 _conPos.filterServiceBoxesByStaff = function(staffId, sgid) { 52592 var arr = []; 52593 var jcontainer = $('#pos-container'); 52594 var isCustomServiceOrder = (innerWidth >= 1500) && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services'); //= isAddEmptyBoxes 52595 var isEdit = jcontainer.hasClass('edit-pos'); 52596 var currentOrder = 1; 52597 52598 if (!UTIL.isEmpty(sgid)) { //display services (in sg) 52599 var jsvc = $('#allServiceOptions #crSvc' + sgid); 52600 var sg = _conPos.getServiceGroupObject(sgid); 52601 var boxes = SA.POS.inventory_json.services; 52602 52603 for (var i=0; i < boxes.length; i++) { 52604 if (sgid == boxes[i].service_group_id) { 52605 var svcid = boxes[i].id; 52606 52607 if (UTIL.isEmpty(staffId) || jsvc.find('option[value="' + svcid + '"]').attr('staff_ids').split(',').has(staffId)
52607) { 52608 var price = UserPortal.Booking.lookupService(svcid, staffId).price; //UserPortal.Booking.lookupServiceForStaff(svcid, staffId).price; 52609 var box = boxes[i]; 52610 52611 if (!UTIL.isEmpty(price) && UTIL.coalesceMoney(price) != UTIL.coalesceMoney(box.price_mn)) { 52612 box = jQuery.extend({}, box); 52613 box.price_mn = price; 52614 } 52615 52616 if (isCustomServiceOrder) { 52617 currentOrder = _addEmptyBoxes(arr, boxes[i], currentOrder); 52618 } 52619 52620 arr.push(_getBox('s', box, isEdit)); 52621 ++currentOrder; 52622 } else if (isCustomServiceOrder) { 52623 _addEmptyBox(arr, currentOrder, false); 52624 ++currentOrder; 52625 } 52626 } 52627 } 52628 } else { //display sg 52629 var jsg = $('#ServiceGroupOptionsClone'); 52630 var sg = null; 52631 var boxes = SA.POS.inventory_json.service_groups; 52632 52633 for (var i=0; i < boxes.length; i++) { 52634 sgid = boxes[i].id; 52635 52636 if (UTIL.isEmpty(staffId) || jsg.find('option[value="' + sgid + '"]').attr('staff_ids').split(',').has(staffId)) { 52637 if (isCustomServiceOrder) { 52638 currentOrder = _addEmptyBoxes(arr, boxes[i], currentOrder); 52639 } 52640 52641 arr.push(_getBox('sg', boxes[i], isEdit)); 52642 ++currentOrder; 52643 } else if (isCustomServiceOrder) { 52644 _addEmptyBox(arr, i+1, false); 52645 ++currentOrder; 52646 } 52647 52648 ++currentOrder; 52649 } 52650 } 52651 52652 _displayBoxes(arr, sg); 52653 52654 if (!UTIL.isEmpty(sgid)) { 52655 jcontainer.find('#pos-service-group-list').find('.pos-type-list[service_group_id = "' + sgid + '"]').addClass('selected-service-group'); 52656 } 52657 } 52658 52659 _conPos.filterBoxesServiceGroup = function(sgid, isEdit, isFromBreadcrumb) { 52660 var arr = [], services = SA.POS.inventory_json.services; 52661 var sg = _conPos.getServiceGroupObject(sgid); 52662 var staffId = $('#pos-header-staff').find('#btnSelectedStaff > a').attr('staff_id'); 52663 52664 if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); } 52665 52666 if (true || !UTIL.isEmpty(staffId)) { 52667 _conPos.filterServiceBoxesByStaff(staffId, sgid); 52668 return; 52669 } 52670 52671 for (var i=0; i < services.length; i++) { 52672 if (sgid == services[i].service_group_id) { 52673 arr.push(_getBox('s', services[i], isEdit)); 52674 } 52675 } 52676 52677 _displayBoxes(arr, sg); 52678 $('#pos-container').find('#pos-service-group-list').find('.pos-type-list[service_group_id = "' + sgid + '"]').addClass('selected-service-group'); 52679 } 52680 52681 function _displayBoxesProducts(products, isEdit) { 52682 var css, arr = []; 52683 52684 for (var i=0; i < products.length; i++) { 52685 arr.push(_getBox('i', products[i], isEdit)); 52686 } 52687 52688 _displayBoxes(arr); 52689 } 52690 52691 function _displayServiceGroupBoxes(isEdit) { 52692 var arr = [], currentOrder = 1; 52693 var staffId = $('#pos-header-staff').find('#btnSelectedStaff > a').attr('staff_id'); 52694 var jcontainer = $('#pos-container'); 52695 var isCustomServiceOrder = (innerWidth >= 1500) && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services'); //= isAddEmptyBoxes 52696 52697 if (true || !UTIL.isEmpty(staffId)) { 52698 _conPos.filterServiceBoxesByStaff(staffId); 52699 return; 52700 } 52701 52702 if (_conPos.inventory_json.service_groups.length === 1) { // || _conPos.inventory_json.services.length <= _boxesPerPage 52703 var svc = _conPos.inventory_json.services; 52704 var boxtype = 's'; 52705 } else { 52706 var svc = _conPos.inventory_json.service_groups; 52707 var boxtype = 'sg'; 52708 } 52709 52710 for (var i=0; i < svc.length; i++) { 52711 if (isCustomServiceOrder) { 52712 currentOrder = _addEmptyBoxes(arr, svc[i], currentOrder, isEdit); 52713 } 52714 52715 arr.push(_getBox(boxtype, svc[i], isEdit)); 52716 ++currentOrder; 52717 } 52718 52719 _displayBoxes(arr); 52720 } 52721 52722 function _initBoxSortOrder(jcontainer) { 52723 if (innerWidth < 1500) { 52724 _conPos.Edit.openHelp(); 52725 return; 52726 } 52727 52728 var jwindow = jcontainer.find('#pos-product-window'); 52729 var jTableGrid = jwindow.find('#pos-window-grid'); 52730 52731 jwindow.find('.pos-product-box').draggable({ 52732 "snap": true, "snapTolerance": 50, "snapMode": "outer" 52733 , "grid": [124,122], "containment": jwindow 52734 , "containment": jTableGrid 52735 , handle: '.pos-box-drag' 52736 //, items: '.pos-product-box' 52737 //, cancel: 'div' 52738 52739 /* 52740 , start: function(event, ui) { 52741 var jtd = $(ui.helper).parent(); 52742 var isRevert = (jtd.find('.pos-product-box').length > 1); 52743 52744 var jbox = $(this); 52745 jbox.draggable('option', 'revert', isRevert); 52746 } 52747 52748 , stop: function (event, ui) { 52749 var jbox = $(this); 52750 var jtd = $(ui.helper).parent(); 52751 var isRevert = (jtd.find('.pos-product-box').length > 1); 52752 var newOrder = jtd.attr('order_sr'); 52753 52754 if (!jbox.draggable('option', 'revert')) { 52755 var sgid = jbox.attr('service_group_id'); 52756 var svcid = jbox.attr('service_id'); 52757 52758 //toDo: Update DB 52759 jbox.attr('order_sr', newOrder); 52760 } 52761 } 52762 */ 52763 }); 52764 52765 _initBoxDroppable(jwindow); 52766 //jwindow.find('.pos-product-box-empty').disableSelection(); 52767 } 52768 function _initBoxDroppable(jwindow) { 52769 jwindow.find('td').droppable({ 52770 classes: { 52771 "ui-droppable-active": "ui-state-active", 52772 "ui-droppable-hover": "ui-state-hover" 52773 }, 52774 /* accept: function(jDragBox) { 52775 if (jDragBox.hasClass('pos-product-box')) { 52776 var jtd = $(this); 52777 var jDropBox = jtd.find('.pos-product-box'); //box already in new box (i.e. box currently in dropable) 52778 var sgidDragBox = jDropBox.attr('service_group_id'), svcidDragBox = UTIL.coalesceInt(jDropBox.attr('service_id')); 52779 var thisOrder = jtd.attr('order_sr'), dragOrder = jDragBox.parent().attr('order_sr'); 52780 52781 if (jDropBox.length > 0 && thisOrder != dragOrder) { 52782 return false; 52783 } else { 52784 return true; 52785 } 52786 } else { 52787 return false; 52788 } 52789 }, */ 52790 drop: function(event, ui) { 52791 var tdNew = $(this); //.addClass("ui-state-highlight"); 52792 var jbox = $(ui.draggable); 52793 var tdOld = jbox.parent(); 52794 52795 var newOrder = tdNew.attr('order_sr'), oldOrder = tdOld.attr('order_sr'); 52796 var duplicateSGID = null, duplicateSvcId = null; 52797 52798 if (newOrder != oldOrder) { //= box actually moved 52799 if (tdNew.find('.pos-product-box').length) { 52800 var jDuplicateBox = tdNew.find('.pos-product-box'); 52801 52802 jDuplicateBox.appendTo(tdOld); 52803 jDuplicateBox.css({ "inset": "" }); 52804 jDuplicateBox.attr('order_sr', oldOrder); 52805 duplicateSGID = jDuplicateBox.attr('service_group_id'), duplicateSvcId = jDuplicateBox.attr('service_id'); 52806 } 52807 52808 jbox.appendTo(tdNew); 52809 jbox.css({ "inset": "" }); 52810 jbox.attr('order_sr', newOrder); 52811 var sgid = jbox.attr('service_group_id'), svcid = jbox.attr('service_id'); 52812 52813 //Update DB 52814 if (!UTIL.isEmpty(svcid)) { 52815 SA.POS.getServiceObject(svcid).order = newOrder; //SA.POS.inventory_json.service_groups[8].order 52816 _updateServiceOrder(sgid, svcid, newOrder); 52817 52818 if (!UTIL.isEmpty(duplicateSvcId)) { 52819 SA.POS.getServiceObject(duplicateSvcId).order = oldOrder; 52820 _updateServiceOrder(duplicateSGID, duplicateSvcId, oldOrder) 52821 } 52822 } else { 52823 SA.POS.getServiceGroupObject(sgid).order = newOrder; 52824 _updateServiceGroupOrder(); 52825 } 52826 } 52827 } 52828 }); 52829 } 52830 52831 function _updateServiceOrder(sgid, svcid, order) { 52832 var url = GLO.Link.Object.Provider.Ajax + 'ServiceOrder'; 52833
52834 $.ajax({ type: "POST", url: url, "cache": false, data: { "service": svcid, "servicegroup": sgid, "order": order } }); 52835 //.success(function(data, textStatus, jqXHR) { }) 52836 //.error(function(jqXHR, textStatus, errorThrown) { }); 52837 } 52838 function _updateServiceGroupOrder() { 52839 var xml = '', h4 = $('#pos-product-window').find('.pos-product-box'); 52840 52841 for (var i=0; i < h4.length; i++) { 52842 xml += '<h4 service_group_id="' + h4.eq(i).attr('service_group_id') + '" order_sr="' + h4.eq(i).attr('order_sr') + '"/>'; 52843 } 52844 52845 xml = UTIL.htmlEncode('<div>' + xml + '</div>'); 52846 var url = GLO.Link.Object.Provider.Ajax + 'ServiceGroupOrder'; 52847 52848 $.ajax({ type: "POST", url: url, "cache": false, data: { "service_group_xml": xml } }); 52849 //.success(function(data, textStatus, jqXHR) { }) 52850 //.error(function(jqXHR, textStatus, errorThrown) { }); 52851 } 52852 52853 function _getBoxesHtm(arrBoxes) { 52854 if (arrBoxes.length > _boxesPerPage) { //requires more button. 52855 var htm = ''; 52856 52857 for (var i=0; i < (_boxesPerPage - 1); i++) { 52858 htm += arrBoxes[i]; 52859 } 52860 52861 var arrowRight = '<i class="fa fa-arrow-right fa-4x"></i> <i class="fa fa-arrow-circle-o-right fa-5x"></i> <i class="fa fa-arrow-circle-right fa-5x"></i>'; 52862 htm += '<div id="pos-box-next" box_type="n" next_item_nr="' + (_boxesPerPage - 1) + '" class="pos-product-box"><div>' + arrowRight + '</div></div>'; 52863 } else { 52864 var htm = arrBoxes.join(''); 52865 } 52866 52867 return htm; 52868 } 52869 function _displayBoxes(arrBoxes, grand, parent, isSystemReset) { 52870 _conPos.boxArray = arrBoxes; 52871 52872 var jcontainer = $('#pos-container'); 52873 var jwindow = $('#pos-product-window'); 52874 var isEditServices = jcontainer.hasClass('edit-pos') && jcontainer.hasClass('services'); 52875 52876 jcontainer.find('#pos-service-group-list').find('.pos-type-list.selected-service-group').removeClass('selected-service-group'); 52877 52878 _addBoxesToScreen(jcontainer, jwindow, arrBoxes, isEditServices); 52879 _displayEnterProductHeader(grand, parent, isSystemReset); 52880 _conPos.Edit.displayForIsEdit(grand, parent); 52881 } 52882 function _addBoxesToScreen(jcontainer, jwindow, arrBoxes, isEditServices) { 52883 var isCustomServiceOrder = (innerWidth >= 1500 && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services')); 52884 52885 if (isEditServices && isCustomServiceOrder && arrBoxes.length <= _boxesPerPage) { 52886 _addBoxesToScreenGrid(jwindow, arrBoxes); 52887 } else { 52888 var htm = _getBoxesHtm(arrBoxes); 52889 jwindow.html(htm); 52890 } 52891 52892 if (isEditServices) { 52893 _initBoxSortOrder(jcontainer); 52894 } 52895 52896 jwindow.find('.pos-product-box').click(SA.POS.clickBox); //GLO.UI.setClick(jwindow, '.pos-product-box', SA.POS.clickBox); 52897 } 52898 function _addBoxesToScreenGrid(jwindow, arrBoxes) { 52899 var tbl = '<table id="pos-window-grid">'; 52900 var cellsPerRow = 8; 52901 var htmDragText = '<div class="pos-box-drag-text"><i>Drag Service</i> <i>Box Here</i></div>'; 52902 52903 for (var i=0; i < 56; i++) { 52904 if (i % cellsPerRow == 0) { 52905 tbl += '<tr row_order_sr="' + parseInt(i/cellsPerRow + 1) + '">'; 52906 } 52907 52908 tbl += '<td order_sr="' + (i + 1) + '">' + htmDragText + '</td>'; 52909 52910 if (i % cellsPerRow === 7) { 52911 tbl += '</tr>'; 52912 } 52913 } 52914 52915 tbl += '</table>'; 52916 var jgrid = jwindow.html(tbl); 52917 var jtds = jgrid.find('td'); 52918 52919 for (var b=0; b < arrBoxes.length; b++) { 52920 var jbox = $(arrBoxes[b]) 52921 var index = parseInt(jbox.attr('order_sr')) - 1; 52922 52923 if (!jbox.hasClass('pos-product-box-empty')) { 52924 jtds.eq(index).html(arrBoxes[b]); 52925 } 52926 } 52927 } 52928 52929 function _getBox(boxtype, jsonItem, isEditPos) { 52930 var css = '', innerStyle = '', innerClass = '', cssClass = '', cornerCnt = '', bottomCorner = '', div = '<div box_type="' + boxtype + '" '; 52931 52932 if (jsonItem["background-color"]) { 52933 css = "background-color: rgba(" + jsonItem["background-color"] + ", 1);"; 52934 52935 if (jsonItem["background-color"] !== '255,255,255') { 52936 innerClass = ' class="has-back-color"'; 52937 } 52938 } 52939 52940 if (jsonItem.color) { 52941 var colorStyle = 'color: rgb(' + jsonItem.color + ');'; 52942 css += colorStyle; 52943 innerStyle += colorStyle; 52944 } 52945 52946 if (jsonItem.image_vc && (_conPos.inventory_json.use_service_image_fl || !_isDisplayServices())) { 52947 css += "background-image: url('" + GLO.Data.cdnDirectory + "upload-folder/" + jsonItem.image_vc + "');"; 52948 innerClass = ' class="has-back-img"'; 52949 } 52950 52951 if (jsonItem.css_class_vc) { var cssClass = ' ' + jsonItem.css_class_vc; } 52952 52953 if (boxtype === 's') { 52954 div += 'service_id="' + UTIL.cleanString(jsonItem.id) + '" service_group_id="' + UTIL.cleanString(jsonItem.service_group_id) + '" order_sr="' + jsonItem.order + '" '; 52955 cornerCnt = _getPriceSquare(jsonItem.price_mn); 52956 } else if (boxtype === 'sg') { 52957 div += 'service_group_id="' + UTIL.cleanString(jsonItem.id) + '" order_sr="' + jsonItem.order + '" '; 52958 cornerCnt = _getProductCountSquare(jsonItem.service_count); 52959 } else if (boxtype === 'i') { 52960 div += _getProductAttributes(jsonItem.id, jsonItem.product_line_id, jsonItem.vendor_id, jsonItem.inventory_type_id, jsonItem.category_id); 52961 cornerCnt = _getPriceSquare(jsonItem.price_mn); 52962 bottomCorner = _getProductSize(jsonItem); 52963 } else if (boxtype === 'pl') { 52964 div += _getProductAttributes(null, jsonItem.id, jsonItem.vendor_id); 52965 cornerCnt = _getProductCountSquare(jsonItem.product_count); 52966 } else if (boxtype === 'v') { 52967 div += _getProductAttributes(null, null, jsonItem.id); 52968 cornerCnt = _getProductCountSquare(jsonItem.total_product_count); 52969 } else if (boxtype === 'ct') { 52970 div += _getProductAttributes(null, null, null, jsonItem.id, jsonItem.category_id); 52971 cornerCnt = _getProductCountSquare(jsonItem.product_count); 52972 } else if (boxtype === 'c') { 52973 div += _getProductAttributes(null, null, null, null, jsonItem.id); 52974 cornerCnt = _getProductCountSquare(jsonItem.total_product_count); 52975 } 52976 52977 var htmDragHandle = _getBoxDragHandle(isEditPos && (boxtype == 's' || boxtype == 'sg')); 52978 var divInner = '<div' + innerClass + ' style="' + innerStyle + '">' + UTIL.coalesce(jsonItem.label, jsonItem.name) + '</div>'; 52979 return div + 'class="pos-product-box' + cssClass + '" style="' + css + '">' + htmDragHandle + cornerCnt + divInner + bottomCorner + '</div>'; 52980 } 52981 function _getProductAttributes(inventoryId, productLineId, vendorId, typeId, categoryId) { 52982 var xml = ''; 52983 52984 if (!UTIL.isEmpty(inventoryId)) { 52985 xml += 'inventory_id="' + inventoryId + '" '; 52986 } 52987 52988 if (!UTIL.isEmpty(productLineId)) { 52989 xml += 'product_line_id="' + productLineId + '" '; 52990 } 52991 52992 if (!UTIL.isEmpty(vendorId)) {
52993 xml += 'vendor_id="' + vendorId + '" '; 52994 } 52995 52996 if (!UTIL.isEmpty(typeId)) { 52997 xml += 'inventory_type_id="' + typeId + '" '; 52998 } 52999 53000 if (!UTIL.isEmpty(categoryId)) { 53001 xml += 'category_id="' + categoryId + '" '; 53002 } 53003 53004 return xml; 53005 } 53006 53007 function _getProductSize(jsonItem) { 53008 if (!UTIL.isEmpty(jsonItem.size_vc)) { 53009 var size = jsonItem.size_vc; 53010 53011 if (!UTIL.isEmpty(jsonItem.unit_abbreviation_vc)) { 53012 size += ' ' + jsonItem.unit_abbreviation_vc; 53013 } 53014 53015 return '<span class="product-size">' + size + '</span>'; 53016 } else { 53017 return ''; 53018 } 53019 } 53020 function _getPriceSquare(price) { 53021 if (UTIL.coalesceMoney(price) > 0) { 53022 var dsign = '<span class="dollar-sign">$</span>'; 53023 return '<span class="product-price">' + dsign + UTIL.displayMoney(price, true, false, true) + '</span>'; 53024 } else { 53025 return ''; 53026 } 53027 } 53028 function _getProductCountSquare(productCnt) { 53029 return '<span class="product-count">' + productCnt + '</span>'; 53030 } 53031 53032 function _applyPackage(jbox) { 53033 var inventoryId = jbox.attr('inventory_id'), typeId = UTIL.cleanString(jbox.attr('inventory_type_id')), categoryId = UTIL.cleanString(jbox.attr('category_id')); 53034 var vendorId = UTIL.cleanString(jbox.attr('vendor_id')); 53035 var price = UTIL.directTagOnly(jbox.find('.product-price')); 53036 53037 UserPortal.Price.Package.apply(null, inventoryId, typeId, categoryId, vendorId, price); 53038 } 53039 53040 function _setServiceGroupList(staffId) { 53041 var jsg = $('#ServiceGroupOptionsClone'); 53042 var sgList = ''; 53043 var boxes = SA.POS.inventory_json.service_groups; 53044 53045 for (var i=0; i < boxes.length; i++) { 53046 sgid = boxes[i].id; 53047 53048 if (UTIL.isEmpty(staffId) || jsg.find('option[value="' + sgid + '"]').attr('staff_ids').split(',').has(staffId)) { 53049 var sgName = boxes[i].name; 53050 var bgcolor = 'rgba(' + boxes[i]["background-color"] + ', 1)'; 53051 var style = ' style="background-color: ' + bgcolor + '"'; 53052 var cssTextClass = 'line-count-' + (parseInt(sgName.length / 13) + 1) + ' character-count-' + sgName.length; 53053 var cssClass = ' class="pos-type-list ' + cssTextClass + '"'; //UTIL.cleanString(boxes[i].css_class_vc) 53054 var onclick = ' onclick="SA.POS.selectServiceGroup(this)"'; 53055 53056 sgList += '<div service_group_id="' + sgid + '"' + cssClass + onclick + style + '>' + sgName + '</div>'; 53057 } 53058 } 53059 53060 $('#pos-service-group-list').html(sgList); 53061 } 53062 53063 _conPos.selectServiceGroup = function(element) { 53064 var jsg = $(element); 53065 var sgid = jsg.attr('service_group_id'); 53066 _conPos.filterBoxesServiceGroup(sgid); 53067 } 53068 53069 _conPos.addProductRowToTicket = function(inventoryId, jbox, jbarcode) { 53070 SA.Ticket.addProductLine(inventoryId); 53071 53072 if (jbox) { 53073 _applyPackage(jbox); 53074 } else { 53075 var typeId = jbarcode.attr('type_id'), categoryId = jbarcode.attr('category_id'), vendorId = jbarcode.attr('vendor_id'), price = jbarcode.attr('price_mn'); 53076 UserPortal.Price.Package.apply(null, inventoryId, typeId, categoryId, vendorId, price); 53077 } 53078 53079 SA.Ticket.ticketChanged(); 53080 } 53081 53082 _conPos.clickBox = function() { 53083 var jbox = $(this); 53084 var boxtype = jbox.attr('box_type'); 53085 var isEditPos = $('#pos-container').hasClass('edit-pos'); 53086 53087 if (boxtype === 'sg') { 53088 var sgid = jbox.attr('service_group_id'); 53089 53090 if (isEditPos) { 53091 _conPos.Edit.openServiceGroup(jbox, sgid); 53092 } else { 53093 _conPos.filterBoxesServiceGroup(sgid, isEditPos); 53094 } 53095 } else if (boxtype === 's') { 53096 var serviceId = jbox.attr('service_id'), sgid = jbox.attr('service_group_id'); 53097 53098 if (isEditPos) { 53099 _conPos.Edit.openService(jbox, serviceId); 53100 //return GLO.Popup.Info.open('_conPos.clickBox: Edit POS Services will be enabled in March 2021', 'Edit POS'); //toDo: Edit Services 53101 } else { 53102 SA.Ticket.addServiceLine(serviceId, sgid); 53103 SA.Ticket.ticketChanged(); 53104 } 53105 } else if (boxtype === 'i') { 53106 var inventoryId = jbox.attr('inventory_id'); 53107 53108 if (isEditPos) { 53109 _conPos.Edit.openProduct(jbox, inventoryId); 53110 } else { 53111 _conPos.addProductRowToTicket(inventoryId, jbox); 53112 } 53113 } else if (boxtype === 'pl') { 53114 var productLineId = jbox.attr('product_line_id'); 53115 _conPos.filterBoxesProductLine(productLineId, isEditPos); 53116 53117 if (isEditPos) { _conPos.Edit.openBrandOrPLine(jbox, true); } //_conPos.Edit.moveBoxForEdit(jbox); 53118 } else if (boxtype === 'v') { 53119 if (isEditPos) { _conPos.Edit.openBrandOrPLine(jbox); } 53120 53121 var vid = jbox.attr('vendor_id'); 53122 _conPos.filterBoxesVendor(vid, isEditPos); 53123 } else if (boxtype === 'ct') { 53124 var id = jbox.attr('inventory_type_id'); //category_type_id 53125 _conPos.filterBoxesCategoryType(id, isEditPos); 53126 53127 if (isEditPos) { _conPos.Edit.openCategoryOrType(jbox, true); } 53128 } else if (boxtype === 'c') { 53129 var id = jbox.attr('category_id'); 53130 _conPos.filterBoxesCategory(id, isEditPos); 53131 53132 if (isEditPos) { _conPos.Edit.openCategoryOrType(jbox); } 53133 } else if (boxtype === 'p' || boxtype === 'n') { 53134 var start = jbox.attr('next_item_nr'); 53135 _displayMore(start); 53136 } 53137 } 53138 53139 _conPos.addTicketRowComplete = function() { 53140 $('#pos-product-header-enter #pos-enter-product-or-amount').val(''); 53141 $('#pos-product-header-enter .btnAction2').addClass('hide'); 53142 } 53143 53144 function _displayMore(startItem) { 53145 startItem = parseInt(startItem); 53146 var boxCnt = (_boxesPerPage - 2); 53147 53148 if (startItem > 0) { //is more/next. 53149 var prevItem = startItem - boxCnt; 53150 if (startItem < _boxesPerPage) { --prevItem; } //=prev screen will still have "prev" button. 53151 53152 var arrowLeft = '<i class="fa fa-arrow-left fa-4x"></i> <i class="fa fa-arrow-circle-o-left fa-5x"></i> <i class="fa fa-arrow-circle-left fa-5x"></i>'; 53153 var htm = '<div id="pos-box-prev" box_type="p" next_item_nr="' + prevItem + '" class="pos-product-box"><div>' + arrowLeft + '</div></div>'; 53154 } else { //is prev. 53155 startItem = 0; 53156 boxCnt = (_boxesPerPage - 1); 53157 var htm = ''; 53158 } 53159 53160 for (var i = startItem; i < startItem + boxCnt; i++) { 53161 if (_conPos.boxArray.length === i) { break; } 53162 htm += _conPos.boxArray[i]; 53163 } 53164 53165 if (_conPos.boxArray.length - 1 == startItem + boxCnt) { 53166 htm += _conPos.boxArray[startItem + boxCnt]; 53167 } else if (_conPos.boxArray.length > startItem + boxCnt) { 53168 var arrowRight = '<i class="fa fa-arrow-right fa-4x"></i> <i class="fa fa-arrow-circle-o-right fa-5x"></i> <i class="fa fa-arrow-circle-right fa-5x"></i>'; 53169 htm += '<div id="pos-box-next" box_type="n" next_item_nr="' + (startItem + boxCnt) + '" class="pos-product-box"><div>' + arrowRight + '</div></div>'; 53170 } 53171 53172 var jwindow = $('#pos-product-window'); 53173 jwindow.html(htm); 53174 jwindow.find('.pos-product-box').click(SA.POS.clickBox); //GLO.UI.setClick(jwindow, '.pos-product-box', SA.POS.clickBox); 53175 } 53176 53177 function _getGrandBreadCrumb(grand, jbreadcrumb) { 53178 var isEdit = $('#pos-container').hasClass('edit-pos'); 53179 53180 if (_isDisplayServices()) { 53181 jbreadcrumb.attr('service_group_id', grand.id); 53182 return ' id="pos-breadcrumb-sg" service_group_id="' + grand.id + '" onclick="SA.POS.filterBoxesServiceGroup(' + grand.id + ', ' + isEdit + ', true)"'; 53183 } else if (_conPos.sortType === 2) { 53184 jbreadcrumb.attr('vendor_id', grand.id); 53185 return ' id="pos-breadcrumb-vendor" vendor_id="' + grand.id + '" onclick="SA.POS.filterBoxesVendor(' + grand.id + ', ' + isEdit + ', true)"'; 53186 } else { 53187 jbreadcrumb.attr('category_id', grand.id); 53188 return ' id="pos-breadcrumb-category" category_id="' + grand.id + '" onclick="SA.POS.filterBoxesCategory(' + grand.id + ', ' + isEdit + ', true)"'; 53189 } 53190 } 53191 53192 function _getParentBreadCrumb(parent, jbreadcrumb) { 53193 var isEdit = $('#pos-container').hasClass('edit-pos'); 53194 53195 if (_isDisplayServices()) { 53196 return GLO.Popup.Warning.open('Services Have No Parent (only Grand)', 'Get Parent Breadcrumb'); 53197 53198 //jbreadcrumb.attr('service_group_id', parent.id); 53199 //return ' id="pos-breadcrumb-sg" service_group_id="' + parent.id + '" onclick="SA.POS.filterBoxesServiceGroup(' + parent.id + ')"'; 53200 } else if (_conPos.sortType === 2) { 53201 jbreadcrumb.attr('product_line_id', parent.id); 53202 return ' id="pos-breadcrumb-pline" product_line_id="' + parent.id + '" onclick="SA.POS.filterBoxesProductLine(' + parent.id + ', ' + isEdit + ', true)"'; 53203 } else { 53204 jbreadcrumb.attr('inventory_type_id', parent.id); 53205 return ' id="pos-breadcrumb-category-type" inventory_type_id="' + parent.id + '" onclick="SA.POS.filterBoxesCategoryType(' + parent.id + ', ' + isEdit + ', true)"'; 53206 } 53207 } 53208 53209 function _getAddParentBreadCrumb(arrow) { 53210 var isEdit = $('#pos-container').hasClass('edit-pos'); 53211 53212 if (_isDisplayServices()) { 53213 return ''; //return GLO.Popup.Warning.open('Services Have No Parent (only Grand)', 'Get Add Parent Breadcrumb'); 53214 } else if (_conPos.sortType === 2) { 53215 return arrow + '<span id="pos-product-header-add-pline" onclick="SA.POS.Edit.openNewPLine()"><i class="fa fa-plus"></i> <span>' + SA.Resource.Add.toLowerCase() + ' <b>' + SA.Resource.Product.toLowerCase() + ' </b>' + SA.Resource.Line.toLowerCase() + '</span> </span>'; 53216 } else { 53217 return arrow + '<span id="pos-product-header-add-category-type" onclick="SA.POS.Edit.openNewCategoryType()"><i class="fa fa-plus"></i> <span>' + SA.Resource.AddType.toLowerCase() + '</span> </span>'; 53218 } 53219 } 53220 53221 function _displayEnterProductHeader(grand, parent, isSystemReset) { 53222 var jinput = $('#pos-product-header-enter'); 53223 var jbreadcrumb = $('#pos-product-header-breadcrumb'); 53224 var jpos = $('#pos-container'); 53225 jbreadcrumb.removeAttr('vendor_id').removeAttr('category_id').removeAttr('product_line_id').removeAttr('inventory_type_id').removeAttr('service_group_id'); 53226 53227 if (!UTIL.isEmptyObject(grand)) { 53228 var arrow = '<b class="breadcrumb-spacer">➜</b>'; 53229 var htm = '<span id="btnPosHome" class="btnAdd"><a id="pos-breadcrumb-home" onclick="SA.POS.filterBoxesHome()">' + SA.Resource.Home + '</a></span>' + arrow 53230 var pnm = '', gnm = grand.name; 53231 var attribute = _getGrandBreadCrumb(grand, jbreadcrumb); 53232 53233 if (!UTIL.isEmptyObject(parent)) { 53234 var isEditPos = $('#pos-container').hasClass('edit-pos'); 53235 53236 if (!isEditPos && grand.type_count + grand.product_count === 1) { //= grand only contains parent so header only needs to contain grand. 53237 parent = null; 53238 } else { 53239 pnm = parent.name; 53240 } 53241 } 53242 53243 if ( (gnm.length > 20 && UTIL.cleanString(pnm).length > 10) || (gnm.length > 20 && UTIL.cleanString(pnm).length > 5) ) { 53244 htm += UTIL.maxStringHtml(gnm, 15, false, 'a', '', '', attribute); 53245 } else if (gnm.length > 15 && UTIL.cleanString(pnm).length > 15) { 53246 htm += UTIL.maxStringHtml(gnm, 12, false, 'a', '', '', attribute); 53247 } else { 53248 htm += UTIL.maxStringHtml(gnm, 30, false, 'a', '', '', attribute); 53249 } 53250 53251 if (!UTIL.isEmptyObject(parent)) { 53252 attribute = _getParentBreadCrumb(parent, jbreadcrumb); 53253 53254 if (pnm.length > 20 && gnm.length > 15) { 53255 htm += arrow + UTIL.maxStringHtml(pnm, 15, false, 'a', '', '', attribute); 53256 } else if (pnm.length > 15 && gnm.length > 5) { 53257 htm += arrow + UTIL.maxStringHtml(pnm, 15, false, 'a', '', '', attribute); 53258 } else { 53259 htm += arrow + UTIL.maxStringHtml(pnm, 20, false, 'a', '', '', attribute); 53260 } 53261 } else if ($('#pos-container').hasClass('edit-pos') && !_isDisplayServices()) { 53262 htm += _getAddParentBreadCrumb(arrow); 53263 } 53264 53265 jpos.addClass('has-breadcrumb'); 53266 jinput.addClass('hide'); 53267 jbreadcrumb.html(htm).removeClass('hide'); 53268 } else if (jinput.hasClass('hide')) { 53269 var fnSetBreadcrumb = function() { 53270 jbreadcrumb.html('').addClass('hide'); 53271 jinput.removeClass('hide'); 53272 jpos.removeClass('has-breadcrumb'); 53273 }; 53274 53275 if (isSystemReset) { 53276 fnSetBreadcrumb(); 53277 } else { 53278 var timeout = 10; 53279 if (GLO.Info.isMobile(true)) { timeout = 400; } //= avoids user accidentally putting focus on 'Enter Product or Price' input field. 53280 53281 setTimeout(function() { 53282 fnSetBreadcrumb(); 53283 }, timeout); 53284 } 53285 } 53286 } 53287 53288 _conPos.toggleMenu = function(isClose) { 53289 var j = $('#pos-container'); 53290 53291 if (j.hasClass('edit-pos')) { _conPos.Edit.changeMode(); } 53292 53293 var jmenu = j.find('#pos-portal-menu'); 53294 var jpos = j.find('#pos'); 53295 53296 if (isClose || jmenu.is(':visible')) { 53297 _conPos.closeMenu(jpos, jmenu); 53298 } else { 53299 _conPos.openMenu(jpos, jmenu); 53300 } 53301 } 53302 53303 _conPos.openMenu = function(jpos, jmenu) { 53304 jpos.addClass('compress'); //toDo: add animation. 53305 jmenu.removeClass('hide'); //.parent().removeClass('hide'); //toDo: add animation. 53306 53307 $('#pos-action-menu:visible').addClass('hide'); //toDo: add animation (if exists). 53308 53309 $('#pos-action-menu-button').removeClass('menu-open'); 53310 $('#pos-menu-button').addClass('menu-open'); 53311 } 53312 53313 _conPos.closeMenu = function(jpos, jmenu) { 53314 jmenu.addClass('hide'); //.parent().addClass('hide'); //toDo: add animation. 53315 jpos.removeClass('compress'); //toDo: add animation. 53316 53317 $('#pos-menu-button').removeClass('menu-open'); 53318 } 53319 53320 _conPos.toggleActionMenu = function(isClose) { 53321 var j = $('#pos-container'); 53322 53323 if (j.hasClass('edit-pos')) { _conPos.Edit.changeMode(); } 53324 53325 var jmenu = j.find('#pos-action-menu'); 53326 var jpos = j.find('#pos'); 53327 53328 if (isClose || jmenu.is(':visible')) { 53329 _conPos.closeActionMenu(jpos, jmenu); 53330 } else { 53331 _conPos.openActionMenu(jpos, jmenu); 53332 } 53333 } 53334 53335 _conPos.openActionMenu = function(jpos, jmenu) { 53336 jpos.addClass('compress'); //toDo: add animation. 53337 jmenu.removeClass('hide'); //.parent().removeClass('hide'); //toDo: add animation. 53338 53339 $('#pos-portal-menu:visible').addClass('hide'); //toDo: add animation (if exists). 53340 53341 $('#pos-menu-button').removeClass('menu-open'); 53342 $('#pos-action-menu-button').addClass('menu-open'); 53343 } 53344 53345 _conPos.closeActionMenu = function(jpos, jmenu) { 53346 jmenu.addClass('hide'); //.parent().addClass('hide'); //toDo: add animation. 53347 jpos.removeClass('compress'); //toDo: add animation. 53348 53349 $('#pos-action-menu-button').removeClass('menu-open'); 53350 } 53351 53352 _conPos.logout = function() { 53353 var sname = GLO.Info.getStaffName(); 53354 53355 var fn = function() { 53356 document.location = GLO.Link.Page.LoginHome + 'logout'; 53357 } 53358 53359 new GLO.Popup.Confirm(SA.Resource.LogoutConfirm + ' ' + sname + '?', fn
53359); 53360 } 53361 53362 _conPos.searchKeyUp = function(element) { 53363 if (UTIL.isNumber(element.value)) { 53364 $("#pos-product-header-enter").addClass('is-numeric'); 53365 } else { 53366 $("#pos-product-header-enter").removeClass('is-numeric'); 53367 } 53368 } 53369 53370 _conPos.openStaffPreview = function(staffBox) { 53371 var ajaxRequest, jbox = $(staffBox); 53372 var sid = jbox.attr('staff_id'), isFA = UTIL.parseBool(jbox.attr('is_first_available_fl')); 53373 var sname = jbox.find('.pos-staff-name').text(); 53374 var thumb = jbox.find('.staff-thumbnail'); 53375 53376 var htmPreview = '<div id="pop-preview-staff"><p style="letter-spacing: 1px; font-weight: bold; font-size: 20px;">Looking up Tickets for ' + sname + '...</p></div>'; 53377 var url = GLO.Link.WebsiteDomain + 'pos/StaffPreview?cdn=' + GLO.Data.cdnVersion + '&staff=' + sid; 53378 53379 function fnCancelOpenTicket() { 53380 if (ajaxRequest && ajaxRequest.abort) { 53381 ajaxRequest.abort(); 53382 } 53383 53384 if (oj && oj.close) { 53385 oj.close(); 53386 } 53387 } 53388 53389 var oj = new GLO.Popup.Processing.open(htmPreview, sname, fnCancelOpenTicket); 53390 var jpop = oj.getPopup(); 53391 jpop.find('.btnOk').addClass('btnAdd').attr('id', 'btnNewTicketQuick').find('>a').text('New Ticket').css({ "font-size": "20px" }); 53392 53393 ajaxRequest = $.ajax({ type: "GET", url: url, "cache": false }) 53394 .success(function(data, textStatus, jqXHR) { 53395 if ($(data).hasClass('warning')) { 53396 if (UTIL.parseBool($(data).attr('must_refresh'))) { 53397 setTimeout(function() { 53398 location.reload(); 53399 }, 450); 53400 } 53401 53402 new GLO.Popup.Warning(data); 53403 return true; 53404 } else if (oj.close()) { 53405 _staffPreviewHtm(sid, sname, isFA, thumb, data); 53406 } 53407 }).error(function(jqXHR, textStatus, errorThrown) { 53408 if (textStatus == 'abort' && event && event.currentTarget && event.currentTarget.id == 'btnNewTicketQuick') { 53409 if (oj && oj.close) { 53410 oj.close(); 53411 } 53412 53413 SA.Ticket.newTicket(sid, sname, isFA); 53414 } 53415 }); 53416 } 53417 function _getClockInIcon(staffId, isFA) { 53418 if (!isFA && $('#header-main-row-clock-out #clock-out-icon').length) { 53419 return '<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.pickStaff(' + staffId + ')" title="Clock-In/Out"> <a style="color: rgb(255, 255, 255);"></a> </span>'; 53420 } 53421 } 53422 53423 _conPos.helpQuickGuideMore = function() { 53424 var jpop = $('#pop-help-pos-screen-quick-guide').closest('.glopop'); 53425 jpop.find('.hide-detail').removeClass('hide-detail'); 53426 jpop.find('#help-pos-screen-more').remove(); 53427 } 53428 _conPos.openHelpQuickGuide = function(scrollTo) { 53429 var arrow = '<b class="arrow-right" style="padding: 0 4px;">➜</b>'; 53430 var screen = '<b class="narrow-text" style="color: #4F81BD;">POS Screen</b>'; 53431 var card = '<b class="narrow-text" style="color: #4F81BD;">Staff Card</b>'; 53432 var day = '<b class="narrow-text" style="color: #4F81BD;">Staff Summary popup</b>'; 53433 var panel = '<b class="narrow-text" style="color: #4F81BD;">Ticket Panel</b>'; 53434 var bar = '<b class="narrow-text" style="color: #4F81BD;">Ticket Status Bar</b>'; 53435 53436 var htmScreen = _getPosScreenHelp(arrow, screen, card, day, panel, bar); 53437 var htmStaffCards = _getStaffCardHelp(arrow, screen, card, day, panel, bar); 53438 var htmStaffOverview = _getStaffPopupHelp(arrow, screen, card, day, panel, bar); 53439 53440 var htmPanel = _getPosClientPanelHelp(arrow, screen, card, day, panel, bar); 53441 var htmTicket = _getTicketHelp(arrow, screen, card, day, panel, bar); 53442 var htmColors = _getColorHelp(arrow, screen, card, day, panel, bar); 53443 53444 var htm = '<div id="pop-help-pos-screen-quick-guide">' + htmScreen + htmStaffCards + htmStaffOverview + htmPanel + htmTicket + htmColors + '</div>'; 53445 var jpop = GLO.Popup.Custom.openSimple(htm, 'POS Screen Overview', null, null, null, 'wide-screen-guide').addClass('pop-pos'); 53446 GLO.Popup.Custom.singleButton(jpop, 'Close'); 53447 53448 //if (scrollTo) { UI.highlight(jpop.find('#' + scrollTo)); } 53449 } 53450 function _getPosScreenHelp(arrow, screen, card, day, panel, bar) { 53451 var tina = '<i class="narrow-text">Tina</i>', eartha = '<i class="narrow-text">Eartha</i>'; 53452 var chloe = '<i class="narrow-text">Chloe</i>', ashley = '<i class="narrow-text">Ashley</i>'; 53453 var bart = '<i class="narrow-text">Bartholomew</i>', sara = '<i class="narrow-text">Sara</i>'; 53454 53455 var liAlways = '<li class="always-display">'; 53456 var bNarrow = '<b class="narrow-text" style="color: #4F81BD;">'; 53457 53458 var bSignIn = '<b class="narrow-text" style="background-color: deeppink; color: white;">Signed-In</b>'; 53459 var bNowTag = '<b class="narrow-text" style="color: white; background: linear-gradient(rgba(120, 0,200, .1), rgba(120, 0,200, .8)), linear-gradient(black, black);">'; 53460 var bNow1 = bNowTag + 'Now</b>'; 53461 var bNow2 = bNowTag + 'Now <span style="color: inherit;">(or very soon)</span></b>'; 53462 var bCheckIn = '<b class="narrow-text" style="background-color: rgba(255, 255, 0, .4);">Checked-In</b>'; 53463 var bReady = '<b class="narrow-text" style="background-color: rgb(40, 180, 255);">Ready to Pay</b>'; 53464 var bCheckOut = '<b class="narrow-text" style="background-color: #9AFF9A;">Checked-Out</b>'; 53465 var bAvailable = '<b class="narrow-text" style="background-color: rgb(0,255,0);">AVAILABLE</b>'; 53466 var bLate = '<b class="narrow-text" style="background-color: rgb(220,220,220);">Late</b>'; 53467 var bUpcoming = '<b class="narrow-text" style="background-color: purple; color: white;">Upcoming</b>'; 53468 var bPast = '<b class="narrow-text" style="background-color: rgba(200,200,200, .6);">Past</b>'; 53469 var bNoShow = '<b class="narrow-text" style="background-color: rgb(255,0,0);">No Show</b>';
53470 var bLateCancel = '<b class="narrow-text" style="background-color: orange;">Late Cancel</b>'; 53471 53472 var cSignIn = '<li>At the top in pink is <i class="narrow-text">Serena Smith</i> who recently ' + bSignIn + '</li>'; 53473 var cNow = '<li><i class="narrow-text">Casa</i> + <i class="narrow-text">Silvia</i> who have an appointment ' + bNow2 + '</li>'; 53474 var cCheckIn = '<li><i class="narrow-text">Alana Cook</i> in yellow is currently ' + bCheckIn + '</li>'; 53475 var cReady = '<li>In blue <i class="narrow-text">Daniela</i> is ' + bCheckIn + ' and her ticket is ' + bReady + '</li>'; 53476 53477 var cLate = '<li><i class="narrow-text">Diana Mills</i> is 48 minutes ' + bLate + ' <span style="letter-spacing: 0;">(Diana might be a no-show)</span></li>'; 53478 var cUpcoming = '<li>In Purple are 4 ' + bUpcoming + ' appointments</li>'; 53479 var cPast = '<li><i class="narrow-text">Alice Moon</i> is a ' + bPast + ' appointment <span style="letter-spacing: 0; font-size: 90%;">(that was never <span>' + bCheckIn + ', ' + bCheckOut + ', or marked as ' + bNoShow + ')</li>'; 53480 var cCheckOut = '<li style="margin-bottom: 20px;">At the bottom of the ' + panel + ' are all the ' + bCheckOut + ' tickets in Green</li>'; 53481 var cNote = liAlways + panel + 'displays all tickets for current day <span>(except ' + bNoShow + ' + ' + bLateCancel + ' tickets)</span></li>'; 53482 var cAlways = liAlways + 'Press any' + bNarrow + 'Ticket Status bar</b> to open ticket</li>'; 53483 53484 var exampleDetail = '<i class="hide-detail">, in example image below:</i>'; 53485 var bCards = '<b class="pos-screen-quick-header">Staff Cards</b>'; 53486 53487 var msgCards1 = '<p style="margin-bottom: 0;">' + bCards + ' left-side of ' + screen + ' has each' + card + arrow + ' displaying staff\'s status' + exampleDetail + '</p>'; 53488 var msgCards2 = '<ul class="hide-detail" style="font-size: 110%;">' 53489 + '<li>' + tina + ' + ' + eartha + ' are ' + bAvailable + '</li>' 53490 + '<li>' + chloe + ' has an appointment ' + bNow1 + ' + ' + ashley + ' has an appointment starting ' + bNowTag + 'in 13 minutes</b></li>' 53491 + '<li>' + sara + ' client <b class="narrow-text" style="background-color: deeppink; color: white;">Signed-In 3 minutes ago</b></li>' 53492 + '<li>' + bart + ' ticket is estimated to <b class="narrow-text" style="background-color: rgba(255, 255, 0, .6);">end in 13 minutes</b></li>' 53493 + liAlways + 'Press a' + bNarrow + 'Staff Card</b> to open the' + bNarrow + 'Staff Summary popup</b></li>' 53494 + '</ul>'; 53495 53496 var bPanel = '<b class="pos-screen-quick-header">Ticket Panel</b>'; 53497 var msgPanel1 = '<p style="margin-bottom: 0;">' + bPanel + ' right-side of ' + screen + ' has ' + panel + arrow + 'displaying ' + bar + ' for each ticket</p>'; 53498 var msgPanelList = '<ul id="help-pos-screen-panel-list" class="hide-detail">' + cSignIn + cNow + cCheckIn + cReady + cLate + cUpcoming + cPast + cCheckOut + cNote + cAlways + '</ul>'; 53499 53500 var imgScreen = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/pos-screen2.png"/>'; 53501 imgScreen = '<div id="help-pos-screen-diagram">' + imgScreen + '</div>'; 53502 53503 var htmCards = '<div id="help-pos-screen-cards">' + msgCards1 + msgCards2 + '</div>'; 53504 var htmBars = '<div id="help-pos-screen-panel">' + msgPanel1 + msgPanelList + '</div>'; 53505 var btnMore = '<div id="help-pos-screen-more"> <span class="btnAdd"> <a onclick="SA.POS.helpQuickGuideMore()">More Info...</a> </span> </div>'; 53506 53507 return '<div id="help-pos-screen">' + htmCards + htmBars + btnMore + imgScreen + '</div>'; 53508 } 53509 function _getStaffCardHelp(arrow, screen, card, day, panel, bar) { 53510 var header = '<h3>POS Staff Cards</h3>'; 53511 var imgStaffCard = '<img id="pos-full-staff-card" src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/full-staff-card2.png"/>'; 53512 imgStaffCard = '<div id="help-staff-card-diagram">' + imgStaffCard + '</div>'; 53513 var msg1 = '<p style="margin-bottom: 0;">Each ' + card + ' displays</p>'; 53514 53515 //if the staff is estimated to complete the current checked-in ticket in less than one hour (based on service time) then it will display when the the ticket is expected to be completed, otherwise displays BUSY 53516 //Available - purple: has upcoming appointment, but has time to do another service before appointment | Available - greeen: no upcoming appointment 53517 53518 var bubbleSignIn = '<span class="staff-appt-count staff-appt-signin "><b class="staff-appt-signin-count" title="1 client self sign-in">1</b></span>'; 53519 var bubbleCheckIn = '<span class="staff-appt-count staff-appt-checkin"><b class="staff-appt-checkin-count" title="2 tickets checked-in">2</b></span>'; 53520 var bubbleCheckOut = '<span class="staff-appt-count staff-appt-checkout"><b class="staff-appt-checkout-count" title="3 tickets checked-out">3</b></span>'; 53521 53522 var bubbleNow = '<span class="staff-appt-count staff-appt-now"><b class="staff-appt-now-count" title="1 now appointment (starts within 20 minutes)">1</b></span>'; 53523 var bubbleUpcoming = '<span class="staff-appt-count staff-appt-upcoming"><b class="staff-appt-upcoming-count" title="4 upcoming appointments">4</b></span>'; 53524 var bubbleLate = '<span class="staff-appt-count staff-appt-late"><b class="staff-appt-late-count" title="1 late appointment (start time more than 20 minutes after current time, but less than 90 minutes)">1</b></span>'; 53525 53526 var bubbles = bubbleSignIn + ' ' + bubbleCheckIn + ' ' + bubbleCheckOut + ' ' + bubbleNow + ' ' + bubbleUpcoming + ' ' + bubbleLate; 53527 bubbles = '<div id="pos-staff-list"> <div class="pos-staff-cell">' + bubbles + '</div> </div>'; 53528 53529 var bSignIn = '<b class="narrow-text" style="background-color: deeppink; color: white;">SIGN-IN 3 minutes ago</b>'; 53530 var bNowTag = '<b class="narrow-text" style="color: white; background: linear-gradient(rgba(120, 0,200, .1), rgba(120, 0,200, .8)), linear-gradient(black, black);">'; 53531 var bAvailable = '<b class="narrow-text" style="background-color: rgb(0,255,0);">AVAILABLE</b>'; 53532 var bBusy = '<b class="narrow-text" style="background-color: rgba(255, 255, 0, .4);">BUSY</b>'; 53533 53534 var thumb = '<li>
53534Staff thumbnail image <span>(if uploaded)</span></li>'; 53535 var status = '<li>Status bar' + arrow + bAvailable + ', ' + bBusy + ', ' + bNowTag + 'APPT NOW</b>, ' + bNowTag + 'APPT in 13 minutes</b>, ' + bSignIn + ', etc...</li>'; 53536 var time = '<li>Time range working' + arrow + '<b>2 pm - 9 pm</b></li>'; 53537 var circle = '<li>Ticket count bubbles <span>(uses colors listed above)</span>' + arrow + bubbles + '</li>'; 53538 var list = '<ul>' + thumb + status + time + circle + '</ul>'; 53539 53540 var msgBreak = '<p>Staff Cards also display when a staff is about to go on break or is on break</p>'; 53541 var imgBreakSoon = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/break-soon.png" style="width: 40%; max-width: 150px; margin: auto; padding-right: 40px;"/>'; 53542 var imgBreakTime = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/break-time.png" style="width: 40%; max-width: 150px; margin: auto;"/>'; 53543 var htmBreak = '<div id="help-staff-card-break">' + msgBreak + '<div id="help-staff-card-break-images">' + imgBreakSoon + imgBreakTime + '</div></div>'; 53544 53545 return '<div id="help-pos-staff-card" style="padding-bottom: 24px; background-color: white;">' + header + imgStaffCard + msg1 + list + htmBreak + '</div>'; 53546 } 53547 function _getStaffPopupHelp(arrow, screen, card, day, panel, bar) { 53548 var header = '<h3>POS Staff Summary popup</h3>'; 53549 var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-overview2.png" style="width: 90%; max-width: 640px; margin: auto; margin-bottom: 24px;"/>'; 53550 var imgDiv = '<div id="help-staff-preview-diagram">' + img + '</div>'; 53551 53552 var aProfileSvc = '<a onclick="GLO.Uri.gotoUri2(\'provider/profile/4?helloback=website\')">Profile ' + arrow + ' Service</a>'; 53553 var aResourceSetup = '<a onclick="GLO.Uri.gotoUri2(\'provider/manage/resource\', this, event, true)">resource setup</a>'; 53554 53555 //var msg = '<p style="padding-bottom: 0;">Press a ' + card + ' to display the ' + day + '</p>'; 53556 var msg1 = '<p>Press a ' + card + arrow + 'to open the ' + day + '</p>'; 53557 var msg2 = '<p>The service name is the service color set in ' + aProfileSvc + '</p>'; 53558 var msg3 = '<p>Displays resource name above service time, if ' + aResourceSetup + ' <i class="narrow-text">(can setup resources like pedicure chair, booth #, massage table, etc)</i></p>'; 53559 53560 var onSite = '(clients on premise)'; 53561 if (GLO.Data.provider.industry_cd == 1 || GLO.Data.provider.industry_cd == 8) { onSite = '(clients in salon)'; } 53562 53563 var bSignin = '<b class="ticket-status pos-color-signin">Sign-In</b>'; 53564 var bCheckin = '<b class="ticket-status pos-color-checkin">Checked-In</b>'; 53565 var bReady = '<b class="narrow-text pos-color-ready">READY to PAY</b>'; 53566 var bNow = '<b class="ticket-status pos-color-now">NOW</b>'; 53567 53568 var bLate = '<b class="ticket-status pos-color-late">LATE</b>'; 53569 var bPast = '<b class="ticket-status pos-color-past">PAST</b>'; 53570 var bUpcoming = '<b class="ticket-status pos-color-upcoming">UPCOMING</b>'; 53571 53572 var bCheckout = '<b class="ticket-status pos-color-checkout">Checked-Out</b>'; 53573 var bNoShow = '<b class="ticket-status pos-color-no-show">No Show</b>'; 53574 var bLateCancel = '<b class="ticket-status pos-color-late-cancel">Late Cancel</b>'; 53575 53576 var current = '<li><b>Current Tickets</b> ' + onSite + ': ' + bSignin + ', ' + bCheckin + ', ' + bReady + ', ' + bNow + '</li>'; 53577 var scheduled = '<li><b>Scheduled Tickets</b> ' + bLate + ', ' + bPast + ', ' + bUpcoming + '</li>'; 53578 var completed = '<li><b>Completed Tickets</b> ' + bCheckout + ', ' + bNoShow + ', ' + bLateCancel + '</li>'; 53579 53580 var listLabel = '<div id="pos-help-staff-summary-label">Displays all staff\'s tickets for the current day</div>'; 53581 var list = listLabel + '<ul>' + current + scheduled + completed + '</ul>'; 53582 53583 return '<div id="help-pos-staff-preview">' + header + msg1 + msg2 + msg3 + list + imgDiv + '</div>'; 53584 } 53585 function _getPosClientPanelHelp(arrow, screen, card, day, panel, bar) { 53586 var header = '<h3>POS Ticket Panel</h3>'; 53587 var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/client-panel2.png" style="width: 90%; max-width: 980px; margin: auto; margin-bottom: 24px;"/>'; 53588 var imgDiv = '<div id="help-pos-client-panel-diagram">
53588' + img + '</div>'; 53589 53590 var bNoShow = '<b class="narrow-text pos-color-no-show">No Show</b>'; 53591 var bLateCancel = '<b class="narrow-text pos-color-late-cancel">Late Cancel</b>'; 53592 var bClientBar = '<b class="narrow-text" style="color: #4F81BD;">Ticket Status bar</b>'; 53593 53594 var msg1 = '<p>Displays all tickets for the current day <span>(except ' + bNoShow + ' + ' + bLateCancel + ' tickets)</span></p>'; 53595 var msg2 = '<p>At the top of the ' + panel + ' can filter ' + card + ' displayed</p>'; 53596 var msg3 = '<p>Press any ' + bClientBar + ' to open ticket</p>'; 53597 53598 return '<div id="help-pos-client-panel">' + header + msg1 + msg2 + msg3 + imgDiv + '</div>'; 53599 } 53600 function _getTicketHelp(arrow, screen, card, day, panel, bar) { 53601 var header = '<h3>POS Ticket</h3>'; 53602 var msg = '<p style="padding: 24px; padding-left: 12px;">To open ticket press' + arrow + 'ticket in ' + day + ', ' + bar + ' in ' + panel + ', scan QR on ticket, or search for ticket</p>'; 53603 53604 var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/pos-ticket2.png" style=""/>'; 53605 var imgDiv = '<div id="help-pos-ticket-diagram">' + img + '</div>'; 53606 53607 var hIn = '<h6>Check-In</h6>'; 53608 var hOut = '<h6>Check-Out</h6>'; 53609 var hClover = '<h6>Clover Credit Card Machine</h6>'; 53610 53611 var in1 = '<li>Can enable auto-printing ticket at check-in' + arrow + 'then scan ticket at front desk to checkout</li>'; 53612 var in2 = '<li>With just the push of a button can assign chair or table that ticket is assigned</li>'; 53613 var in3 = '<li>Can enable client self sign-in + self-checkout</li>'; 53614 53615 var out1 = '<li>Checkout ticket with just 2 clicks or 1 scan</li>'; 53616 var out2 = '<li>Simply scan ticket, product, or gift card to checkout ticket</li>'; 53617 var out3 = '<li>Have group parties?' + arrow + 'Easily link or split tickets</li>'; 53618 var out4 = '<li>Support for gift cards and loyalty points</li>'; 53619 var out5 = '<li>Setup discounts <span class="narrow-text>(like afternoon happy hours, birthdays, memberships, etc)</span> + add-on fees <span class="narrow-text>(credit card convenience fees, product fees, etc)</span></li>'; 53620 var out6 = '<li>After Checkout, Appointment survey texts automatically sent to client' + arrow + 'encouraging 5 star reviews from happy clients and for un-happy clients private feedback directly to the manager </li>'; 53621 var out7 = '<li>Automatic re-marketing' + arrow + 'encouraging customers to come back more often</li>'; 53622 53623 var clover1 = '<li>Automate your consent form' + arrow + 'Before client checks out, can display payment / refund policy that client must agree to before checking out</li>'; 53624 var clover2 = '<li>Tip prompt on Clover device' + arrow + 'can use original ticket price (before discounts) or total ticket price (after discounts)</li>'; 53625 53626 var listIn = hIn + '<ul>' + in1 + in2 + in3 + '</ul>'; 53627 var listOut = hOut + '<ul>' + out1 + out2 + out3 + out4 + out5 + out6 + out7 + '</ul>'; 53628 var listClover = hClover + '<ul>' + clover1 + clover2 + '</ul>'; 53629 53630 return '<div id="help-pos-ticket">' + header + msg + imgDiv + listIn + listOut + listClover + '</div>'; 53631 } 53632 function _getColorHelp(arrow, screen, card, day, panel, bar) { 53633 var header = '<h3>POS Screen Colors</h3>'; 53634 var msg1 = '<p style="text-align: center; font-style: italic;">The ' + screen + ' is color coded so you can quickly identify staff and ticket status</p>'; 53635 var msg2 = ''; 53636 53637 var liSignin = '<li><b class="ticket-status pos-color-signin">Sign-In</b> client signed-in</li>'; 53638 var bReady = '<b class="narrow-text pos-color-ready">READY to PAY</b>'; 53639 var liIn = '<li><b class="ticket-status pos-color-checkin">Checked-In</b> appointment, includes appointments marked as ' + bReady + '</li>'; 53640 var bAvailable = arrow + 'staff set as <b class="narrow-text pos-color-checkout">AVAILABLE</b> <i class="narrow-text">(if staff does not have appointment)</i>'; 53641 var liOut = '<li style="margin-bottom: 24px;"><b class="ticket-status pos-color-checkout">Checked-Out</b> appointment, when ticket checked-out ' + bAvailable + '</li>'; 53642 53643 var liNow = '<li><b class="ticket-status pos-color-now">NOW</b> appointment starts within 15 minutes of current time <i class="narrow-text">(and not yet checked-in or signed-in)</i></li>'; 53644 var liLate = '<li><b class="ticket-status pos-color-late">LATE</b> appointment 15 - 60 minutes late <i class="narrow-text">
53644(and not yet marked as no-show or late-cancel)</i></li>'; 53645 var liPast = '<li><b class="ticket-status pos-color-past">PAST</b> appointment more than 1 hour late <i class="narrow-text">(and not marked as no-show or late-cancel)</i></li>'; 53646 var liUpcoming = '<li style="margin-bottom: 24px;"><b class="ticket-status pos-color-upcoming">UPCOMING</b> appointment starts more than 15 minutes in the future</li>'; 53647 53648 var liNoShow = '<li><b class="ticket-status pos-color-no-show">No Show</b> appointment marked as a no show</li>'; 53649 var liLateCancel = '<li><b class="ticket-status pos-color-late-cancel">Late Cancel</b> appointment marked as a late cancelation</li>'; 53650 53651 var listColors = '<ul id="help-pos-color-list">' + liSignin + liIn + liOut + liNow + liLate + liPast + liUpcoming + liNoShow + liLateCancel + '</ul>'; 53652 return '<div id="help-pos-colors">' + header + msg1 + msg2 + listColors + '</div>'; 53653 } 53654 53655 function _staffPreviewHtm(staffId, staffName, isFA, thumb, htm) { 53656 var ul = $(htm).find('ul'); //.click(SA.POS.openTicketFromStaffFromPreview); 53657 var ticketCount = ul.length; 53658 var helpIcon = '<b class="question-icon" onclick="SA.POS.openHelpQuickGuide(\'help-pos-staff-card\')" style="position: absolute; top: 4px; left: 0; border: 2px outset white; color: white;">?</b>'; 53659 var labelTicketCount = '<b class="narrow-text" style="color: rgb(240,240,180);">' + UTIL.pluralLabel(ticketCount, 'Ticket') + '</b>'; 53660 var btnPrint = ''; 53661 53662 if (_allowStaffPrintCommission()) { 53663 btnPrint = '<a id="btnPrintStaffCommissionInner" onclick="SA.POS.printTodayCommissionByStaff(this, ' + staffId + ')">Close Day</a>'; 53664 btnPrint = '<span id="btnPrintStaffCommission" class="btnAdd" title="Print Today\'s Staff Commission">' + btnPrint + '</span>'; 53665 } 53666 53667 var h1 = helpIcon + '<b class="staff-preview-name">' + staffName + '</b> ' + labelTicketCount; 53668 53669 /* 53670 var btnNewTicket = '<div id="staff-preview-new"><span id="btnNewTicket" class="btnAdd" onclick="SA.Ticket.newTicket(' + staffId + ', \'' + staffName + '\', ' + isFA + ')"><a>New Ticket</a></span></div>'; 53671 var htmExistingTicket = ' to create a new ticket' 53672 53673 if (ticketCount > 0) { 53674 htmExistingTicket = ' or <b class="narrow-text" style="color: rgb(0, 160, 220);">Existing Ticket</b> <span class="narrow-text">(below)</span>'; 53675 } 53676 53677 var bNewTicket = '<b class="narrow-text" style="color: rgb(0, 160, 220);">New Ticket</b> button <span class="narrow-text">(above)</span>'; 53678 var msg = '<p id="staff-preview-instruction">Press ' + bNewTicket + htmExistingTicket + '</p>'; 53679 */ 53680 53681 htm = '<div id="pop-staff-preview" staff_id="' + staffId + '">' + htm + '</div>'; // + btnNewTicket + msg 53682 53683 var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos-staff-preview'); 53684 jpop.find('h1.friendly-responsive').css({ "margin-bottom": "0" }); 53685 53686 if (thumb && thumb.length && thumb.outerHTML && innerWidth > 760) { 53687 jpop.find('#staff-preview-header').append(thumb.outerHTML()); 53688 } 53689 53690 GLO.Popup.Custom.singleButton(jpop, 'Close'); 53691 53692 var iconClockIn = _getClockInIcon(staffId, isFA); 53693 var jbtns = jpop.find('.pop-buttons'); 53694 jbtns.append(iconClockIn); 53695 jbtns.prepend(btnPrint); 53696 53697 _addResourceIcon(jpop); 53698 SA.TicketCard.checkIfNeedReload(jpop, staffId, ticketCount); 53699 //toDo: ?? click main screen to close ticket ?? 53700 } 53701 53702 _conPos.openTicketFromStaffFromPreview = function(element) { 53703 var ul = $(element) 53704 var cname = $('.staff-preview-client-name').text(); 53705 var bkg = ul.attr('booking_nr'), smid = ul.attr('smid'); 53706 53707 var msg = 'Opening Ticket P' + bkg; 53708 53709 if (!UTIL.isEmpty(cname)) { 53710 msg += ' for ' + cname; 53711 } 53712 53713 var jpop = GLO.Popup.Processing.open('<div id="pop-proceing-open-ticket">' + msg + '...</div>', 'Open Ticket'); 53714 53715 setTimeout(function() { 53716 if (GLO.Popup.closeIfExist(jpop)) { 53717 UserPortal.getTicket(smid, bkg, null, false, true); 53718 } 53719 }, 50); 53720 } 53721 53722 function _allowStaffPrintCommission() { 53723 if (GLO.Info.roleType < 200) { 53724 return false; 53725 } else if (GLO.Data.Staff.role_report_cd == 99 || GLO.Data.Staff.role_report_cd == 199 || GLO.Data.Staff.role_report_cd == 500) { 53726 return false; 53727 } else if (GLO.Data.provider.report.reportCanViewPrice && GLO.Data.provider.report.reportCanViewCommission && GLO.Data.provider.report.reportCanViewTip) { 53728 return true; 53729 } 53730 53731 return false; 53732 } 53733 53734 function _addResourceIcon(jpop) { 53735 var jtickets = jpop.find('#staff-preview-tickets > ul'); 53736 53737 for (var i=0; i < jtickets.length; i++) { 53738 var resourceId = jtickets.eq(i).attr('resource_id'); 53739
53740 if (!UTIL.isEmpty(resourceId)) { 53741 var rname = UserPortal.getResourceName(resourceId); 53742 var icon = '<span class="staff-preview-resource-icon"><span><b>' + rname + '</b></span></span>'; 53743 53744 jtickets.eq(i).find('.staff-preview-date-range').append(icon); 53745 } 53746 } 53747 } 53748 53749 function _getSelectStaffList(element, jsonSelectStaff) { 53750 var htmStaff = '', jthis = $(element); 53751 53752 if (jthis.hasClass('pos-service-label')) { 53753 var serviceName = jthis.find('b').text(); 53754 var jline = jthis.closest('.pos-ticket-line-item'); 53755 var sgid = jline.attr('service_group_id'), svcid = jline.attr('service_id'); 53756 var staffIds = $('#allServiceOptions #crSvc' + sgid).find('option[value="' + svcid + '"]').attr('staff_ids').split(','); 53757 var jstaff = UserPortal.getStaffDropDown().find('option'); 53758 53759 jsonSelectStaff.lineId = jline.attr('id'); 53760 jsonSelectStaff.header = UTIL.coalesce(serviceName, jsonSelectStaff.header); 53761 jsonSelectStaff.attributes = ' line_id="' + jsonSelectStaff.lineId + '"'; 53762 53763 for (var i=0; i < jstaff.length; i++) { 53764 if (staffIds.has(jstaff.eq(i).attr('value'))) { 53765 htmStaff += jstaff.eq(i).outerHTML(); 53766 } 53767 } 53768 53769 return $(htmStaff); 53770 } else if (jthis.hasClass('pos-staff-label')) { 53771 var staffId = jthis.closest('.pos-staff-line-item').attr('staff_id'); 53772 var jlines = jthis.closest('.pos-ticket-line-item[staff_id="' + staffId + '"]'); 53773 var jstaff = $(UserPortal.getStaffDropDown().outerHTML()).find('option'); //= make copy, so can remove from copy 53774 53775 jsonSelectStaff.header = '<b>Change Staff</b> <i class="narrow-text>(current staff: ' + jthis.text() + ')</i>'; 53776 jsonSelectStaff.replaceStaffId = staffId; 53777 jsonSelectStaff.attributes = ' replace_staff_id="' + staffId + '"'; 53778 53779 for (var a=0; a < jlines.length; a++) { 53780 var sgid = jlines.eq(a).attr('service_group_id'), svcid = jlines.eq(a).attr('service_id'); 53781 var svcid = jlines.attr('service_id'); 53782 var staffIds = $('#allServiceOptions #crSvc' + sgid).find('option[value="' + svcid + '"]').attr('staff_ids').split(','); 53783 53784 for (var b=0; b < jstaff.length; b++) { 53785 if (!staffIds.has(jstaff.eq(b).attr('value'))) { 53786 jstaff.eq(i).remove(); 53787 } 53788 } 53789 } 53790 53791 if (jstaff.length) { 53792 for (var i=0; i < jstaff.length; i++) { 53793 htmStaff += jstaff.eq(i).outerHTML(); 53794 } 53795 } else { 53796 htmStaff = '<div><p>No staff member performs all these services</p><p>Please click each service to assign staff</p></div>'; 53797 } 53798 53799 return $(htmStaff); 53800 } else { 53801 return UserPortal.getStaffDropDown().find('option'); 53802 } 53803 } 53804 function _getSelectStaffId(element) { 53805 var jline = $(element).closest('div'); 53806 53807 if (!jline.hasClass('pos-staff-line-item') && !jline.hasClass('pos-service-line-item')) { 53808 jline = $('#pos-header-staff').find('#btnSelectedStaff > a'); 53809 } 53810 53811 return jline.attr('staff_id'); 53812 } 53813 _conPos.openSelectStaff = function(event, serviceId) { 53814 GLO.Popup.closeIfExist($('#pop-warnng-staff-required').closest('.glopop')); 53815 53816 if ($('#pop-pos-select-staff').closest('.glopop').length) { 53817 return; 53818 } 53819 53820 var ul = '<ul id="pos-staff-list">'; 53821 var jsonSelectStaff = { "attributes": "", "header": "Select Staff" }; 53822 var jstaff = _getSelectStaffList(this, jsonSelectStaff); 53823 var currSID = _getSelectStaffId(this); 53824 53825 for (var i=0; i < jstaff.length; i++) { 53826 var sname = jstaff.eq(i).text(), sid = jstaff.eq(i).attr('value'); 53827 var role = jstaff.eq(i).attr('role'); 53828 var css = '', faAttribute = ''; 53829 53830 if (UserPortal.staffPerformsClientService(sid)) { 53831 if (UTIL.parseBool(jstaff.eq(i).attr('is_first_available_fl'))) { 53832 faAttribute = ' is_first_available_fl="1"'; 53833 } 53834 53835 if (sname != 'Anyone' && UTIL.coalesceInt(role, 100) > 99) { 53836 if (currSID == sid) { 53837 css = ' class="selected"'; 53838 } 53839 53840 ul += '<li' + css + ' staff_id="' + sid + '"' + faAttribute + '>' + sname + '</li>'; 53841 } 53842 } 53843 } 53844 53845 ul += '</ul>'; 53846 53847 var htm = '<div id="pop-pos-select-staff"' + jsonSelectStaff.attributes + ' service_id="' + $.trim(serviceId) + '"><div>' + ul + '</div></div>'; 53848 var jpop = GLO.Popup.Custom.openSimple(htm, jsonSelectStaff.header); 53849 53850 if (!UTIL.isEmpty(jsonSelectStaff.lineId)) { 53851 jpop.prepend('<span id="btnRemoveService">
53851<a onclick="SA.POS.removeServiceLine(\'' + jsonSelectStaff.lineId + '\')">Remove Service</a></span>'); 53852 } else if (!UTIL.isEmpty(currSID) && UTIL.isEmpty(jsonSelectStaff.replaceStaffId)) { 53853 jpop.prepend('<span id="btnRemoveService"><a onclick="SA.POS.clearStaff()">Clear Staff</a></span>'); 53854 } 53855 53856 jpop.find('h1').css({ "position": "relative", "z-index": "100" }); 53857 jpop.find('li').click(SA.POS.selectStaff); 53858 GLO.Popup.Custom.singleButton(jpop, 'Close'); 53859 53860 var btnHeight = (jpop.outerHeight() - 28) + "px"; 53861 jpop.find('#btnRemoveService > a').css({ "width": btnHeight }); 53862 } 53863 _conPos.selectStaff = function() { 53864 var li = $(this); 53865 var staffId = li.attr('staff_id'), staffName = li.text(), isFA = UTIL.parseBool(li.attr('is_first_available_fl')); 53866 var jpop = $('#pop-pos-select-staff'); 53867 var lineId = jpop.attr('line_id'), replaceStaffId = jpop.attr('replace_staff_id'), serviceId = jpop.attr('service_id'); 53868 53869 if (!UTIL.isEmpty(lineId)) { 53870 var jtix = $('#pos-ticket'); 53871 var jline = jtix.find('#' + lineId + '.pos-ticket-line-item'); 53872 53873 _addStaffToLine(jtix, jline, staffId, staffName); 53874 _changeDefaultStaff(staffId, staffName, isFA); 53875 SA.Ticket.ticketChanged(); 53876 } else if (!UTIL.isEmpty(replaceStaffId)) { 53877 var jtix = $('#pos-ticket'); 53878 var jlines = jtix.find('.pos-service-line-item[staff_id="' + replaceStaffId + '"]'); 53879 53880 var rowStaff = jtix.find('#staff-row-' + replaceStaffId); 53881 var rowStaffNew = jtix.find('#staff-row-' + staffId); 53882 53883 if (rowStaffNew.length == 0) { 53884 rowStaff.attr('id', 'staff-row-' + staffId); 53885 rowStaff.attr('staff_id', staffId); 53886 rowStaff.find('.pos-staff-label').text(staffName); 53887 } 53888 53889 for (var i=0; i < jlines.length; i++) { 53890 var jline = jlines.eq(i); 53891 _addStaffToLine(jtix, jline, staffId, staffName); 53892 } 53893 53894 if (rowStaffNew.length) { 53895 rowStaff.remove(); 53896 } 53897 53898 _changeDefaultStaff(staffId, staffName, isFA); 53899 SA.Ticket.ticketChanged(); 53900 } else { 53901 _conPos.selectDefaultStaff(staffId, staffName, isFA); 53902 } 53903 53904 SA.Ticket.setStaffHeader(); 53905 SA.Ticket.enableOrDisableTicketScroll(); 53906 SA.Ticket.addServiceLineAfterAddStaff(serviceId); 53907 GLO.Popup.close(jpop.closest('.glopop')); 53908 } 53909 function _changeDefaultStaff(staffId, staffName, isFA) { 53910 var currentDefaultStaffId = $('#pos-header-staff-button #btnSelectedStaff > a').attr('staff_id'); 53911 var jsvc = $('#pos-ticket').find('.pos-service-line-item[staff_id = ' + currentDefaultStaffId + ']'); 53912 53913 if (jsvc.length === 0) { 53914 _conPos.selectDefaultStaff(staffId, staffName, isFA); 53915 } 53916 } 53917 _conPos.selectDefaultStaff = function(staffId, staffName, isFA) { 53918 var sgid = $('#pos-product-header-breadcrumb #pos-breadcrumb-sg').attr('service_group_id'); 53919 53920 _conPos.setStaff(staffId, staffName, isFA, sgid); 53921 _addStaffToServiceMissingStaff(staffId); 53922 } 53923 _conPos.setStaff = function(staffId, staffName, isFA, sgid) { 53924 if (innerWidth < 900) { 53925 staffName = UTIL.maxString(staffName, 12, true); 53926 } 53927 53928 $('#pos-header-staff').addClass('selected').find('#btnSelectedStaff > a').attr('staff_id', staffId).attr('is_first_available_fl', isFA).text(staffName); 53929 _conPos.filterServiceBoxesByStaff(staffId, sgid); 53930 } 53931 53932 function _resetServiceLineDates(jline) { 53933 var serviceId = jline.attr('service_id'); 53934 var staffId = jline.attr('staff_id'); 53935 53936 jline.removeAttr('appt_dt'); 53937 jline.removeAttr('time_vc'); 53938 jline.removeAttr('end_dt'); 53939 53940 var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true); 53941 jline.attr('service_length_nr', ojDefault.minutes_nr); 53942 jline.attr('prep_nr', ojDefault.prep_nr, 0); 53943 jline.attr('prep_fl', ojDefault.prep_fl); 53944 53945 jline.attr('processing_nr', ojDefault.processing_nr, 0); 53946 jline.attr('processing_fl', ojDefault.processing_fl); 53947 jline.attr('finish_out_nr', ojDefault.finish_out_nr, 0); 53948 jline.attr('finish_out_fl', ojDefault.finish_out_fl); 53949 } 53950 function _addStaffToLine(jtix, jline, sid, sname) { 53951 //var jlabel = jline.find('.line-item-name'); 53952 //jlabel.find('i').remove(); 53953 //jlabel.prepend('<i>' + UTIL.maxString(sname, 10, true) + '</i>'); 53954 53955 var rowStaff = SA.Ticket.getStaffTicketLastRow(jtix, sid, jline); 53956 var replaceStaffId = jline.attr('staff_id');
53957 var isClientRequest = 0; 53958 53959 if (UserPortal.isFirstAvailable(sid)) { 53960 jline.attr('is_first_available_fl', 1); 53961 } else { 53962 jline.removeAttr('is_first_available_fl'); 53963 isClientRequest = SA.Ticket.getIsClientRequest(sid); 53964 } 53965 53966 jline.attr('staff_id', sid); 53967 rowStaff.after(jline); 53968 _resetServiceLineDates(jline); 53969 53970 //if previous staff only had 1 service -> remove staff row 53971 var serviceCountForStaff = jtix.find('.pos-service-line-item[staff_id="' + replaceStaffId + '"]').length; 53972 53973 if (serviceCountForStaff === 0) { 53974 jtix.find('.pos-staff-line-item[staff_id="' + replaceStaffId + '"]').remove(); 53975 } 53976 } 53977 function _addStaffToServiceMissingStaff(staffId, isIncludeFirstAvailable) { 53978 var jtix = $('#pos-ticket'); 53979 var jlines = jtix.find('.pos-service-line-item'); 53980 var staffChangecount = 0; 53981 var sname = UserPortal.getStaffName(staffId); 53982 53983 for (var i=0; i < jlines.length; i++) { 53984 var jline = jlines.eq(i); 53985 var isFA = UTIL.parseBool(jline.attr('is_first_available_fl')); 53986 53987 if (UTIL.isEmpty(jline.attr('staff_id')) || (isFA && isIncludeFirstAvailable)) { 53988 var serviceId = jline.attr('service_id'); 53989 53990 if (UserPortal.staffPerformsService(serviceId, staffId)) { 53991 _addStaffToLine(jtix, jline, staffId, sname); 53992 ++staffChangecount; 53993 } 53994 } 53995 } 53996 53997 if (staffChangecount > 0) { 53998 SA.Ticket.ticketChanged(); 53999 } 54000 } 54001 _conPos.clearStaff = function() { 54002 GLO.Popup.close($('#pop-pos-select-staff').closest('.glopop')); 54003 $('#pos-header-staff').removeClass('selected').find('#btnSelectedStaff > a').removeAttr('staff_id').removeAttr('is_first_available_fl').text(''); 54004 SA.Ticket.enableOrDisableTicketScroll(); 54005 54006 var sgid = $('#pos-product-header-breadcrumb').attr('service_group_id'); 54007 54008 if (!UTIL.isEmpty(sgid)) { 54009 _conPos.filterBoxesServiceGroup(sgid); 54010 } else { 54011 _conPos.filterBoxesHome(); 54012 } 54013 } 54014 _conPos.removeServiceLine = function(lineId) { 54015 GLO.Popup.close($('#pop-pos-select-staff').closest('.glopop')); 54016 $('#pos-ticket').find('#pos-ticket-order #' + lineId).find('.ticket-row-remove').click(); 54017 } 54018 54019 _conPos.getServiceGroupObject = function(sgid) { 54020 var sg = SA.POS.inventory_json.service_groups; 54021 sgid = parseInt(sgid); 54022 54023 for (var i=0; i < sg.length; i++) { 54024 if (sgid == sg[i].id) { 54025 return sg[i]; 54026 } 54027 } 54028 54029 return null; 54030 } 54031 _conPos.getServiceObject = function(serviceId) { 54032 var svc = SA.POS.inventory_json.services; 54033 serviceId = parseInt(serviceId); 54034 54035 for (var i=0; i < svc.length; i++) { 54036 if (serviceId === svc[i].id) { 54037 return svc[i]; 54038 } 54039 } 54040 54041 return null; 54042 } 54043 _conPos.getVendorObject = function(vendorId) { 54044 var vendors = SA.POS.inventory_json.vendors; 54045 vendorId = parseInt(vendorId); 54046 54047 for (var i=0; i < vendors.length; i++) { 54048 if (vendorId == vendors[i].id) { 54049 return vendors[i]; 54050 } 54051 } 54052 54053 return null; 54054 } 54055 _conPos.getPLineObject = function(plineId) { 54056 var plines = SA.POS.inventory_json.product_lines; 54057 plineId = parseInt(plineId); 54058 54059 for (var i=0; i < plines.length; i++) { 54060 if (plineId == plines[i].id) { 54061 return plines[i]; 54062 } 54063 } 54064 54065 return null; 54066 } 54067 _conPos.getProductObject = function(inventoryId) { 54068 var products = SA.POS.inventory_json.products; 54069 inventoryId = parseInt(inventoryId); 54070 54071 for (var i=0; i < products.length; i++) { 54072 if (inventoryId === products[i].id) { 54073 return products[i]; 54074 } 54075 } 54076 54077 return null; 54078 } 54079 _conPos.getObject = function(jsonArray, jsonIdKey, id) { 54080 id = parseInt(id); 54081 54082 for (var i=0; i < jsonArray.length; i++) { 54083 if (id === jsonArray[i][jsonIdKey]) { 54084 return jsonArray[i]; 54085 } 54086 } 54087 54088 return null; 54089 } 54090 54091 _conPos.printTodaySales = function(event, element) { 54092 GLO.Report.Sales.printByStaffFromPOS(); 54093 } 54094 function _displayNoSalesTodayWarning() { 54095 var aPayrollByDay = 'Daily Payroll Report'; 54096 54097 if (GLO.Info.roleType > 219) {
54098 aPayrollByDay = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/sales\')">' + aPayrollByDay + '</a>'; 54099 } 54100 54101 var msg1 = '<p>No Sales Found Today</p>'; 54102 var msg2 = '<p>To print a previous days sales commission go to the ' + aPayrollByDay + '</p>'; 54103 var htm = '<div id="pop-warn-pos-no-sales">' + msg1 + msg2 + '</div>'; 54104 54105 GLO.Popup.Info.open(htm, 'No Sales Found Today'); 54106 } 54107 _conPos.printTodayCommissionToPrinter = function(element) { //step 4: print from popup 54108 var jpop = $('#report-payroll-days-all-data'); 54109 var jtbl = jpop.find('#report-payroll-days'); 54110 var htm = jpop.outerHTML(); 54111 54112 var css = '', msg = null, fnAfterPrint = null; 54113 var commissionTotal = UTIL.coalesceMoney(UTIL.coalesceString(jtbl.find('tfoot .payroll-column-commission').text(), jtbl.find('tbody .payroll-column-commission').text()).replace('$', '')); 54114 var dtLastProcessed = jpop.find('#payroll-last-processed-date').text(); 54115 54116 if (!UTIL.isDate(dtLastProcessed)) { 54117 msg = 'Need to process payroll to view commission amount'; 54118 } else if (UTIL.isToday(new Date(dtLastProcessed).addMinutes(-360))) { 54119 msg = 'Need to process payroll to view commission amount'; 54120 } else if (commissionTotal === 0) { 54121 msg = 'Commission empty, may need to checkout tickets then process payroll to view commission amount'; 54122 } 54123 54124 if (msg) { 54125 fnAfterPrint = function() { 54126 var jpop = GLO.Report.Payroll.openProcessingPayrollPopup(true, msg, true).getPopup(); 54127 }; 54128 } 54129 54130 GLO.Popup.close(jpop.closest('.glopop')); 54131 UI.Print.print(htm, css, false, fnAfterPrint); 54132 } 54133 _conPos.printTodayCommissionDisplay = function(url) { //step 3: display report in popup 54134 var sfilter = GLO.Uri.getQueryStringValueFromUrl('sfilter', url); 54135 var staffId = null; 54136 54137 if (sfilter && sfilter.indexOf && sfilter.indexOf(',') === -1 && UTIL.isNumber(sfilter)) { 54138 staffId = sfilter; 54139 } 54140 54141 var jpop = GLO.Report.Payroll.initByDayPopup(staffId); 54142 54143 if (UTIL.parseBool(GLO.Uri.getQueryStringValueFromUrl('isAutoPrint', url))) { 54144 jpop.find('#btnPrintStaffCommission > a').click(); 54145 } 54146 } 54147 _conPos.printTodayCommissionByStaffNow = function(element, staffId) { //step 2.5: + lookup staff + PIN 54148 var today = new Date().toGloDate(); 54149 var url = 'report/payrollDays?sfilter=' + staffId + '&start=' + today + '&end=' + today; //+ '&period=current'; 54150 } 54151 _conPos.printTodayCommissionByStaff = function(element, staffId, isAutoPrint) { //step 2: enter PIN + verify PIN on server, then lookup report data 54152 var today = new Date().toGloDate(); 54153 var url = 'report/payrollDays?sfilter=' + staffId + '&start=' + today + '&end=' + today; //+ '&period=current'; 54154 var sname = UserPortal.getStaffName(staffId); 54155 var msg = 'Lookup Commission Today for ' + sname; 54156 var header = UserPortal.getStaffName(staffId) + ' Payroll Today'; 54157 54158 if (isAutoPrint) { 54159 url += '&isAutoPrint=1'; 54160 } else { 54161 msg = GLO.Report.Payroll.openProcessingPayrollPopup(false, msg); 54162 } 54163 54164 GLO.Popup.closeIfExist($('#pop-print-commission-select-staff').closest('.glopop')); 54165 GLO.Popup.closeIfExist($('.pop-pos-staff-preview.glopop')); 54166 GLO.Popup.closeIfExist($('.pop-pos.glopop')); 54167 GLO.Popup.closeIfExist($('#pop-processing-payroll').closest('.glopop')); 54168 54169 //SA.Menu.openRequirePIN(url, false, element, true, msg); 54170 if (SA.Menu.isRequirePIN(url, element, event, true, header)) { 54171 return false; 54172 } else { 54173 var popupId = 'report-payroll-days-full-page', fnOnload = SA.POS.printTodayCommissionDisplay; 54174 SA.Menu.openPopupReport(element, url, header, popupId, msg, fnOnload); //_openPopupReport(null, element, url, h1, popupId, msg, fnOnload); 54175 } 54176 } 54177 54178 _conPos.printTodayCommissionPopup = function() { 54179 var jpop = $('#pop-print-commission-select-staff'); 54180 jpop.find('#print-staff-summary-info').remove(); 54181 jpop.find('.pop-header').remove(); 54182 54183 var htm = jpop.outerHTML(); 54184 var fnAfterPrint = null, css = null; 54185 54186 GLO.Popup.close(jpop); 54187 GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop')); 54188 UI.Print.print(htm, css, false, fnAfterPrint); 54189 } 54190 _conPos.printTodayCommission = function(element) { //step 1: select staff 54191 var staffSummary = SA.TicketCard.getStaffSummary(); 54192 var arr = []; 54193 54194 var jrpt = $('#pos-staff-list'); 54195 var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]'); 54196 54197 if (tdStaff.length === 0) { 54198 _displayNoSalesTodayWarning(); 54199 return; 54200 } 54201 54202 for (var i=0; i < staffSummary.length; i++) { 54203 if (staffSummary[i].service_sr > 0) { 54204 arr.push(staffSummary[i]); 54205 } 54206 } 54207 54208 arr = UTIL.sortArray(arr, "price_mn"); //later add support for "turn_sr" (and turns column in table below) 54209 54210 if (arr.length === 1) { 54211 _conRptSales.printByStaff2(arr[0].id); 54212 } else { 54213 var h1 = 'Print Staff Commission Today'; 54214 //var h1Staff = '<h3 class="friendly-responsive" style="margin-top: 0;"><div>Select Staff</div></h3>'; 54215 var btnPrintAll = '<span class="btnAdd">
54215<a onclick="SA.POS.printTodayCommissionPopup()">Print Summary</a></span>'; 54216 var msg2Style = ' style="padding: 0 8px; line-height: 1.2; text-align: center"'; 54217 var msg = '<p id="print-staff-summary-info" style="padding: 12px; text-align: center;">Select staff below or ' + btnPrintAll + '</p>'; 54218 var msg2 = '<p' + msg2Style + '>Tickets that are <b class="narrow-text">checked-in</b>, <b class="narrow-text">checked-out</b>, or <b class="narrow-text">ready-to-pay</b></p>'; 54219 54220 var infoTicket = 'Tickets that have the status: Checked-Out, Ready To Pay, or Checked-In'; 54221 var infoPrice = 'Service Price before discount and add-on fees'; 54222 54223 var thPrice = '<th class="column-print-price" title="' + infoPrice + '">Price</th>'; 54224 var thTicket = '<th class="column-print-ticket" title="' + infoTicket + '" style="padding-left: 2px; padding-right: 4px;">Tickets</th>'; 54225 var thService = '<th style="padding-left: 2px; padding-right: 4px;">Services</th>'; 54226 var thead = '<thead> <tr> <th class="column-print-staff">Staff</th>' + thPrice + thTicket + thService + '</thead>'; 54227 var htmTable = '<table class="pop-select-staff tablesorter" style="width: 100%;">' + thead + '<tbody>'; 54228 54229 for (var a=0; a < arr.length; a++) { 54230 var trClass = '', name = UTIL.coalesceString(arr[a].title, arr[a].name); 54231 var btnStaff = '<span class="btn btnSA"><a class="pop-select-staff-name" onclick="SA.POS.printTodayCommissionByStaff(this, ' + arr[a].id + ')">' + name + '</a></span>'; 54232 var tdStaff = '<td class="column-print-staff" order_by="' + name + '">' + btnStaff + '</td>'; 54233 54234 var titleTicket = UTIL.pluralLabel(arr[a].ticket_sr, 'ticket') + ' with ' + UTIL.pluralLabel(arr[a].service_sr, 'service') + ' || ' + infoTicket; 54235 var tdTicket = '<td class="column-print-ticket" title="' + titleTicket + '">' + arr[a].ticket_sr + '</td>'; 54236 var tdService = '<td class="column-print-service" title="' + titleTicket + '">' + arr[a].service_sr + '</td>'; 54237 54238 var price = UTIL.displayMoney(arr[a].price_mn, false, false, true); 54239 var titlePrice = price + ' || ' + infoPrice; 54240 var tdPrice = '<td class="column-print-price" title="' + titlePrice + '">' + price + '</td>'; 54241 54242 htmTable += '<tr class="' + trClass + '">' + tdStaff + tdPrice + tdTicket + tdService + '</tr>'; 54243 } 54244 54245 htmTable += '</tbody></table>'; 54246 var htm = '<div id="pop-print-commission-select-staff">' + msg2 + msg + htmTable + '</div>'; 54247 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 54248 var jtbl = jpop.find('table.tablesorter'); 54249 54250 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54251 UI.initTableSorter(jtbl); 54252 GLO.Report.CellSummary.initReport(jtbl, false, true); 54253 jpop.find('.msg.scrollable-for-mac').css({ "overflow-x": "hidden" }); 54254 } 54255 } 54256 _conPos.printTodayCommission_OLD = function(element) { //step 1: select staff 54257 var jrpt = $('#pos-staff-list'); 54258 var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]'); 54259 54260 if (tdStaff.length === 0) { 54261 _displayNoSalesTodayWarning(); 54262 return; 54263 } 54264 54265 var arr = []; 54266 var sid = tdStaff.eq(0).attr('staff_id'); 54267 54268 for (var i=0; i < tdStaff.length; i++) { 54269 var sid = tdStaff.eq(i).attr('staff_id'); 54270 var staffName = tdStaff.eq(i).find('.pos-staff-name').text(); 54271 var ticketCheckedOutCount = UTIL.coalesceInt(tdStaff.eq(i).find('.staff-appt-checkout-count').text(), 0); 54272 54273 if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) { 54274 if (ticketCheckedOutCount > 0) { 54275 var sortName = '00-' + staffName; 54276 } else { 54277 var sortName = 'zz-' + staffName; 54278 } 54279 54280 if (ticketCheckedOutCount > 0 || !UTIL.parseBool(tdStaff.eq(i).attr('is_first_available_fl'))) { 54281 arr.push({ "id": sid, "name": staffName, "ticket_out_sr": ticketCheckedOutCount, "sortname": sortName }); 54282 } 54283 } 54284 } 54285 54286 arr = UTIL.sortArray(arr, "sortname"); 54287 54288 if (arr.length === 1) { 54289 _conRptSales.printByStaff2(arr[0].id); 54290 } else { 54291 var h1 = 'Print Staff Commission Today', ul = '<ul class="pop-select-staff">'; 54292 var h1Staff = '<h3 class="friendly-responsive" style="margin-top: 0;"><div>Select Staff</div></h3>'; 54293 var msg = '<p style="padding: 8px 0;">Tickets that are checked-in, checked-out, or ready-to-pay</p>'; 54294 54295 for (var a=0; a < arr.length; a++) { 54296 var liClass = '', labelTicket = ''; 54297 var labelStaff = '<span class="btn btnSA"><a class="pop-select-staff-name" onclick="SA.POS.printTodayCommissionByStaff(this, ' + arr[a].id + ')">' + arr[a].name + '</a></span>'; 54298 54299 if (arr[a].ticket_out_sr > 0) { 54300 labelTicket = UTIL.pluralLabel(arr[a].ticket_out_sr, 'ticket'); 54301 labelTicket = '<span class="staff-appt-count staff-appt-checkout"><b class="staff-appt-checkout-count" title="' + labelTicket + ' Checked Out">' + arr[a].ticket_out_sr + '</b></span>'; 54302 liClass = 'has-ticket-checked-out'; 54303 } else { 54304 liClass = 'no-ticket-checked-out'; 54305 } 54306 54307 ul += '<li class="' + liClass + '">' + labelStaff + labelTicket + '</li>'; 54308 } 54309 54310 ul += '</ul>'; 54311 var htm = '<div id="pop-print-commission-select-staff">' + h1Staff + msg + ul + '</div>'; 54312 var jpop = GLO.Popup.Custom.openSimple(htm, h1); 54313 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54314 } 54315 } 54316
54317 _conPos.openReportMenu = function() { 54318 GLO.Popup.closeIfExist($('.pop-pos.glopop')); 54319 54320 var htmIn = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportCheckedIn(null, this)">Checked-In</a> </span>'; 54321 var htmOut = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportCheckedOut(null, this)">Checked-Out</a> </span>'; 54322 var htmUpcoming = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportUpcomingAppointments(null, this)">Upcoming Today</a> </span>'; 54323 var htmQuickLeft = '<div id="hd-reports-menu-quick-left">' + htmIn + htmOut + htmUpcoming + '</div>'; 54324 54325 var jpop = new GLO.Popup.Custom( $('#hd-reports-menu') ).getPopup().addClass('pop-header-drop-menu'); 54326 var jtop = jpop.find('#hd-reports-menu-top'); 54327 54328 jtop.find('h5').replaceWith(htmQuickLeft); 54329 jtop.find('#hd-reports-menu-quick').css({ "width": "280px", "margin": "auto", "margin-bottom": "16px", "padding-left": "8px" }); //"float": "none", 54330 54331 var htmBrand = '<span class="sa-brand"><i>Schedule</i><b>Anyone</b></span>'; 54332 var css = 'padding-top: 10px; padding-bottom: 8px; letter-spacing: 2px; font-size: 18px; background-color: white;'; 54333 var h1 = '<h1 style="' + css + '">' + htmBrand + ' <span>Reports</span> </h1>'; 54334 54335 jpop.find('.pop-header').html(h1); 54336 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54337 54338 var btnManagerReports = '<span class="manager-reports-link"><a onclick="SA.POS.openManagerReport()">Manager Reports</a></span>'; 54339 var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>'; 54340 54341 jpop.find('.pop-header').css({ "position": "relative" }).append(btnManagerReports); 54342 jpop.find('.pop-buttons-parent').append(btnPosHelp); 54343 54344 /* 54345 var jbtns = jpop.find('.pop-buttons'); 54346 jbtns.find('.btnSave').remove(); 54347 jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').find('a').css({ "letter-spacing": "1px" }).text(SA.Resource.Close); 54348 */ 54349 } 54350 54351 _conPos.openManagerReport = function() { 54352 GLO.Popup.closeIfExist($('.pop-pos.glopop')); 54353 GLO.Popup.closeIfExist($('.pop-header-drop-menu.glopop')); 54354 54355 var htmSummary = SA.TicketCard.getCardSummary(); 54356 54357 var btnPrintSales = '<span id="btnPrintSales" class="btnAdd"><a onclick="SA.POS.printTodaySales(event, this)">Print Detail</a></span>'; 54358 var sales1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/sales\')">Sales Summary</a></label> <i>Dashboard of Today\'s Sales</i></div>'; 54359 var sales2 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1\')">Sales Detail</a></label> <i>per Service</i>' + btnPrintSales + '</div>'; 54360 var sales3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/TicketHistory\')">Ticket History</a></label> <i>per Ticket</i></div>'; 54361 var htmSales = '<div class="pop-report-box"><h3>Sales Reports</h3>' + sales1 + sales2 + sales3 + '</div>'; 54362 54363 var pay1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'payment/ReportBatch\')">Today\'s Batch</a></label> <i>Credit/Debit Payments</i></div>'; 54364 var pay2 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1&paymethod=0\')">Payment Detail</a></label> <i>Today\'s Payments</i></div>'; 54365 var pay3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/cash\')">Ticket History</a></label> <i>Today\'s Cash Payments</i></div>'; 54366 var htmPayment = '<div class="pop-report-box"><h3>Payment Reports</h3>' + pay1 + pay2 + pay3 + '</div>'; 54367 54368 var aPayroll = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/payroll\')">Payroll</a>'; 54369 var other4 = '', other5 = '', other6 = ''; 54370 54371 if (_allowStaffPrintCommission()) { 54372 var btnPrintPayroll = '<span id="btnPrintPayroll" class="btnAdd" title="Print Today\'s Staff Commission">
54372<a onclick="SA.POS.printTodayCommission(this)">Print Summary</a></span>'; 54373 } else { 54374 var btnPrintPayroll = ''; 54375 } 54376 54377 if (innerHeight > 900) { 54378 var aReminderView = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/reminders\')">Reminder View</a>'; 54379 var aActivityView = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/apptportal\')">Activity View</a>'; 54380 54381 other4 = '<div class="pop-pos-line pop-pos-appt-rpt"><label>' + aReminderView + '</label> <i>Reminders sent & scheduled to be sent</i></div>'; 54382 other5 = '<div class="pop-pos-line pop-pos-appt-rpt"><label>' + aActivityView + '</label> <i>Ticket update history</i></div>'; 54383 54384 if (SA.Data.resourceJson.length) { 54385 var lblCal = '', aCal = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/ResourceView\')">Resource Calendar</a>'; 54386 54387 for (var i=0; i < SA.Data.resourceJson.length; i++) { 54388 if (i > 0) { lblCal += ', '; } 54389 54390 lblCal += SA.Data.resourceJson[i].name; 54391 } 54392 54393 other6 = '<div id="pop-pos-line-resource-cal" class="pop-pos-line pop-pos-appt-rpt"><label>' + aCal + '</label> <i>' + lblCal + '</i></div>'; 54394 } 54395 } 54396 54397 var other1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'message/ClientList\')">Client List</a></label> <i>View Clients + Send Marketing Messages</i></div>'; 54398 var other2 = '<div id="pop-mr-payroll" class="pop-pos-line"><label>' + aPayroll + '</label> <i>Automatically Calculated</i>' + btnPrintPayroll + '</div>'; 54399 var other3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'report/StaffGoal?isActiveStaffOnly=1\')">Goals</a></label> <i>Track Sales with Charts</i></div>'; 54400 var htmOther = '<div class="pop-report-box"><h3>Other Reports</h3>' + other1 + other2 + other3 + other4 + other5 + other6 + '</div>'; 54401 54402 var btnAllReports = '<span class="all-reports-link"><a onclick="SA.POS.openReportMenu()">All Reports</a></span>'; 54403 var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>'; 54404 54405 var htm = '<div id="pop-manager-report">' + htmSummary + htmSales + htmPayment + htmOther + '</div>'; 54406 var jpop = GLO.Popup.Custom.openSimple(htm, 'Manager Reports').addClass('pop-pos').attr('title', 'Owner / Manager Reports'); 54407 54408 jpop.find('.pop-header').css({ "position": "relative" }).append(btnAllReports); 54409 jpop.find('.pop-buttons-parent').append(btnPosHelp); 54410 54411 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54412 } 54413 _conPos.openTurnTracker = function() { 54414 var uriSignin = GLO.Data.provider.urikey + '/Signin'; 54415 var btnEditSignin = '<span class="btnAdd btnGoToSignin btnGoToSigninEdit"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriSignin + '\', this, event, true)">Edit Sign-In</a></span>'; 54416 var aSignin = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriSignin + '\', this, event, true)"><b>Sign-In Screen</b></a></i>'; 54417 var aSignin2 = '<i class="pop-pos-text2">' + btnEditSignin + '</i>'; 54418 var htmSignin = '<div class="pop-pos-line" id="pop-pos-signin"><label>Client Sign-In</label>' + aSignin + aSignin2 + '</div>'; 54419 54420 var htmTurnTracking = '<p style="text-align: center;">Advanced Turn Tracking Coming Soon in October 2026...</p>'; 54421 var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>'; 54422 54423 var htm = '<div id="pop-turn-tracker" style="padding: 12px;">' + htmSignin + htmTurnTracking + '</div>'; 54424 var jpop = GLO.Popup.Custom.openSimple(htm, 'Turn Tracking').addClass('pop-pos'); 54425 54426 jpop.find('.pop-buttons-parent').append(btnPosHelp); 54427 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54428 } 54429 _conPos.openProfile = function() { 54430 var msg = ''; 54431 var aBizProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/2\', this, event, true)" style="border-bottom: none;">Business Profile</a>'; 54432 var hBiz = '<h3>Manage Your ' + aBizProfile + '</h3>'; 54433 54434 var aSvc = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, event, true)">Add + Edit</a></i>'; 54435 var aSvc2 = '<i class="pop-pos-text2"><span class="btnAdd">
54435<a onclick="SA.POS.Edit.changeMode()" style="font-style: normal;">Edit P.O.S. Screen</a></span></i>'; 54436 var htmBizSvc = '<div id="pop-pos-profile-service" class="pop-pos-line"><label>Services</label>' + aSvc + aSvc2 + '</div>'; 54437 54438 var aSigninLink = GLO.Data.provider.urikey + '/Signin'; 54439 var aSigninCustomize = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aSigninLink + '?open=help-overview&mode=edit&back=pos\', this, event, true)">Customize</a></i>'; 54440 var aSigninView = '<i class="pop-pos-text2"><a class="pop-pos-profile-narrow-text" onclick="UI.openChildWindow(\'' + aSigninLink + '\', null, true)">View Sign-In Screen</a></i>'; //GLO.Uri.gotoUriWithSpinner(\'' + aSigninLink + '\', this, event, true) 54441 var htmSignin = '<div id="pop-pos-profile-signin" class="pop-pos-line"><label>Client Sign-In</label>' + aSigninCustomize + aSigninView + '</div>'; 54442 54443 var aWebManage = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'wizard/website\', this, event, true)">Manage</a></i>'; 54444 var aWebView = '<i class="pop-pos-text2"><a onclick="SA.App.openLinkInBrowser(\'' + GLO.Data.provider.websiteuri + '?helloback=website\', true)">View Website</a></i>'; 54445 var htmWeb = '<div id="pop-pos-profile-web" class="pop-pos-line"><label>Website</label>' + aWebManage + aWebView + '</div>'; 54446 54447 var aDiscount = '<i><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/discount\')">Discounts</a></i>'; 54448 var aAddOn = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/addon\')">Add-On Fees</a></i>'; 54449 var htmDiscount = '<div id="pop-pos-profile-discount" class="pop-pos-line"><label>Setup</label>' + aDiscount + aAddOn + '</div>'; 54450 54451 var aMsgOverview = '<i style="width: inherit;"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/message?helloback=pos\', this, event, true)">Message Plan + Overview</a></i>'; 54452 var htmMsg = '<div class="pop-pos-line" id="pop-pos-profile-message"><label>Email/Text</label>' + aMsgOverview + '</div>'; 54453 54454 var aAdvanced = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced\', this, event, true)">Advanced Setup</a></i>'; 54455 54456 //var aInventory = ''; '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoInventory(event, this, \'inventory\')">Product List</a></i>'; 54457 var aSecurity = ''; '<i class="pop-pos-text2"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/SetupSecurity/CompanyComputer\', this, event, true)">Security</a></i>'; 54458 var htmAdvanced = '<div class="pop-pos-line" id="pop-pos-profile-advanced"><label>More Options</label>' + aAdvanced + aSecurity + '</div>'; 54459 54460 var htmBiz = '<div id="pop-pos-profile-preview-biz">' + hBiz + htmBizSvc + htmSignin + htmWeb + htmDiscount + htmMsg + htmAdvanced + '</div>'; 54461 var hStaff = '<h3>Manage Staff Profiles</h3>'; 54462 54463 var titleStaff = 'Add + Edit Profile, Alerts, Role (permission), Normal Hours, Online Booking Profile'; 54464 var aStaff = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?\', this, event, true)" title="' + titleStaff + '">Add + Edit</a></i>'; 54465 var aProfileReport = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport2(event, this, \'reports/StaffProfile\')">Profile Report</a></i>'; 54466 var htmStaff1 = '<div id="pop-pos-profile-staff-service" class="pop-pos-line"><label>Staff</label>' + aStaff + aProfileReport + '</div>'; 54467 54468 var aStaffSvc = '<i><a class="pop-pos-profile-narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?highlight=wiz5-column-staff-service\', this, event, true)">Services for each Staff</a></i>'; 54469 var aCommission = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/CommissionByStaffService\')">Commission</a></i>'; 54470 var htmStaff2 = '<div id="pop-pos-profile-staff2" class="pop-pos-line"><label>Customize</label>' + aStaffSvc + aCommission + '</div>'; 54471 54472 //var htmStaffRpt = '<div class="pop-pos-line"><label style="letter-spacing: 0;">Staff Profile Report</label>' + aProfileReport + '</div>'; 54473 var htmStaff = '<div id="pop-pos-profile-preview-staff">' + hStaff + htmStaff1 + htmStaff2 + '</div>'; // + htmStaffRpt 54474 54475 var btnPosHelp = '<span class="btnAdd btnPosHelp">
54475<a onclick="SA.POS.openHelp(true)">Help</a></span>'; //GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?open=tab-help\', this, event, true) 54476 54477 if ($('#header-main-row-clock-out #clock-out-icon').length) { 54478 var iconClockIn = '<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.open(this)" title="Clock In and Out"> <a style="color: rgb(255, 255, 255);"></a> </span>'; 54479 } else { 54480 var iconClockIn = ''; 54481 } 54482 54483 var htm = '<div id="pop-pos-profile-preview">' + htmBiz + htmStaff + '</div>'; 54484 var jpop = GLO.Popup.Custom.openSimple(htm, 'Manage Profile').addClass('pop-pos'); 54485 54486 jpop.find('.pop-buttons-parent').append(btnPosHelp).find('.pop-buttons').append(iconClockIn); 54487 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54488 } 54489 _conPos.openHelp = function(isIncludeWebsite) { 54490 GLO.Popup.closeIfExist($('.pop-pos.glopop')); 54491 GLO.Popup.closeIfExist($('.pop-header-drop-menu.glopop')); 54492 54493 var htmHi = '<div id="pop-pos-help-hi" style="font-weight: bold; color: #4F81BD;">Hi ' + GLO.Info.getStaffName() + '</div>'; 54494 var aEditPos = '<label><span class="btnAdd"><a onclick="SA.POS.Edit.openHelp()">Edit P.O.S.</a></span></label>'; 54495 var aFAQ = '<label><a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=pos\', this, event, true)">Frequently Asked Questions</a></label>'; 54496 var aHowToGuides = '<label><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?open=tab-help\', this, event, true)">How To Guides</a></label>'; 54497 var aNew = '<label><a onclick="SA.POS.openNewFeatures()">Newest Features</a></label>'; 54498 var aHelpIcon = '<b class="question-icon">?</b>'; 54499 54500 var htmQuickGuide = '<h5 id="pop-pos-help-quick" onclick="SA.POS.openHelpQuickGuide()">' + aHelpIcon + '<label>P.O.S. Screen Quick Guide</label></h5>'; 54501 var htmContact = '<h5 id="pop-pos-contact-sa" onclick="GLO.Log.openContactSAPopup(null, null, null, true)"> <i>Contact</i> ' + GLO.Info.getScheduleAnyoneHtm(true) + '</h5>'; 54502 var htmEditPos = '<div class="pop-pos-line" id="pop-pos-help-edit">' + aEditPos + '<i>Customize the P.O.S. Screen</i></div>'; 54503 var htmFAQ = '<div class="pop-pos-line" id="pop-pos-help-faq">' + aFAQ + '<i>Quick overview of common questions</i></div>'; 54504 var htmHowToGuides = '<div class="pop-pos-line" id="pop-pos-help-how-to">' + aHowToGuides + '<i>Detailed information how everything works</i></div>'; 54505 var htmNew = '<div class="pop-pos-line" id="pop-pos-help-new">' + aNew + '<i>Checkout the latest ' + GLO.Info.getScheduleAnyoneHtm() + ' features</i></div>'; 54506 54507 if (isIncludeWebsite) { 54508 var aWeb = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + GLO.Info.getScheduleAnyoneWebsite() + '\', this, event, true)">' + GLO.Info.getScheduleAnyoneHtm() + '.com</a>'; 54509 var htmWeb = '<div class="pop-pos-line" id="pop-pos-help-web"><label>' + aWeb + '</label><i>Visit our website for more information</i></div>'; 54510 } else { 54511 var htmWeb = ''; 54512 } 54513 54514 var htm = '<div id="pop-pos-help">' + htmHi + htmQuickGuide + htmContact + htmEditPos + htmFAQ + htmHowToGuides + htmNew + htmWeb + '</div>'; 54515 var h1 = GLO.Info.getScheduleAnyoneHtm(true) + ' Help'; 54516 var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos'); 54517 54518 jpop.find('h1').css({ "background-color": "#444" }); 54519 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54520 } 54521 54522 _conPos.openNewFeatures = function() { 54523 GLO.Popup.close( $('#pop-pos-help').closest('.glopop') ); 54524 54525 var icon = $('#header-main-logo')[0]; 54526 SA.Menu.openNewestFeatureHelp(icon); 54527 } 54528 54529 _conPos.Edit = (function() { 54530 function _conPosEdit() { } 54531 var _plineDD = null; 54532 var _DEFAULT_COLOR = 'rgb(98,190,203)', _DEFAULT_BACKGROUND_COLOR = 'rgb(255,255,255)'; 54533 var _popEditBrand = null, _popEditCategory = null, _popEditProduct = null; 54534 54535 _conPosEdit.changeMode = function() { 54536 SA.Ticket.displayTicket(); 54537 var j = $('#pos-container'); 54538 var jbreadcrumb = j.find('#pos-product-header-breadcrumb'); 54539 54540 if (j.hasClass('edit-pos')) { 54541 j.removeClass('edit-pos'); 54542 j.find('#pos-edit-add-buttons').addClass('hide'); 54543 54544 var parentBtn = j.find('#pos-product-header-breadcrumb').find('#pos-product-header-add-pline, #pos-product-header-add-category-type'); 54545 54546 if (parentBtn.length > 0) { 54547 parentBtn.remove(); 54548 jbreadcrumb.find('b:last').remove(); 54549 } 54550 54551 $('#hello-bar-generic').remove(); 54552 $('#edit-pos-button').find('a').text('Edit POS'); 54553 $('body').removeClass('phone-has-hello-bar'); 54554 54555 SA.Ticket.clearTicket(); 54556 var uri = GLO.Link.WebsiteDomain + 'pos'; 54557 //if (keepEdit) { uri += '?edit=1'; } 54558 } else { 54559 j.find('#POS_Use_Service_Image_fl').prop('checked', _conPos.inventory_json.use_service_image_fl); 54560 54561 GLO.Popup.closeIfExist($('#pop-pos-profile-preview').closest('.glopop')); 54562 SA.POS.toggleActionMenu(true); //if (!$('#pos-action-menu').hasClass('hide')) { 54563 54564 _setEditModeHideTicketPanel(); 54565 _addHelloBar('Edit P.O.S. Screen', 'SA.POS.Edit.changeMode()'); 54566 54567 j.addClass('edit-pos'); 54568 var uri = GLO.Link.WebsiteDomain + 'pos?edit=1'; 54569 } 54570 54571 window.history.replaceState("", "", uri); //=removes '?edit=true' (if exists) from url. 54572 _clickBreadcrumbEnd(null, null, true); 54573 54574 /* //= instead just calling breadcrumbEnd, which also dis
54574plays (if is edit) or hides (if not) brands / plines with zero products. 54575 var vendor = null, vendorId = jbreadcrumb.attr('vendor_id'); 54576 var productLine = null, plineId = jbreadcrumb.attr('product_line_id'); 54577 54578 if (plineId) { productLine = _conPos.getPLineObject(plineId); } 54579 if (vendorId) { vendor = _conPos.getVendorObject(vendorId); } 54580 54581 _displayEnterProductHeader(vendor, productLine); 54582 _conPosEdit.displayForIsEdit(vendor, productLine); 54583 */ 54584 } 54585 54586 function _setEditModeHideTicketPanel() { 54587 var j = $('#pos-ticket-edit-hide-panel'); 54588 54589 if (_conPos.inventory_json.hide_ticket_panel_fl) { 54590 j.find('#POS_Edit_Ticket_Panel_Hide').prop('checked', true); 54591 } else if (UTIL.parseBool($.cookies.get('hide_ticket_panel_fl'))) { 54592 j.find('#POS_Edit_Ticket_Panel_Hide_This_Device').prop('checked', true); 54593 } else { 54594 j.find('#POS_Edit_Ticket_Panel_Display').prop('checked', true); 54595 } 54596 } 54597 54598 function _addHelloBar(label, closeFnName, customClass) { 54599 $('#hello-bar-generic').remove(); 54600 54601 if (innerWidth < 800) { 54602 var saHtm = '<img class="sa-logo sa-logo-footer" src="https://www.ScheduleAnyone.com/image/marketing/logo/logo.png">'; 54603 } else { 54604 var saHtm = GLO.Info.getScheduleAnyoneHtm(); 54605 } 54606 54607 //var closeIcon = '<span class="close-hello-bar-icon"><b onclick="' + closeFnName + '">✖</b></span>'; 54608 var closeIcon = '<a class="x-close-img sa-sprite" onclick="' + closeFnName + '" style="float: right; border-bottom: none;"></a>'; 54609 54610 var helloBar = '<div id="hello-bar-generic" class="hello-bar-container ' + $.trim(customClass) + '" style="display:none;"> <p>' 54611 + '<span class="hello-bar-brand hello-bar-brand-left">' + saHtm + '</b></span>' 54612 + '<span class="hello-bar-center">' 54613 + '<span class="hello-bar-label">' + label + '</span>' 54614 + '<span class="hello-bar-buttons">' 54615 + '<span class="btnQuestions btnAdd"><a onclick="SA.POS.Edit.openHelp()">Questions?</a></span>' 54616 + '<span class="btnContact btnAdd"><a onclick="GLO.Log.openContactSAPopup()"> Contact</a> </span>' 54617 + '</span>' 54618 + '</span>' 54619 + '<span class="hello-bar-brand-right">' + closeIcon + '</span>' 54620 + '</p> </div>'; 54621 54622 GLO.Info.displayHelloBarHtm(helloBar); 54623 } 54624 54625 _conPosEdit.changeSortBy = function() { 54626 if (_conPos.sortType === 1) { 54627 $('#sort-product-by-category').prop('checked', true); 54628 $('#pos-product-header-add-category').removeClass('hideX'); 54629 54630 $('#pos-product-header-add-vendor').addClass('hideX'); 54631 } else if (_conPos.sortType === 2) { 54632 $('#sort-product-by-brand').prop('checked', true); 54633 $('#pos-product-header-add-vendor').removeClass('hideX'); 54634 54635 $('#pos-product-header-add-category').addClass('hideX'); 54636 } 54637 } 54638 54639 _conPosEdit.displayForIsEdit = function(grand, parent) { 54640 if (!$('#pos-container').hasClass('edit-pos')) { return; } 54641 54642 if (grand || parent) { 54643 $('#pos-edit-add-buttons').addClass('hide'); 54644 54645 if (_isDisplayServices()) { 54646 var jbox = $(_getBox('sg', grand)); 54647 _conPos.Edit.moveBoxForEdit(jbox); 54648 } else if (_conPos.sortType === 2) { 54649 if (parent) { 54650 var jbox = $(_getBox('pl', parent)); 54651 _conPos.Edit.moveBoxForEdit(jbox, true); 54652 } else { 54653 var jbox = $(_getBox('v', grand)); 54654 _conPos.Edit.moveBoxForEdit(jbox); 54655 } 54656 } else { 54657 if (parent) { 54658 var jbox = $(_getBox('ct', parent)); 54659 _conPos.Edit.moveBoxForEdit(jbox, true); 54660 } else { 54661 var jbox = $(_getBox('c', grand)); 54662 _conPos.Edit.moveBoxForEdit(jbox); 54663 } 54664 } 54665 } else { 54666 $('#pos-edit-add-buttons, #pos-product-header-add-vendor, #pos-product-header-add-category').removeClass('hide'); 54667 $('#pos-header-edit-box').html(''); 54668 } 54669 } 54670 54671 _conPosEdit.moveBoxForEdit = function(jbox, isProductLine) { 54672 //alert(jbox.outerHTML()); 54673 $('#pos-header-edit-box').html(jbox.outerHTML()); 54674 54675 var jbox = $('#pos-header-edit-box').find('.pos-product-box'); 54676 54677 if (_isDisplayServices()) { 54678 jbox.click(SA.POS.Edit.openServiceGroup); 54679 } else if (_conPos.sortType === 2) { 54680 if (isProductLine) { 54681 jbox.click(SA.POS.Edit.openPLine); //GLO.UI.setClick(jbox, null, SA.POS.Edit.openPLine); 54682 } else { 54683 jbox.click(SA.POS.Edit.openVendor); //GLO.UI.setClick(jbox, null, SA.POS.Edit.openVendor); 54684 } 54685 } else { 54686 if (isProductLine) { 54687 jbox.click(SA.POS.Edit.openCategoryType); 54688 } else { 54689 jbox.click(SA.POS.Edit.openCategory); 54690 } 54691 } 54692 } 54693 54694 _conPosEdit.leftHandMode = function(checkbox) { 54695 if ($(checkbox).prop('checked')) { 54696 var isLeft = 1; 54697 $('#pos-container').removeClass('left-ticket'); 54698 } else { 54699 var isLeft = 0; 54700 $('#pos-container').addClass('left-ticket'); 54701 } 54702 54703 var url = GLO.Link.WebsiteDomain + 'pos/LeftHandMode'; 54704 54705 var jqxhr = $.ajax({ type: "POST", dataType: 'json', url: url, data: { "isleft": isLeft }, "cache": false }) 54706 .success(function(data, textStatus, jqXHR) { 54707 54708 }) 54709 .error(function(jqXHR, textStatus, errorThrown) { 54710 54711 }); 54712 } 54713 54714 _conPosEdit.openServiceGroup = function(jbox) { 54715 if (UTIL.isEmptyObject(jbox)) { 54716 jbox = $(this); 54717 } 54718 54719 var sgid = jbox.attr('service_group_id'); 54720 var sg = _conPos.getServiceGroupObject(sgid); 54721 54722 var urlChangeImage = UserPortal.getProviderUri() + 'gallery/ServiceGroup/edit?helloback=pos&isedit=1&imgsize=icon#keyid=' + sgid;
54723 var urlChangeBackground = 'provider/profile/4?sgid=' + sgid + '&edit=color&helloback=pos&isedit=1'; 54724 var aChangeBackground = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeBackground + '\', this, event, true)">'; 54725 54726 var p = '<p class="text-over-background">'; 54727 var msg1 = p + 'P.O.S. uses color from ' + aChangeBackground + 'Profile -> Service</a></p>'; 54728 var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">Service Gallery</a></p>'; 54729 54730 if (!UTIL.isEmpty(sg.image_vc)) { 54731 var imgLabel = 'Change Image', htmChangeBackground = ''; 54732 } else { 54733 var imgLabel = 'Upload Image'; 54734 var htmChangeBackground = '<div style="margin-top: 32px;"><span class="btnAdd">' + aChangeBackground + 'Change Color</a></span></div>'; 54735 } 54736 54737 var htm = msg1 + msg2; 54738 htm += '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeImage + '\', this, event, true)">' + imgLabel + '</a></span></div>'; 54739 htm += htmChangeBackground; 54740 54741 var jpop = GLO.Popup.Custom.openSimple('<div id="pop-pos-edit-service-group" style="min-height: 300px; min-width: 300px;">' + htm + '</div>', sg.name); 54742 jpop.css({ "background-color": "rgb(" + sg["background-color"] + ")" }); 54743 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54744 } 54745 _conPosEdit.openService = function(jbox, serviceId) { 54746 var jbox = $(jbox); 54747 var sgid = jbox.attr('service_group_id'); 54748 var svc = _conPos.getServiceObject(serviceId); 54749 var sg = _conPos.getServiceGroupObject(sgid); 54750 54751 var urlChangeImage = UserPortal.getProviderUri() + 'gallery/' + sg.gallery_uri_key_vc + '/edit?helloback=pos&isedit=1&imgsize=icon&gallery_id=' + sg.gallery_id + '&gallery_key_id=' + sgid + '#keyid=' + serviceId; 54752 var urlChangeBackground = 'provider/profile/4?sgid=' + sgid + '&edit=color&helloback=pos&isedit=1'; 54753 var aChangeBackground = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeBackground + '\', this, event, true)">'; 54754 54755 var p = '<p class="text-over-background">'; 54756 var msg1 = p + 'P.O.S. uses color from ' + aChangeBackground + 'Profile -> Service</a></p>'; 54757 54758 if (!UTIL.isEmpty(svc.image_vc)) { 54759 var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a></p>'; 54760 var htm = '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="' + _getLinkFunction(urlChangeImage) + '">Change Image</a></span></div>'; 54761 } else { 54762 if (UTIL.isEmpty(sg.gallery_id)) { 54763 urlChangeImage = UserPortal.getProviderUri() + 'gallery/new/edit?category=sg' + sgid + '&imgsize=icon&IsHide=1&helloback=pos&isedit=1#keyid=' + serviceId; 54764 var msg2 = p + 'Add <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a> then upload ' + svc.name + ' image to see image in your P.O.S.</p>'; 54765 } else { 54766 var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a></p>'; 54767 } 54768 54769 var htm = '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="' + _getLinkFunction(urlChangeImage) + '">Upload Image</a></span></div>'; 54770 htm += '<div style="margin-top: 32px;"><span class="btnAdd">' + aChangeBackground + 'Change Color</a></span></div>'; 54771 } 54772 54773 var img = jbox.css('background-image').replace('url(', '').replace(')', '').replace(/"/g, '').replace(/'/g, ''); 54774 var htmManageImage = _getManageImageHtm(img); 54775 54776 var jpop = GLO.Popup.Custom.openSimple('<div id="pop-pos-edit-service" style="min-height: 300px; min-width: 300px;">' + msg1 + msg2 + htm + '</div>', svc.name); 54777 jpop.css({ "background-color": "rgb(" + sg["background-color"] + ")" }); 54778 GLO.Popup.Custom.singleButton(jpop, 'Close'); 54779 } 54780 function _getManageImageHtm(imgUrl) { 54781 54782 54783 if (!UTIL.isEmpty(imgUrl)) { 54784 var jimg = $('.pos-popup-sample-box .upload-control-parent').clone(); 54785 jimg.css({ "background-image": "url('" + + "')" }); 54786 return jimg.outerHTML(); 54787 } else {
54788 return $('.pos-popup-sample-box .sa-upload').outerHTML(); 54789 } 54790 } 54791 function _getLinkFunction(url) { 54792 return 'GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)'; //, \'Service Image\' 54793 } 54794 54795 _conPosEdit.openVendor = function() { 54796 var jbox = $(this); 54797 _conPosEdit.openBrandOrPLine(jbox); 54798 } 54799 _conPosEdit.openPLine = function() { 54800 var jbox = $(this); 54801 _conPosEdit.openBrandOrPLine(jbox, true); 54802 } 54803 _conPosEdit.openNewPLine = function() { 54804 _conPosEdit.openBrandOrPLine(null, true); 54805 } 54806 54807 _conPosEdit.openCategory = function() { 54808 var jbox = $(this); 54809 _conPosEdit.openCategoryOrType(jbox); 54810 } 54811 _conPosEdit.openCategoryType = function() { 54812 var jbox = $(this); 54813 _conPosEdit.openCategoryOrType(jbox, true); 54814 } 54815 _conPosEdit.openNewCategoryType = function() { 54816 _conPosEdit.openCategoryOrType(null, true); 54817 } 54818 54819 _conPosEdit.openCategoryOrType = function(jbox, isType) { 54820 var fn, catId = null; 54821 54822 if (jbox && jbox.attr) { 54823 catId = jbox.attr('category_id'); 54824 } 54825 54826 var htm = _getPopupCategoryHtm(); 54827 var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit Category', SA.POS.Edit.saveCategory); 54828 54829 if (isType) { 54830 var jdd = jpop.find('#Existing_Category_id'); 54831 var tr = jpop.find('#ctype-input-row').removeClass('hide'); 54832 54833 _addDD(jdd, SA.POS.inventory_json.categories, SA.Resource.Category); 54834 jdd.find('option[value="new"]').remove(); 54835 54836 if (catId) { //set type: 54837 var ctypeId = jbox.attr('inventory_type_id'); 54838 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", ctypeId); 54839 54840 fn = 'SA.POS.Edit.removeCategoryType'; //if (ctype.product_count === 0) { 54841 54842 jpop.find('h1').text(SA.Resource.EditType); 54843 jpop.find('#Inventory_Type_id').val(ctypeId); 54844 54845 var jname = jpop.find('#Inventory_Type_Name_vc').val(ctype.name).keyup(SA.POS.Edit.setBoxText); 54846 54847 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54848 } else { 54849 catId = UTIL.cleanString($('#pos-header-edit-box .pos-product-box').attr('category_id')); 54850 54851 jpop.find('h1').text(SA.Resource.AddType); 54852 jpop.find('.upload-preview').css({ "text-transform": "capitalize" }); 54853 54854 var jname = jpop.find('#Inventory_Type_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" }); 54855 54856 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54857 } 54858 54859 if (catId) { 54860 tr = jpop.find('#category-select-row').removeClass('hide'); 54861 tr.find('#Existing_Category_id').val(catId); 54862 } else { 54863 jbox = null; 54864 } 54865 } else { 54866 var tr = jpop.find('#category-input-row').removeClass('hide'); 54867 54868 if (catId) { 54869 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catId); 54870 54871 fn = 'SA.POS.Edit.removeCategory'; 54872 54873 jpop.find('h1').text(SA.Resource.EditCategory); 54874 tr.find('#Category_id').val(catId); 54875 var jname = tr.find('#Category_Name_vc').val(category.name).keyup(SA.POS.Edit.setBoxText); 54876 54877 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54878 } else { 54879 jbox = null; 54880 jpop.find('h1').text(SA.Resource.AddCategory); 54881 jpop.find('.upload-preview').css({ "text-transform": "capitalize" }); 54882 54883 var jname = jpop.find('#Category_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" }); 54884 54885 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54886 } 54887 } 54888 54889 if (GLO.Info.isMobile()) { 54890 jpop.find('#Existing_Category_id').find('option:first').text('( ' + SA.Resource.SelectCategory + ' )'); 54891 } 54892 54893 _openFinish(jpop, jbox, fn); 54894 } 54895 54896 function _getPopupCategoryHtm() { 54897 if (_popEditCategory === null) { 54898 var jpop = $('#pos-popup-category'); 54899 _popEditCategory = jpop.outerHTML(); 54900 jpop.remove(); 54901 } 54902 54903 return _popEditCategory; 54904 } 54905 function _getPopupBrandHtm() { 54906 if (_popEditBrand === null) { 54907 var jpop = $('#pos-popup-brand'); 54908 _popEditBrand = jpop.outerHTML(); 54909 jpop.remove(); 54910 } 54911 54912 return _popEditBrand; 54913 } 54914 function _getPopupProductHtm() { 54915 if (_popEditProduct === null) { 54916 var jpop = $('#pos-popup-product'); 54917 _popEditProduct = jpop.outerHTML(); 54918 jpop.remove(); 54919 } 54920 54921 return _popEditProduct; 54922 } 54923 54924 _conPosEdit.openBrandOrPLine = function(jbox, isPLine) { 54925 jbox = $(jbox); 54926 var fn, vendorId = jbox.attr('vendor_id'); 54927 54928 var htm = _getPopupBrandHtm(); 54929 var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit', SA.POS.Edit.saveVendor); 54930 54931 if (isPLine) { 54932 var jdd = jpop.find('#Existing_Vendor_id'); 54933 var tr = jpop.find('#pline-input-row').removeClass('hide'); 54934 54935 _addDD(jdd, SA.POS.inventory_json.vendors, SA.Resource.Brand); 54936 54937 if (vendorId) { //set pline: 54938 var plineId = jbox.attr('product_line_id'); 54939 var pline = _conPos.getPLineObject(plineId); 54940 54941 fn = 'SA.POS.Edit.removePLine'; 54942 54943 jpop.find('h1').text(SA.Resource.EditProductLine); 54944 jpop.find('#Product_Line_id').val(plineId); 54945 jpop.find('#Product_Line_Name_vc').val(pline.name).keyup(SA.POS.Edit.setBoxText); 54946 } else { 54947 vendorId = UTIL.cleanString($('#pos-header-edit-box .pos-product-box').attr('vendor_id')); 54948 54949 jpop.find('h1').text(SA.Resource.AddProductLine); 54950 jpop.find('.upload-preview').css({ "text-transform": "capitalize" }); 54951 54952 var jname = jpop.find('#Product_Line_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" }); 54953 54954 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54955 } 54956 54957 if (vendorId) { //set vendor: 54958 tr = jpop.find('#brand-select-row').removeClass('hide'); 54959 tr.find('#Existing_Vendor_id').val(vendorId); 54960 } else { 54961 jbox = null; 54962 } 54963 } else { 54964 var tr = jpop.find('#brand-input-row').removeClass('hide'); 54965 54966 if (vendorId) { 54967 var vendor = _conPos.getVendorObject(vendorId); 54968 54969 fn = 'SA.POS.Edit.removeVendor'; 54970 54971 jpop.find('h1').text(SA.Resource.EditBrand); 54972 tr.find('#Vendor_id').val(vendorId); 54973 var jname = tr.find('#Vendor_Name_vc').val(vendor.name).keyup(SA.POS.Edit.setBoxText); 54974 54975 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54976 } else { 54977 jbox = null; 54978 jpop.find('h1').text(SA.Resource.AddBrand); 54979 jpop.find('.upload-preview').css({ "text-transform": "capitalize" }); 54980 54981 var jname = jpop.find('#Vendor_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" }); 54982 54983 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 54984 } 54985 } 54986 54987 if (GLO.Info.isMobile()) { 54988 jpop.find('#Existing_Vendor_id').find('option:first').text('( ' + SA.Resource.SelectBrand + ' )'); 54989 } 54990 54991 _openFinish(jpop, jbox, fn); 54992 } 54993 54994 _conPosEdit.openProduct = function(jbox, inventoryId) { 54995 var fn, htm = _getPopupProductHtm(); 54996 var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit Product', SA.POS.Edit.saveProduct); 54997 54998 var jdd = jpop.find('#Existing_Vendor_id'); 54999 _addDD(jdd, SA.POS.inventory_json.vendors, SA.Resource.Brand); 55000 55001 jdd = jpop.find('#Existing_Product_Line_id'); 55002 _addPLineDD(jdd, SA.POS.inventory_json.product_lines, SA.Resource.ProductLine); 55003 55004 jdd = jpop.find('#Unit_id'); 55005 _addUnitDD(jdd, SA.POS.inventory_json.units, SA.Resource.Unit); 55006 55007 _addCategoryAndTypeDD(jpop); 55008 var jbreadcrumb = $('#pos-product-header-breadcrumb'); 55009 55010 if (inventoryId) { 55011 fn = 'SA.POS.Edit.removeProduct'; 55012 var product = _conPos.getProductObject(inventoryId); 55013 55014 jpop.find('h1').text(SA.Resource.EditProduct); 55015 jpop.find('#Inventory_id').val(product.id); 55016 jpop.find('#Existing_Vendor_id').val(product.vendor_id); 55017 55018 var jname = jpop.find('#Name_vc').val(product.label).keyup(SA.POS.Edit.setBoxText).focus(); 55019 55020 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 55021 55022 if (product.product_line_id) { jpop.find('#Existing_Product_Line_id').val(product.product_line_id); }
55023 if (product.size_vc) { jpop.find('#Size_dr').val(product.size_vc); } 55024 if (product.unit_id) { jpop.find('#Unit_id').val(product.unit_id); } 55025 55026 if (product.inventory_type_id || product.category_id) { 55027 var typeId = UTIL.coalesce(product.inventory_type_id, 'c' + product.category_id); 55028 jpop.find('#Inventory_Type_id').val(typeId); 55029 } 55030 55031 if (product.upc_vc) { jpop.find('#UPC_vc').val(product.upc_vc); } 55032 if (product.price_mn) { jpop.find('#Price_mn').val(UTIL.displayMoney(product.price_mn, true)); } 55033 55034 if (product.tax_rate_pct === 0 || (UTIL.isEmpty(product.tax_rate_pct) && UTIL.coalesceMoney(GLO.inventoryTax) === 0) ) { jpop.find('#Not_Taxable_fl').prop('checked', true); } 55035 } else { 55036 jpop.find('h1').text(SA.Resource.AddProduct); 55037 jpop.find('.upload-preview').css({ "text-transform": "capitalize" }); 55038 55039 var jname = jpop.find('#Name_vc').css({ "text-transform": "capitalize" }).keyup(SA.POS.Edit.setBoxText); 55040 55041 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); } 55042 55043 if (_conPos.sortType === 2) { 55044 jpop.find('#Existing_Vendor_id').val(); 55045 jpop.find('#Existing_Product_Line_id').val(); 55046 } else { 55047 var typeId = jbreadcrumb.attr('inventory_type_id'); 55048 var catId = jbreadcrumb.attr('category_id'); 55049 55050 if (typeId || catId) { 55051 jpop.find('#Inventory_Type_id').val(UTIL.coalesce(typeId, 'c' + catId)); 55052 } 55053 } 55054 } 55055 55056 if (GLO.Info.isMobile()) { 55057 jpop.find('#Existing_Vendor_id').find('option:first').text('( ' + SA.Resource.SelectBrand + ' )'); 55058 jpop.find('#Existing_Product_Line_id').find('option:first').text('( ' + SA.Resource.ProductLine + ' )'); 55059 jpop.find('#Inventory_Type_id').find('option:first').text('( ' + SA.Resource.Category + ' / ' + SA.Resource.Type + ' )'); 55060 } else { 55061 //jpop.find('.pop-buttons').css({ "width": "600px", "padding-top": "20px" }); 55062 } 55063 55064 jpop.find('#Existing_Product_Line_id').change(); 55065 _openFinish(jpop, jbox, fn); 55066 } 55067 55068 function _addDD(jdd, arr, label) { 55069 for (var i=0; i < arr.length; i++) { 55070 jdd.append('<option value="' + arr[i].id + '">' + arr[i].name + '</option>'); 55071 } 55072 55073 jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>'); 55074 } 55075 55076 function _addPLineDD(jdd, arr, label) { 55077 for (var i=0; i < arr.length; i++) { 55078 jdd.append('<option value="' + arr[i].id + '" vendor_id="' + UTIL.cleanString(arr[i].vendor_id) + '">' + arr[i].name + '</option>'); 55079 } 55080 55081 jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>'); 55082 } 55083 55084 function _addUnitDD(jdd, arr, label) { 55085 for (var i=0; i < arr.length; i++) { 55086 jdd.append('<option value="' + arr[i].id + '" title="' + arr[i].name + '">' + arr[i].abbreviation_vc + '</option>'); 55087 } 55088 55089 jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>'); 55090 } 55091 55092 function _addCategoryAndTypeDD(jpop) { 55093 var categories = SA.POS.inventory_json.categories; 55094 var types = SA.POS.inventory_json.types; 55095 55096 jdd = jpop.find('#Inventory_Type_id'); 55097 55098 for (var i=0; i < categories.length; i++) { 55099 jdd.append('<option value="c' + categories[i].id + '">' + categories[i].name + '</option>'); 55100 55101 for (var j=0; j < types.length; j++) { 55102 if (categories[i].id === types[j].category_id) { 55103 jdd.append('<option value="' + types[j].id + '">' + categories[i].name + ' / ' + types[j].name + '</option>'); 55104 } 55105 } 55106 } 55107 55108 jdd.append('<option value="new">(+ ' + SA.Resource.NewCategoryType + ' )</option>'); 55109 } 55110 55111 _conPosEdit.setBoxText = function() { 55112 $('.pos-popup-sample-box .pos-product-box > div').text(this.value); 55113 } 55114 55115 function _openFinish(jpop, jbox, deleteFunction) { 55116 if (jbox) { 55117 jpop.find('.pos-product-box > div').text(jbox.find('div').text()); 55118 } else { 55119 jpop.find('.pos-product-box > div').text(''); 55120 } 55121 55122 _openFinish_setBox(jbox); 55123 _openFinish_buttons(jpop, deleteFunction); 55124 _openFinish_fileUpload(jpop, jbox); 55125 55126 var jsave = jpop.find('.btnSave a').css({ "border": "3px solid transparent", "letter-spacing": "2px" }); 55127 jpop.find('input, select, textarea').on('change', function() { jsave.css({ "border": "3px solid Red" }); }); 55128 jpop.find('h1').css({ "letter-spacing": "2px" }); 55129 55130 jpop.find('.modalClose, .btnCancel, .btnSave').click(function() {
55131 $('#jscolor-picker-close-button:visible').mousedown(); 55132 }); 55133 } 55134 55135 function _openFinish_setBox(jbox) { 55136 var jColorPicker = new jscolor.color(document.getElementById('pos-background-color'), {}); 55137 var style = '', backColor = _DEFAULT_BACKGROUND_COLOR, textColor = _DEFAULT_COLOR; 55138 55139 if (jbox) { 55140 var style = UTIL.cleanString(jbox.attr('style')); 55141 55142 if (style.indexOf('background-color:') !== -1) { 55143 backColor = jbox.css("background-color"); 55144 } 55145 } 55146 55147 jColorPicker.fromString(UI.rgbToHex(backColor)); 55148 jColorPicker = new jscolor.color(document.getElementById('pos-text-color'), {}); 55149 55150 if (style.indexOf('color:') !== -1) { 55151 jColorPicker.fromString(UI.rgbToHex(jbox.css("color"))); 55152 } else { 55153 jColorPicker.fromString(UI.rgbToHex(_DEFAULT_COLOR)); 55154 } 55155 } 55156 55157 function _openFinish_buttons(jpop, deleteFunction) { 55158 var mtop = "60px"; 55159 55160 if (jpop.find('#pos-popup-product').length === 1) { width = "24px"; } 55161 55162 var jbtns = jpop.find('.pop-buttons').addClass('basic-mobile-buttons').css({ "margin-top": mtop }); 55163 jbtns.find('.btnCancel').css({ "position": "absolute", "left": "8px", "margin-right": "" }); 55164 55165 cssStyle = 'position: absolute; right: 8px; display: inline-block; margin-left: inherit; margin-right: inherit;'; 55166 55167 jbtns.find('.btnSave').css({ "display": "inline-block", "min-width": "64px", "position": "relative", "right": "inherit", "margin": "0", "text-align": "center" }); 55168 jbtns.append('<span class="btnDelete hide" style="' + cssStyle + '"> <a onclick="' + deleteFunction + '()">' + SA.Resource.Delete + '</a> </span>'); 55169 55170 if (deleteFunction) { 55171 jbtns.find('.btnDelete').removeClass('hide'); 55172 } 55173 } 55174 55175 function _openFinish_fileUpload(jpop, jbox) { 55176 SA.Uploader.init(jpop, SA.POS.Edit.imageUploadComplete); 55177 var jpreview = jpop.find('.upload-preview'); 55178 55179 if (jbox) { var img = UTIL.cleanString(jbox.css("background-image")); } else { var img = ''; } 55180 55181 if (img != '' && img !== 'none') { 55182 var imgUrl = img; 55183
55184 if (imgUrl.indexOf('url(') === 0) { 55185 imgUrl = imgUrl.substring(5, imgUrl.length - 2); 55186 } 55187 55188 var arr = imgUrl.split('/'); //var arr = img.substring(4, img.length-1).split('/'); 55189 var nm = arr[arr.length-1]; 55190 55191 jpreview.css({ "background-image": img }); 55192 jpop.find('.pos-popup-box').addClass('edit-image'); 55193 jpop.find('.sa-upload').attr('file_name_vc', nm); 55194 } else { 55195 jpreview.css({ "background-image": "" }); 55196 jpop.find('.pos-popup-box').removeClass('edit-image'); 55197 jpop.find('.sa-upload').attr('file_name_vc', ''); 55198 } 55199 } 55200 55201 _conPosEdit.editImageUpdateUI = function(fileName, imgid) { 55202 var jupload = $('.pos-popup-box'); 55203 _conPosEdit.imageUploadComplete(jupload, fileName, imgid); 55204 } 55205 55206 _conPosEdit.hideEditImage = function() { 55207 $('#pos-container').removeClass('hide'); 55208 55209 var jpop = $('.pos-popup-box').closest('.glopop.hideX').removeClass('hideX'); 55210 var popID = jpop.attr('id').substring(6); //= glopop0 55211 $('#pop-overlay' + popID).removeClass('hideX'); 55212 } 55213 55214 _conPosEdit.displayEditImage = function() { 55215 $('#pos-container').addClass('hide'); 55216 SA.Uploader.Crop.back(); 55217 55218 var jpop = $('.pos-popup-box').closest('.glopop').addClass('hideX'); 55219 var popID = jpop.attr('id').substring(6); //= glopop0 55220 $('#pop-overlay' + popID).addClass('hideX'); 55221 55222 var src = GLO.Data.cdnDirectory + "upload-folder/" + jpop.find('.sa-upload').attr('file_name_vc'); 55223 var jtarget = $('#crop-image').removeClass('hide'); 55224 55225 setTimeout(function() { 55226 //$('body').append('<img src="' + src + '" onload="loadAndScaleImage(this)"/>'); 55227 55228 jtarget = jtarget.find('img').attr('src', src); 55229 GLO.Image.Crop.init(0, jtarget); 55230 }, 200); 55231 } 55232 55233 _conPosEdit.removeImage = function() { 55234 var css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;'; 55235 var htm = '<div> <h1 class="friendly-msg2">' + SA.Resource.DeleteImage + '?</h1> <div class="friendly-msg2">' + SA.Resource.DeleteImageConfirm + '?</div> </div>'; 55236 new GLO.Popup.Confirm(htm, SA.POS.Edit.removeImageConfirmed); 55237 } 55238 55239 _conPosEdit.removeImageConfirmed = function() { 55240 var jpop = $('.pos-popup-box').closest('.glopop'); 55241 var jbox, jd = {}; 55242 55243 if (jpop.find('#pos-popup-brand').length === 1) { 55244 jd.product_line_id = jpop.find('#Product_Line_id').val(); 55245 jd.vendor_id = jpop.find('#Vendor_id').val(); 55246 55247 if (!UTIL.isEmpty(jd.product_line_id)) { 55248 jbox = _conPos.getPLineObject(jd.product_line_id); 55249 } else { 55250 jbox = _conPos.getVendorObject(jd.vendor_id); 55251 } 55252 } else if (jpop.find('#pos-popup-category').length === 1) { 55253 jd.type_id = jpop.find('#Inventory_Type_id').val(); 55254 jd.category_id = jpop.find('#Category_id').val(); 55255 55256 if (!UTIL.isEmpty(jd.type_id)) { 55257 jbox = _conPos.getObject(SA.POS.inventory_json.types, "id", jd.type_id); 55258 } else { 55259 jbox = _conPos.getObject(SA.POS.inventory_json.categories, "id", jd.category_id); 55260 } 55261 } else if (jpop.find('#pos-popup-product').length === 1) { 55262 jd.inventory_id = jpop.find('#Inventory_id').val(); 55263 jbox = _conPos.getProductObject(jd.inventory_id); 55264 } 55265 55266 var url = GLO.Link.WebsiteDomain + 'pos/RemoveImage'; 55267 var jpop = $('.pos-popup-box').closest('.glopop'); 55268 var jbtn = jpop.find('.btnImageRemove'); 55269 55270 GLO.UI.Form.beginProcessing(jbtn); 55271 55272 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd }) 55273 .success(function(data, textStatus, jqXHR) { 55274 GLO.UI.Form.resetProcessing(jbtn); 55275 _removeImageSuccess(jpop, jbox); 55276 }).error(function(jqXHR, textStatus, errorThrown) { 55277 GLO.UI.Form.resetProcessing(jbtn); 55278 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55279 }); 55280 } 55281 55282 function _removeImageSuccess(jpop, jbox) { 55283 jpop.find('.upload-preview').css({ "background-image": "" }); 55284 jpop.find('.btnSave > a').css({ "border": "3px solid transparent" }); 55285 55286 jpop.find('.upload-control-parent').addClass('hide'); 55287 jpop.find('.sa-upload').removeClass('hide').removeAttr('file_name_vc'); 55288 55289 jbox.image_vc = ''; 55290 55291 //_conPosEdit.imageUploadComplete(jpop, '', jbox.id); 55292 _clickBreadcrumbEnd(null, null, true); 55293 55294 jpop.find('.pos-popup-box').removeClass('edit-image'); 55295 } 55296 55297 _conPosEdit.openNewPopup = function(label, boxType, element, parentId) {
55298 var selector = '.glopop #' + element.id; 55299 element.value = ''; 55300 55301 var htm = $('<div id="pos-add-new-popup" box_type="' + boxType + '" selector="' + selector + '" parent_id="' + UTIL.cleanString(parentId) + '" style="margin-bottom: 16px; text-align: center;">' 55302 + '<h1>' + label + '</h1> <input type="text" id="add_new_vc" style="width: 200px;"/> </div>'); 55303 55304 var jpop = new GLO.Popup.Custom(htm, function() { SA.POS.Edit.saveAdd(selector, boxType, parentId); }).getPopup().addClass('no-persist'); 55305 var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2'); 55306 } 55307 55308 _conPosEdit.changeVendor = function(element) { 55309 if (element.value === 'new') { 55310 _conPosEdit.openNewPopup(SA.Resource.AddNewBrand, 'v', element); 55311 $('#pos-popup-product #Existing_Product_Line_id').val(''); 55312 } else { 55313 var jpl = $('#pos-popup-product #Existing_Product_Line_id'); 55314 55315 if (_plineDD === null) { _plineDD = $(jpl.outerHTML()); } 55316 55317 if (element.value === '') { 55318 var newDD = _plineDD.outerHTML(); 55319 } else { 55320 var plOptions = _plineDD.find('option[vendor_id="' + element.value + '"]'); 55321 var newDD = _plineDD.find('option:first').outerHTML(); 55322 var vid = parseInt(element.value); 55323 55324 for (var i=0; i < plOptions.length; i++) { 55325 if (vid === parseInt(plOptions.eq(i).attr('vendor_id'))) { 55326 newDD += plOptions.eq(i).outerHTML(); 55327 } 55328 } 55329 55330 newDD += _plineDD.find('option:last').outerHTML(); 55331 } 55332 55333 jpl.html(newDD); 55334 } 55335 } 55336 55337 _conPosEdit.changePLine = function(element) { 55338 var jbrand = $('#pos-popup-product #Existing_Vendor_id'); 55339 55340 if (element.value === 'new') { 55341 if (!UTIL.isEmpty(jbrand.val())) { 55342 var brandName = jbrand.find('option:selected').text(); 55343 var brandId = jbrand.val(); 55344 55345 _conPosEdit.openNewPopup(SA.Resource.New + ' ' + brandName + ' ' + SA.Resource.ProductLine, 'pl', element, brandId); 55346 } else { 55347 new GLO.Popup.Warning(SA.Resource.PleaseSelectBrandMessage, function() { jbrand.focus(); }); 55348 element.value = ''; 55349 } 55350 } else { 55351 var plid = element.value; 55352 jbrand.val(jbrand.val()).change(); 55353 element.value = plid; 55354 } 55355 } 55356 55357 _conPosEdit.changeUnit = function(element) { 55358 if (element.value === 'new') { 55359 _conPosEdit.openNewPopup(SA.Resource.AddNewUnit, 'u', element); 55360 55361 var jpop = $('#pos-add-new-popup').closest('.glopop'); 55362 var jnm = jpop.find('#add_new_vc'); 55363 55364 jnm.before('<div style="margin-bottom: 20px;"> <label for="Abbreviation_vc">' + SA.Resource.Abbreviation + '</label> <input type="text" id="Abbreviation_vc" style="width: 80px;" maxlength="5"></select> </div>'); 55365 } 55366 } 55367 55368 _conPosEdit.changeCategoryType = function(element) { 55369 if (element.value === 'new') { 55370 var jpop = $('#pos-add-new-popup').closest('.glopop'); 55371 GLO.Popup.close(jpop); 55372 55373 jpop = $('#pos-popup-product').closest('.glopop'); 55374 element = jpop.find('#Inventory_Type_id')[0]; 55375 55376 _conPosEdit.openNewPopup(SA.Resource.AddNewCategoryType, 'ct', element); 55377 55378 var categories = SA.POS.inventory_json.categories; 55379 var catDD = '<select id="Type_Category_id" class="glopop-first" onchange="SA.POS.Edit.changeCategory(this)" style="width: 200px;">'; 55380 55381 for (var i=0; i < categories.length; i++) { 55382 catDD += '<option value="' + categories[i].id + '">' + categories[i].name + '</option>'; 55383 } 55384 55385 catDD += '<option value="new">(+ ' + SA.Resource.NewCategory + ')</option> </categories>'; 55386 55387 var jAddNewPop = $('#pos-add-new-popup').closest('.glopop'); 55388 jAddNewPop.find('#add_new_vc').replaceWith('<div id="new-type-row"> <label for="add_new_vc">' + SA.Resource.Type + '</label>' + jAddNewPop.find('#add_new_vc').removeClass('glopop-first').outerHTML() + '</div>'); 55389 jAddNewPop.find('#new-type-row').before('<div style="margin-bottom: 20px;"> <label for="Type_Category_id">' + SA.Resource.Category + '</label>' + catDD + '</div>'); 55390 55391 if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { 55392 jAddNewPop.find('#Type_Category_id').focus(); 55393 } 55394 55395 jAddNewPop.find('label').css({ "display": "inline-block", "width": "80px", "text-align": "center" }); 55396 } 55397 } 55398 55399 _conPosEdit.changeCategory = function(element) { 55400 if (element.value === 'new') { 55401 var jAddNewPop = $('#pos-add-new-popup').closest('.glopop'); 55402 jAddNewPop.find('#Type_Category_id').replaceWith('<input type="text" id="Type_Category_id" class="glopop-first" style="width: 200px;">'); 55403 } 55404 } 55405
55406 _conPosEdit.changeBackgroundColor = function(thisElement) { 55407 document.getElementById('pos-background-color').color.showPicker(); 55408 55409 if (event.x && event.y) { 55410 $('#jscolor-picker-box').css({ "top": (event.y - 20), "left": (event.x - 20) }); 55411 } 55412 } 55413 55414 _conPosEdit.changeTextColor = function(thisElement) { 55415 document.getElementById('pos-text-color').color.showPicker(); 55416 55417 if (event.x && event.y) { 55418 $('#jscolor-picker-box').css({ "top": (event.y - 50), "left": (event.x - 20) }); 55419 } 55420 } 55421 55422 _conPosEdit.removeCategory = function() { 55423 var jpop = $('#pos-popup-category').closest('.glopop'); 55424 var catId = jpop.find('#Category_id').val(); 55425 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catId); 55426 55427 if (category.type_count !== 0) { 55428 var msg = '<div class="friendly-msg2">Please remove the ' + category.type_count + ' types associated with this category<br/>(or move them to a different category)</div>'; 55429 new GLO.Popup.Warning(msg); 55430 return; 55431 } else if (category.total_product_count !== 0) { 55432 var msg = '<div class="friendly-msg2">Please remove the ' + category.product_count + ' products associated with this category<br/>(or change the product\'s type)</div>'; 55433 new GLO.Popup.Warning(msg); 55434 return; 55435 } 55436 55437 var url = GLO.Link.WebsiteDomain + 'pos/RemoveCategory'; 55438 var jsave = jpop.find('.btnSave'); 55439 GLO.UI.Form.beginProcessing(jsave); 55440 55441 $.ajax({ "type": "POST", "url": url, "cache": false, data: { "category_id": catId } }) 55442 .success(function(data, textStatus, jqXHR) { 55443 GLO.UI.Form.resetProcessing(jsave); 55444 GLO.Popup.close(jpop); 55445 55446 _removeSuccessful('c', catId); 55447 }).error(function(jqXHR, textStatus, errorThrown) { 55448 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55449 }); 55450 } 55451 55452 _conPosEdit.removeCategoryType = function() { 55453 var jpop = $('#pos-popup-category').closest('.glopop'); 55454 var ctid = jpop.find('#Inventory_Type_id').val(); 55455 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", ctid); 55456 55457 if (ctype.product_count > 0) { 55458 new GLO.Popup.Warning('Please remove the ' + ctype.product_count + ' products associated with this type (or change the products type)'); 55459 return; 55460 } 55461 55462 var url = GLO.Link.WebsiteDomain + 'pos/RemoveCategoryType'; 55463 var jsave = jpop.find('.btnSave'); 55464 GLO.UI.Form.beginProcessing(jsave); 55465 55466 $.ajax({ "type": "POST", "url": url, "cache": false, data: { "inventory_type_id": ctid } }) 55467 .success(function(data, textStatus, jqXHR) { 55468 GLO.UI.Form.resetProcessing(jsave); 55469 GLO.Popup.close(jpop); 55470 55471 _removeSuccessful('ct', ctid); 55472 }).error(function(jqXHR, textStatus, errorThrown) { 55473 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55474 }); 55475 } 55476 55477 _conPosEdit.removeVendor = function() { 55478 var jpop = $('#pos-popup-brand').closest('.glopop'); 55479 var vid = jpop.find('#Vendor_id').val(); 55480 var vendor = _conPos.getVendorObject(vid); 55481 55482 if (vendor.product_line_count !== 0) { 55483 var msg = '<div class="friendly-msg2">
55483Please remove the ' + vendor.product_line_count + ' product lines associated with this brand<br/>(or move them to a different brand)</div>'; 55484 new GLO.Popup.Warning(msg); 55485 return; 55486 } else if (vendor.total_product_count !== 0) { 55487 var msg = '<div class="friendly-msg2">Please remove the ' + vendor.total_product_count + ' products associated with this brand<br/>(or change the product\'s brand)</div>'; 55488 new GLO.Popup.Warning(msg); 55489 return; 55490 } 55491 55492 var url = GLO.Link.WebsiteDomain + 'pos/RemoveVendor'; 55493 var jsave = jpop.find('.btnSave'); 55494 GLO.UI.Form.beginProcessing(jsave); 55495 55496 $.ajax({ "type": "POST", "url": url, "cache": false, data: { "vendor_id": vid } }) 55497 .success(function(data, textStatus, jqXHR) { 55498 GLO.UI.Form.resetProcessing(jsave); 55499 GLO.Popup.close(jpop); 55500 55501 _removeSuccessful('v', vid); 55502 }).error(function(jqXHR, textStatus, errorThrown) { 55503 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55504 }); 55505 } 55506 55507 _conPosEdit.removePLine = function() { 55508 var jpop = $('#pos-popup-brand').closest('.glopop'); 55509 var plid = jpop.find('#Product_Line_id').val(); 55510 var pline = _conPos.getPLineObject(plid); 55511 55512 if (pline.product_count !== 0) { 55513 var msg = '<div class="friendly-msg2">Please remove the ' + pline.product_count + ' products associated with this product line<br/>(or move them to a different product line)</div>'; 55514 new GLO.Popup.Warning(msg); 55515 return; 55516 } 55517 55518 var url = GLO.Link.WebsiteDomain + 'pos/RemovePLine'; 55519 var jsave = jpop.find('.btnSave'); 55520 GLO.UI.Form.beginProcessing(jsave); 55521 55522 $.ajax({ "type": "POST", "url": url, "cache": false, data: { "product_line_id": plid } }) 55523 .success(function(data, textStatus, jqXHR) { 55524 GLO.UI.Form.resetProcessing(jsave); 55525 GLO.Popup.close(jpop); 55526 55527 _removeSuccessful('pl', plid); 55528 }).error(function(jqXHR, textStatus, errorThrown) { 55529 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55530 }); 55531 } 55532 55533 _conPosEdit.removeProduct = function() { 55534 var url = GLO.Link.WebsiteDomain + 'pos/RemoveProduct'; 55535 var jpop = $('#pos-popup-product').closest('.glopop'); 55536 var iid = jpop.find('#Inventory_id').val(); 55537 55538 var jsave = jpop.find('.btnSave'); 55539 GLO.UI.Form.beginProcessing(jsave); 55540 55541 $.ajax({ "type": "POST", "url": url, "cache": false, data: { "inventory_id": iid } }) 55542 .success(function(data, textStatus, jqXHR) { 55543 GLO.UI.Form.resetProcessing(jsave); 55544 GLO.Popup.close(jpop); 55545 55546 _removeSuccessful('i', iid); 55547 }).error(function(jqXHR, textStatus, errorThrown) { 55548 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55549 }); 55550 } 55551 55552 function _removeSuccessful(boxtype, id) { 55553 if (boxtype === 'i') { 55554 var jcrumb = $('#pos-product-header-breadcrumb'); 55555 var vid = jcrumb.attr('vendor_id'); 55556 var plid = jcrumb.attr('product_line_id'); 55557 var products = SA.POS.inventory_json.products; 55558 55559 for (var i=0; i < products.length; i++) { 55560 if (id == products[i].id) { 55561 if (products[i].vendor_id) { 55562 var vendor = _conPos.getVendorObject(products[i].vendor_id); 55563 --vendor.total_product_count; 55564 55565 if (products[i].product_line_id) { 55566 --_conPos.getPLineObject(products[i].product_line_id).product_count; 55567 } else { 55568 --vendor.product_count; 55569 } 55570 } 55571 55572 if (products[i].category_id) { 55573 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", products[i].category_id); 55574 --category.total_product_count; 55575
55576 if (products[i].inventory_type_id) { 55577 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", products[i].inventory_type_id); 55578 --ctype.product_count; 55579 } else { 55580 --category.product_count; 55581 } 55582 } 55583 55584 products.splice(i, 1); 55585 break; 55586 } 55587 } 55588 55589 _clickBreadcrumbEnd(vid, plid, true); 55590 } else if (boxtype === 'pl') { 55591 var vid, plines = SA.POS.inventory_json.product_lines; 55592 55593 for (var i=0; i < plines.length; i++) { 55594 if (id == plines[i].id) { 55595 vid = plines[i].vendor_id; 55596 plines.splice(i, 1); 55597 55598 --_conPos.getVendorObject(vid).product_line_count; 55599 break; 55600 } 55601 } 55602 55603 _clickBreadcrumbEnd(vid, null, true); 55604 } else if (boxtype === 'v') { 55605 var vendors = SA.POS.inventory_json.vendors; 55606 55607 for (var i=0; i < vendors.length; i++) { 55608 if (id == vendors[i].id) { 55609 vendors.splice(i, 1); 55610 break; 55611 } 55612 } 55613 55614 _clickBreadcrumbEnd(null, null, true); 55615 } else if (boxtype === 'ct') { 55616 var catid, ctypes = SA.POS.inventory_json.types; 55617 55618 for (var i=0; i < ctypes.length; i++) { 55619 if (id == ctypes[i].id) { 55620 catid = ctypes[i].category_id; 55621 ctypes.splice(i, 1); 55622 55623 --_conPos.getObject(SA.POS.inventory_json.categories, "id", catid).type_count; 55624 break; 55625 } 55626 } 55627 55628 _clickBreadcrumbEnd(catid, null, true); 55629 } else if (boxtype === 'c') { 55630 var categories = SA.POS.inventory_json.categories; 55631 55632 for (var i=0; i < categories.length; i++) { 55633 if (id == categories[i].id) { 55634 categories.splice(i, 1); 55635 break; 55636 } 55637 } 55638 55639 _clickBreadcrumbEnd(null, null, true); 55640 } 55641 } 55642 55643 _conPosEdit.saveAdd = function(selector, boxtype, parentId) { 55644 var jpop = $('#pos-add-new-popup').closest('.glopop'); 55645 var nm = jpop.find('#add_new_vc').val(); 55646 var jdata = { "box_type": boxtype, "name_vc": nm, "parent_id": parentId }; 55647 55648 if (UTIL.isEmpty(nm)) { 55649 new GLO.Popup.Warning(SA.Resource.CannotBeBlank, function(){ jpop.find('#add_new_vc').focus(); }); 55650 return; 55651 } 55652 55653 if (boxtype === 'ct') { 55654 var category = jpop.find('#Type_Category_id').val(); 55655 55656 if (UTIL.isEmpty(category)) { 55657 new GLO.Popup.Warning(SA.Resource.PleaseEnterValue, function(){ jpop.find('#Type_Category_id').focus(); }); 55658 return; 55659 } else if (!UTIL.isNumber(category)) { //= new category name, not existing category. 55660 jdata = { "box_type": boxtype, "name_vc": nm, "type_category_name_vc": category }; 55661 parentId = undefined; 55662 } 55663 } else if (boxtype === 'u') { 55664 jdata.abbreviation_vc = jpop.find('#Abbreviation_vc').val(); 55665 } 55666 55667 var url = GLO.Link.WebsiteDomain + 'pos/SaveAdd'; 55668 var jsave = jpop.find('.btnSave'); 55669 GLO.UI.Form.beginProcessing(jsave); 55670 55671 $.ajax({ "type": "POST", "url": url, "cache": false, data: jdata }) 55672 .success(function(data, textStatus, jqXHR) { 55673 GLO.UI.Form.resetProcessing(jsave); 55674 GLO.Popup.close(jpop); 55675 55676 _saveAddSuccessful(boxtype, data, selector); 55677 }).error(function(jqXHR, textStatus, errorThrown) { 55678 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55679 }); 55680 } 55681 55682 function _saveAddSuccessful(boxtype, data, selector) { 55683 var jdata = $(data); 55684 var id = parseInt(jdata.attr('id')); 55685 var nm = jdata.attr('name'); 55686 var jdd = $(selector); 55687 55688 if (boxtype === 'v') { 55689 SA.POS.inventory_json.vendors.push({ "id": id, "name": nm, "background-color": "", "color": "", "image_vc": "", "product_line_count": 0, "product_count": 0, "total_product_count": 0 }); 55690 55691 jdd.find('option[value="new"]').before('<option value="' + id + '">' + nm + '</option>'); 55692 55693 _clickBreadcrumbEnd(id, null, true); 55694 } else if (boxtype === 'pl') { 55695 var vid = parseInt(jdata.attr('parent_id')); 55696 var opt = '<option value="' + id + '" vendor_id="' + vid + '">' + nm + '</option>'; 55697 55698 ++_conPos.getVendorObject(vid).product_line_count; 55699 SA.POS.inventory_json.product_lines.push({ "id": id, "name": nm, "vend
55699or_id": vid, "background-color": "", "color": "", "image_vc": "", "product_count": 0 }); 55700 55701 jdd.find('option[value="new"]').before(opt); 55702 _plineDD.append(opt); 55703 55704 _clickBreadcrumbEnd(vid, id, true); 55705 } else if (boxtype === 'u') { 55706 var abbreviation = jdata.attr('abbreviation_vc'); 55707 SA.POS.inventory_json.units.push({ "id": id, "name": nm, "abbreviation_vc": abbreviation }); 55708 55709 jdd.find('option[value="new"]').before('<option value="' + id + '" title="' + nm + '">' + abbreviation + '</option>'); 55710 } else if (boxtype === 'ct') { 55711 var typeCategoryId = parseInt(jdata.attr('parent_id')); 55712 var typeCategoryName = UTIL.cleanString(jdata.attr('type_category_name_vc')); 55713 55714 if (typeCategoryName === '') { 55715 typeCategoryName = _conPos.getObject(SA.POS.inventory_json.categories, "id", typeCategoryId).name; 55716 } else { 55717 SA.POS.inventory_json.categories.push({ "id": typeCategoryId, "name": typeCategoryName }); 55718 } 55719 55720 SA.POS.inventory_json.types.push({ "id": id, "name": nm, "category_id": typeCategoryId }); 55721 55722 jdd.find('option[value="new"]').before('<option value="' + id + '">' + typeCategoryName + ' / ' + nm + '</option>'); 55723 jdd.find('option[value="' + id + '"]').prop('selected', 'selected'); 55724 } 55725 55726 jdd.val(id).change(); 55727 } 55728 55729 _conPosEdit.saveVendor = function() { 55730 var jpop = $('#pos-popup-brand').closest('.glopop'); 55731 var vnm = jpop.find('#Vendor_Name_vc:visible'); 55732 55733 if (vnm.length > 0) { 55734 var vid = jpop.find('#Vendor_id').val(); 55735 var jd = { "boxtype": "v", "vendor_id": vid, "vendor_name_vc": vnm.val() }; 55736 } else { 55737 var vid = jpop.find('#Existing_Vendor_id').val(); 55738 var plid = jpop.find('#Product_Line_id').val(); 55739 var plnm = jpop.find('#Product_Line_Name_vc').val(); 55740
55741 var jd = { "boxtype": "pl", "vendor_id": vid, "product_line_id": plid, "product_line_name_vc": plnm }; 55742 } 55743 55744 var jbox = jpop.find('.pos-popup-sample-box .pos-product-box'); 55745 jd.background_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("background-color")).replace('rgb(', '').replace(')', ''), ' ', ''); //jpop.find('#pos-background-color').val(); 55746 jd.text_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("color")).replace('rgb(', '').replace(')', ''), ' ', ''); //jpop.find('#pos-text-color').val(); 55747 jd.file_name_vc = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc')); 55748 55749 if ('rgb(' + jd.text_color_vc + ')' === _DEFAULT_COLOR) { jd.text_color_vc = ''; } 55750 if ('rgb(' + jd.background_color_vc + ')' === _DEFAULT_BACKGROUND_COLOR) { jd.background_color_vc = ''; } 55751 55752 var url = GLO.Link.WebsiteDomain + 'pos/Vendor'; 55753 var jsave = jpop.find('.btnSave'); 55754 GLO.UI.Form.beginProcessing(jsave); 55755 55756 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd }) 55757 .success(function(data, textStatus, jqXHR) { 55758 GLO.UI.Form.resetProcessing(jsave); 55759 GLO.Popup.close(jpop); 55760 55761 _saveVendorSuccessful(jd, data); 55762 }).error(function(jqXHR, textStatus, errorThrown) { 55763 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55764 }); 55765 } 55766 55767 _conPosEdit.saveCategory = function() { 55768 var jpop = $('#pos-popup-category').closest('.glopop'); 55769 var catnm = jpop.find('#Category_Name_vc:visible'); 55770 55771 if (catnm.length > 0) { 55772 var catid = jpop.find('#Category_id').val(); 55773 var jd = { "boxtype": "c", "category_id": catid, "category_name_vc": catnm.val() }; 55774 } else { 55775 var catid = jpop.find('#Existing_Category_id').val(); 55776 var ctid = jpop.find('#Inventory_Type_id').val(); 55777 var ctnm = jpop.find('#Inventory_Type_Name_vc').val(); 55778 55779 var jd = { "boxtype": "ct", "category_id": catid, "inventory_type_id": ctid, "type_name_vc": ctnm }; 55780 } 55781 55782 var jbox = jpop.find('.pos-popup-sample-box .pos-product-box'); 55783 jd.background_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("background-color")).replace('rgb(', '').replace(')', ''), ' ', ''); //jpop.find('#pos-background-color').val(); 55784 jd.text_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("color")).replace('rgb(', '').replace(')', ''), ' ', ''); //jpop.find('#pos-text-color').val(); 55785 jd.file_name_vc = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc')); 55786 55787 if ('rgb(' + jd.text_color_vc + ')' === _DEFAULT_COLOR) { jd.text_color_vc = ''; } 55788 if ('rgb(' + jd.background_color_vc + ')' === _DEFAULT_BACKGROUND_COLOR) { jd.background_color_vc = ''; } 55789 55790 var url = GLO.Link.WebsiteDomain + 'pos/Category'; 55791 var jsave = jpop.find('.btnSave'); 55792 GLO.UI.Form.beginProcessing(jsave); 55793 55794 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd }) 55795 .success(function(data, textStatus, jqXHR) { 55796 GLO.UI.Form.resetProcessing(jsave); 55797 GLO.Popup.close(jpop); 55798 55799 _saveCategorySuccessful(jd, data); 55800 }).error(function(jqXHR, textStatus, errorThrown) { 55801 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55802 }); 55803 } 55804 55805 _conPosEdit.saveProduct = function() { 55806 var jpop = $('#pos-popup-product').closest('.glopop'); 55807 55808 var id = UTIL.cleanString(jpop.find('#Inventory_id').val()); 55809 var nm = jpop.find('#Name_vc').val(); 55810 var vid = UTIL.cleanString(jpop.find('#Existing_Vendor_id').val()); 55811 var plid = UTIL.cleanString(jpop.find('#Existing_Product_Line_id').val()); 55812 55813 var price = UTIL.cleanString(jpop.find('#Price_mn').val()); 55814 var size = UTIL.cleanString(jpop.find('#Size_dr').val()); 55815 var unit = UTIL.cleanString(jpop.find('#Unit_id').val()); 55816 55817 var typeCategory = UTIL.cleanString(jpop.find('#Inventory_Type_id').val()); //var category = jpop.find('#Inventory_Type_id').find('option:selected').attr('category_id'); 55818 var upc = UTIL.cleanString(jpop.find('#UPC_vc').val()); 55819 var imgFileName = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc')); 55820 55821 if (!UTIL.isEmpty(typeCategory) && typeCategory.substring(0, 1) === 'c') { 55822 var categoryId = typeCategory.substring(1); 55823 typeCategory = ''; 55824 } else { 55825 var categoryId = ''; 55826 } 55827 55828 if (UTIL.isEmpty(nm)) { 55829 new GLO.Popup.Warning(SA.Resource.PleaseEnterProductName, function() { jpop.find('#Name_vc').focus(); }); 55830 return; 55831 } 55832
55833 var jinput = { "inventory_id": id, "name_vc": nm, "vendor_id": vid, "product_line_id": plid, "price_mn": price 55834 , "size_dr": size, "unit_id": unit, "inventory_type_id": typeCategory, "category_id": categoryId 55835 , "upc_vc": upc, "image_vc": imgFileName }; 55836 55837 if (jpop.find('#Not_Taxable_fl').prop('checked')) { jinput.not_taxable_fl = 1; } 55838 55839 var url = GLO.Link.WebsiteDomain + 'pos/Product'; 55840 var jsave = jpop.find('.btnSave'); 55841 GLO.UI.Form.beginProcessing(jsave); 55842 55843 $.ajax({ "type": "POST", "url": url, "cache": false, data: jinput }) 55844 .success(function(data, textStatus, jqXHR) { 55845 GLO.UI.Form.resetProcessing(jsave); 55846 GLO.Popup.close(jpop); 55847 55848 var jout = $(data); 55849 55850 if (UTIL.isNumber(jinput.inventory_id)) { 55851 _updateProductSuccessful(jinput, jout); 55852 } else { 55853 _insertProductSuccessful(jinput, jout); 55854 } 55855 }).error(function(jqXHR, textStatus, errorThrown) { 55856 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 55857 }); 55858 } 55859 55860 function _updateProduct_VendorChanged(product, oldVendorId, newVendorId, oldPLineId, newPLineId) { 55861 if (UTIL.coalesceInt(oldVendorId, -1) === UTIL.coalesceInt(newVendorId, -1)) { return; } 55862 55863 product.vendor_id = UTIL.cleanString(newVendorId); 55864 var vendor = _conPos.getVendorObject(newVendorId); 55865 55866 if (vendor) { 55867 ++vendor.total_product_count; 55868 55869 if (UTIL.isEmpty(newPLineId)) { ++vendor.product_count; } 55870 } 55871 55872 if (_conPos.sortType === 2) { 55873 if (vendor) { 55874 product["background-color"] = UTIL.cleanString(vendor["background-color"]); 55875 product.color = UTIL.cleanString(vendor.color); 55876 } else { 55877 product["background-color"] = product.color = ''; 55878 } 55879 } 55880 55881 var oldVendor = _conPos.getVendorObject(oldVendorId); 55882 55883 if (oldVendor) { 55884 --oldVendor.total_product_count; 55885 55886 if (!UTIL.isEmpty(oldPLineId)) { 55887 //--_conPos.getPLineObject(oldPLineId).product_count; //handled by _updateProduct_PLineChanged() 55888 } else { 55889 --oldVendor.product_count; 55890 } 55891 } 55892 } 55893 55894 function _updateProduct_PLineChanged(product, newVendorId, oldPLineId, newPlineId) { 55895 if (UTIL.coalesceInt(oldPLineId, -1) === UTIL.coalesceInt(newPlineId, -1)) { return; } 55896 55897 product.product_line_id = UTIL.cleanString(newPlineId); 55898 55899 if (newPlineId) { 55900 var pline = _conPos.getPLineObject(newPlineId); 55901 ++pline.product_count; 55902 55903 if (_conPos.sortType === 2) { 55904 var vendor = _conPos.getVendorObject(newVendorId); 55905 55906 product["background-color"] = UTIL.cleanString(UTIL.coalesce(pline["background-color"], vendor["background-color"])); 55907 product.color = UTIL.cleanString(UTIL.coalesce(pline.color, vendor.color)); 55908 } 55909 } 55910 55911 if (!UTIL.isEmpty(oldPLineId)) { 55912 var pline = _conPos.getPLineObject(oldPLineId); 55913 --pline.product_count; 55914 } 55915 } 55916 55917 function _updateProduct_CategoryChanged(product, oldCategoryId, newCategoryId, oldTypeId, newTypeId) { 55918 if (UTIL.isEmpty(newCategoryId) && newTypeId) { newCategoryId = _conPos.getObject(SA.POS.inventory_json.types, "id", newTypeId).category_id; } 55919 55920 if (UTIL.coalesceInt(oldCategoryId, -1) === UTIL.coalesceInt(newCategoryId, -1)) { return; } 55921 55922 if (newCategoryId) { 55923 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId); 55924 ++category.total_product_count; 55925 55926 if (UTIL.isEmpty(newTypeId)) { ++category.product_count; } 55927 55928 product.category_id = newCategoryId; 55929 55930 if (_conPos.sortType === 1) { 55931 product["background-color"] = UTIL.cleanString(category["background-color"]); 55932 product.color = UTIL.cleanString(category.color); 55933 } 55934 } else { 55935 product.category_id = ''; 55936 55937 if (_conPos.sortType === 1) { product["background-color"] = product.color = ''; } 55938 } 55939 55940 if (oldCategoryId) { 55941 var oldCategory = _conPos.getObject(SA.POS.inventory_json.categories, "id", oldCategoryId); 55942 --oldCategory.total_product_count; 55943 55944 if (!UTIL.isEmpty(oldTypeId)) { 55945 --_conPos.getObject(SA.POS.inventory_json.types, "id", oldTypeId).product_count; 55946 } else { 55947 --oldCategory.product_count; 55948 } 55949 } 55950 } 55951 55952 function _updateProduct_CategoryTypeChanged(product, newCategoryId, oldTypeId, newT
55952ypeId) { 55953 if (UTIL.coalesceInt(oldTypeId, -1) === UTIL.coalesceInt(newTypeId, -1)) { return; } 55954 55955 product.inventory_type_id = UTIL.cleanString(newTypeId); 55956 55957 if (newTypeId) { 55958 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", newTypeId); 55959 ++ctype.product_count; 55960 55961 product.type_name_vc = UTIL.cleanString(ctype.name); 55962 55963 if (_conPos.sortType === 1) { 55964 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId); 55965 55966 product["background-color"] = UTIL.cleanString(UTIL.coalesce(ctype["background-color"], category["background-color"])); 55967 product.color = UTIL.cleanString(UTIL.coalesce(ctype.color, category.color)); 55968 } 55969 } else { 55970 product.type_name_vc = ''; 55971 } 55972 55973 if (!UTIL.isEmpty(oldTypeId)) { 55974 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", oldTypeId); 55975 --ctype.product_count; 55976 } 55977 } 55978 55979 function _updateProductSuccessful(jinput, jout) { 55980 var inventoryId = parseInt(jout.attr('id')); 55981 var product = _conPos.getProductObject(inventoryId); 55982 55983 product.label = jinput.name_vc; 55984 product.image_vc = UTIL.cleanString(jinput.image_vc); 55985 55986 if (UTIL.parseBool(jinput.not_taxable_fl)) { product.tax_rate_pct = 0; } else { delete product.tax_rate_pct; } 55987 55988 _updateProduct_VendorChanged(product, product.vendor_id, jinput.vendor_id, product.product_line_id, jinput.product_line_id); 55989 _updateProduct_PLineChanged(product, jinput.vendor_id, product.product_line_id, jinput.product_line_id); 55990 55991 _updateProduct_CategoryChanged(product, product.category_id, jinput.category_id, product.inventory_type_id, jinput.inventory_type_id); 55992 _updateProduct_CategoryTypeChanged(product, jinput.category_id, product.inventory_type_id, jinput.inventory_type_id); 55993 55994 product.upc_vc = UTIL.cleanString(jinput.upc_vc); 55995 product.size_vc = UTIL.cleanString(jinput.size_dr); 55996 product.price_mn = UTIL.displayMoney(UTIL.cleanString(jinput.price_mn), true); 55997 product.unit_id = UTIL.cleanString(jinput.unit_id); 55998 product.css_class_vc = jout.attr('css_class'); 55999 56000 if (_conPos.sortType === 2) { //add box to UI (if matches current filter) 56001 _clickBreadcrumbEnd(product.vendor_id, product.product_line_id, true); 56002 } else { 56003 _clickBreadcrumbEnd(product.category_id, product.inventory_type_id, true); 56004 } 56005 } 56006 56007 function _insertProductSuccessful(jinput, jout) { 56008 var plid = UTIL.cleanString(jinput.product_line_id); 56009 var inventoryId = parseInt(jout.attr('id')); 56010 56011 var json = { "id": inventoryId, "label": jout.attr('name'), "css_class_vc": jout.attr('css_class') }; 56012 56013 if (jinput.vendor_id) { 56014 json.vendor_id = parseInt(jinput.vendor_id); 56015 56016 var vendor = _conPos.getVendorObject(jinput.vendor_id); 56017 ++vendor.total_product_count; 56018 56019 if (vendor["background-color"]) { json["background-color"] = vendor["background-color"]; } 56020 if (vendor.color) { json.color = vendor.color; } 56021 56022 if (jinput.product_line_id) { 56023 json.product_line_id = plid; 56024 var pline = _conPos.getPLineObject(plid); 56025 56026 json["background-color"] = pline["background-color"]; 56027 if (jinput.color) { json.color = pline.color; } 56028 56029 ++pline.product_count; 56030 } else { 56031 ++vendor.product_count; 56032 } 56033 } 56034 56035 if (jinput.upc_vc) { json.upc_vc = jinput.upc_vc; } 56036 if (jinput.size_dr) { json.size_vc = jinput.size_dr; } 56037 if (jinput.price_mn) { json.price_mn = UTIL.displayMoney(jinput.price_mn, true); } 56038 if (jinput.unit_id) { json.unit_id = jinput.unit_id; } 56039 56040 if (UTIL.isNumber(jinput.inventory_type_id)) { 56041 json.inventory_type_id = parseInt(jinput.inventory_type_id); 56042 json.category_id = ''; 56043 56044 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", json.inventory_type_id); 56045 ++ctype.product_count; 56046 ++_conPos.getObject(SA.POS.inventory_json.categories, "id", ctype.category_id).total_product_count; 56047 } else if (UTIL.isNumber(jinput.category_id)) { 56048 json.inventory_type_id = ''; 56049 json.category_id = parseInt(jinput.category_id); 56050 56051 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", json.category_id); 56052 ++category.product_count; 56053 ++category.total_product_count; 56054 } else { 56055 json.inventory_type_id = json.category_id = ''; 56056 } 56057
56058 if (jinput.image_vc) { json.image_vc = jinput.image_vc; } 56059 if (UTIL.parseBool(jinput.not_taxable_fl)) { json.tax_rate_pct = 0; } else { delete json.tax_rate_pct; } 56060 56061 SA.POS.inventory_json.products.push(json); 56062 56063 if (_conPos.sortType === 2) { //add box to UI (if matches current filter) 56064 _clickBreadcrumbEnd(json.vendor_id, plid, true); 56065 } else { 56066 _clickBreadcrumbEnd(json.category_id, json.inventory_type_id, true); 56067 } 56068 } 56069 56070 function _saveVendorSuccessful(jsonIn, dataOut) { //applies to saving vendors + plines. 56071 var j = $(dataOut); 56072 var vid = parseInt(j.attr('vendor_id')); 56073 56074 if (jsonIn.boxtype === 'v') { 56075 if (UTIL.isEmpty(jsonIn.vendor_id)) { //= is add. 56076 var vendor = { "id": vid, "product_line_count": 0, "product_count": 0, "total_product_count": 0 }; 56077 SA.POS.inventory_json.vendors.push(vendor); 56078 } else { 56079 var vendor = _conPos.getVendorObject(vid); 56080 } 56081 56082 _checkColorChange(vendor.color, jsonIn.text_color_vc, vendor["background-color"], jsonIn.background_color_vc); 56083 56084 vendor.name = j.attr('vendor_name_vc'); 56085 vendor["background-color"] = jsonIn.background_color_vc; 56086 vendor.color = jsonIn.text_color_vc; 56087 vendor.image_vc = jsonIn.file_name_vc; 56088 vendor.css_class_vc = j.attr('css_class'); 56089 } else { 56090 if (UTIL.isEmpty(jsonIn.product_line_id)) { 56091 var pline = { "id": parseInt(j.attr('product_line_id')), "product_count": 0 }; 56092 SA.POS.inventory_json.product_lines.push(pline); 56093 } else { 56094 var pline = _conPos.getPLineObject(j.attr('product_line_id')); 56095 } 56096 56097 _checkPLineChangedVendor(jsonIn.product_line_id, pline.product_line_id, pline.vendor_id, vid); 56098 56099 pline.name = j.attr('product_line_name_vc'); 56100 pline.vendor_id = vid; 56101 56102 _checkColorChange(pline.color, jsonIn.text_color_vc, pline["background-color"], jsonIn.background_color_vc); 56103 56104 pline["background-color"] = jsonIn.background_color_vc; 56105 pline.color = jsonIn.text_color_vc; 56106 pline.image_vc = jsonIn.file_name_vc; 56107 pline.css_class_vc = j.attr('css_class'); 56108 } 56109 56110 _clickBreadcrumbEnd(null, null, true); //add box to UI (if matches current filter) 56111 } 56112 56113 function _saveCategorySuccessful(jsonIn, dataOut) { //applies to saving category + category-type. 56114 var j = $(dataOut); 56115 var catid = parseInt(j.attr('category_id')); 56116 56117 if (jsonIn.boxtype === 'c') { 56118 if (UTIL.isEmpty(jsonIn.category_id)) { //= is add. 56119 var category = { "id": catid, "type_count": 0, "product_count": 0, "total_product_count": 0 }; 56120 SA.POS.inventory_json.categories.push(category); 56121 } else { 56122 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catid); 56123 } 56124 56125 _checkColorChange(category.color, jsonIn.text_color_vc, category["background-color"], jsonIn.background_color_vc); 56126 56127 category.name = j.attr('category_name_vc'); 56128 category["background-color"] = jsonIn.background_color_vc; 56129 category.color = jsonIn.text_color_vc; 56130 category.image_vc = jsonIn.file_name_vc; 56131 category.css_class_vc = j.attr('css_class'); 56132 } else { 56133 if (UTIL.isEmpty(jsonIn.inventory_type_id)) { 56134 var ctype = { "id": parseInt(j.attr('inventory_type_id')), "product_count": 0 }; 56135 SA.POS.inventory_json.types.push(ctype); 56136 } else { 56137 var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", j.attr('inventory_type_id')); 56138 } 56139 56140 _checkTypeChangedCategory(jsonIn.inventory_type_id, ctype.id, jsonIn.category_id, catid); 56141 56142 ctype.name = j.attr('type_name_vc'); 56143 ctype.category_id = catid; 56144 56145 _checkColorChange(ctype.color, jsonIn.text_color_vc, ctype["background-color"], jsonIn.background_color_vc); 56146 56147 ctype["background-color"] = jsonIn.background_color_vc; 56148 ctype.color = jsonIn.text_color_vc; 56149 ctype.image_vc = jsonIn.file_name_vc; 56150 ctype.css_class_vc = j.attr('css_class'); 56151 } 56152 56153 _clickBreadcrumbEnd(null, null, true); //add box to UI (if matches current filter) 56154 } 56155 56156 function _checkPLineChangedVendor(oldPLineId, newPLineId, oldVendorId, newVendorId) { 56157 if (UTIL.coalesceInt(oldVendorId, -1) !== UTIL.coalesceInt(newVendorId, -1)) { 56158 var vendor = _conPos.getVendorObject(oldVendorId); 56159 if (vendor) { --vendor.product_line_count; } 56160 56161 vendor = _conPos.getVendorObject(newVendorId); 56162 if (vendor) { ++vendor.product_line_count; } 56163 } 56164 } 56165
56166 function _checkTypeChangedCategory(oldTypeId, newTypeId, oldCategoryId, newCategoryId) { 56167 if (UTIL.coalesceInt(oldCategoryId, -1) !== UTIL.coalesceInt(newCategoryId, -1)) { 56168 var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", oldCategoryId); 56169 if (category) { --category.type_count; } 56170 56171 category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId); 56172 if (category) { ++category.type_count; } 56173 } 56174 } 56175 56176 function _checkColorChange(initialColor, newColor, initialBColor, newBColor) { //= if change vendor or pline color need to refresh products with new color (toDo: later do this via JS). 56177 if ('rgb(' + initialColor + ')' === _DEFAULT_COLOR) { initialColor = ''; } 56178 if ('rgb(' + initialBColor + ')' === _DEFAULT_BACKGROUND_COLOR) { initialBColor = ''; } 56179 56180 if (UTIL.cleanString(initialColor) !== newColor || UTIL.cleanString(initialBColor) !== newBColor) { 56181 _conPosEdit.refreshData(); //document.location = GLO.Link.WebsiteDomain + 'pos?edit=true'; //location.reload(); 56182 } 56183 } 56184 56185 _conPosEdit.clickBreadcrumbEnd = function(grandId, parentId, isSystemReset) { 56186 _clickBreadcrumbEnd(grandId, parentId, isSystemReset); 56187 } 56188 56189 function _clickBreadcrumbEnd(grandId, parentId, isCloseEditPopup) { 56190 var jbread = $('#pos-product-header-breadcrumb'); 56191 var jwindow = $('#pos-product-window'); 56192 56193 if (_conPos.sortType === 2) { 56194 parentId = UTIL.coalesce(parentId, jbread.find('#pos-breadcrumb-pline').attr('product_line_id')); 56195 grandId = UTIL.coalesce(grandId, jbread.find('#pos-breadcrumb-vendor').attr('vendor_id')); 56196 } else { 56197 parentId = UTIL.coalesce(parentId, jbread.find('#pos-breadcrumb-category-type').attr('inventory_type_id')); 56198 grandId = UTIL.coalesce(grandId, jbread.find('#pos-breadcrumb-category').attr('category_id')); 56199 } 56200 56201 SA.POS.filterBoxesHome(null, isCloseEditPopup); 56202 56203 if (_conPos.sortType === 2) { 56204 if (UTIL.isNumber(grandId)) { 56205 GLO.UI.click(jwindow, 'div[box_type="v"][vendor_id="' + grandId + '"]'); 56206 } 56207 56208 if (UTIL.isNumber(parentId)) { 56209 GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop')); 56210 GLO.UI.click(jwindow, 'div[box_type="pl"][product_line_id="' + parentId + '"]'); 56211 } 56212 } else { 56213 if (UTIL.isNumber(grandId)) { 56214 GLO.UI.click(jwindow, 'div[box_type="c"][category_id="' + grandId + '"]'); 56215 } 56216 56217 if (UTIL.isNumber(parentId)) { 56218 GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop')); 56219 GLO.UI.click(jwindow, 'div[box_type="ct"][inventory_type_id="' + parentId + '"]'); 56220 } 56221 } 56222 56223 if (isCloseEditPopup) { 56224 GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop')); 56225 } 56226 } 56227 56228 _conPosEdit.changeDisplayTicketPanel = function() { 56229 var url = GLO.Link.WebsiteDomain + 'pos/HideTicketPanel'; 56230 var displayPanel = $('#pos-ticket-edit-mode').find(':radio[name="POS_Edit_Ticket_Panel_Display"]:checked').attr('id'); 56231 var jpanel = $('#pos-panel-client'); 56232 56233 if (displayPanel == 'POS_Edit_Ticket_Panel_Hide_This_Device') { 56234 jpanel.addClass('hideX'); 56235 UTIL.setCookie('hide_ticket_panel_fl', '1'); 56236 56237 var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Hidden on This Device</b></p>'; 56238 GLO.Popup.Success.open(successMsg, 'POS Ticket Panel'); 56239 return; 56240 } else if (displayPanel == 'POS_Edit_Ticket_Panel_Hide') { 56241 jpanel.addClass('hideX'); 56242 UTIL.setCookieWithExpire('hide_ticket_panel_fl', null); 56243 url += '?hide=1'; 56244 56245 var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Hidden</b></p>'; 56246 } else if (displayPanel == 'POS_Edit_Ticket_Panel_Display') { 56247 jpanel.removeClass('hideX'); 56248 UTIL.setCookieWithExpire('hide_ticket_panel_fl', null); 56249 url += '?hide=0'; 56250 56251 var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Displayed</b></p>'; 56252 } 56253 56254 UI.addProcessingLayer(); 56255 56256 $.ajax({ "type": "POST", "url": url, "cache": false }) 56257 .success(function(data, textStatus, jqXHR) { 56258 UI.removeProcessingLayer(); 56259 GLO.Popup.Success.open(successMsg, 'POS Ticket Panel'); 56260 }).error(function(jqXHR, textStatus, errorThrown) { 56261 UI.removeProcessingLayer(); 56262 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 56263 }); 56264 } 56265 _conPosEdit.changeUseServiceImages = function(element) { 56266 if (element.checked) { 56267 var isUseServiceImages = 1; 56268 } else { 56269 var isUseServiceImages = 0; 56270 } 56271 56272 var url = GLO.Link.WebsiteDomain + 'pos/UseServiceImage'; 56273 var jd = { "use_service_image_fl": isUseServiceImages }; 56274 56275 UI.addProcessingLayer(); 56276
56277 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd }) 56278 .success(function(data, textStatus, jqXHR) { 56279 UI.removeProcessingLayer(); 56280 56281 _conPos.inventory_json.use_service_image_fl = isUseServiceImages; 56282 SA.POS.toggleList('services'); 56283 }).error(function(jqXHR, textStatus, errorThrown) { 56284 UI.removeProcessingLayer(); 56285 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 56286 }); 56287 } 56288 _conPosEdit.changeSortTypeService = function(element) { 56289 var url = GLO.Link.WebsiteDomain + 'pos/SortTypeService'; 56290 var jd = { "sort_type_cd": element.value }; 56291 var jcontainer = $('#pos-container'); 56292 56293 if (jd.sort_type_cd == 10) { 56294 jcontainer.removeClass('service-sort-custom'); 56295 } else { 56296 jcontainer.addClass('service-sort-custom'); 56297 } 56298 56299 UI.addProcessingLayer(); 56300 56301 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd }) 56302 .success(function(data, textStatus, jqXHR) { 56303 UI.removeProcessingLayer(); 56304 56305 var json = jQuery.parseJSON(data); 56306 //json.no_toggle_menu_fl = true; 56307 }).error(function(jqXHR, textStatus, errorThrown) { 56308 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 56309 UI.removeProcessingLayer(); 56310 }); 56311 } 56312 _conPosEdit.changeSortTypeProduct = function(element) { 56313 var url = GLO.Link.WebsiteDomain + 'pos/SortTypeProduct'; 56314 var jd = { "sort_type_cd": element.value } 56315 UI.addProcessingLayer(); 56316 56317 $.ajax({ "type": "POST", "url": url, "cache": false, data: jd, dataType: "json" }) 56318 .success(function(data, textStatus, jqXHR) { 56319 UI.removeProcessingLayer(); 56320 56321 var json = jQuery.parseJSON(data); 56322 //json.no_toggle_menu_fl = true; 56323 56324 _conPos.init(json); 56325 _conPos.filterBoxesHome(); 56326 }).error(function(jqXHR, textStatus, errorThrown) { 56327 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 56328 UI.removeProcessingLayer(); 56329 }); 56330 } 56331 _conPosEdit.reloadChanges = function() { 56332 GLO.UI.Form.beginProcessing($('#btnPosEditReloadChanges')); 56333 56334 setTimeout(function() { 56335 location.reload(); 56336 }, 150); 56337 } 56338 56339 _conPosEdit.refreshData = function() { 56340 var url = GLO.Link.WebsiteDomain + 'pos/RefreshData'; 56341 UI.addProcessingLayer(); 56342 56343 $.ajax({ "type": "GET", "url": url, "cache": false, dataType: "json" }) 56344 .success(function(data, textStatus, jqXHR) { 56345 UI.removeProcessingLayer(); 56346 var json = jQuery.parseJSON(data); 56347 json.no_toggle_menu_fl = true; 56348 56349 _conPos.init(json); 56350 _clickBreadcrumbEnd(null, null, true); //_conPos.filterBoxesHome(); 56351 }).error(function(jqXHR, textStatus, errorThrown) { 56352 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 56353 UI.removeProcessingLayer(); 56354 }); 56355 } 56356 56357 _conPosEdit.imageUploadComplete = function(jupload, fileName, imgid, imgSize) { 56358 var img = 'url("' + GLO.Data.cdnDirectory + 'upload-folder/' + fileName + '")'; 56359 var jpop = jupload.closest('.glopop'); 56360 var jbox = null; 56361 56362 jpop.find('.upload-preview').css({ "background-image": img }); 56363 jpop.find('.sa-upload').attr('file_name_vc', fileName); 56364 56365 if (jpop.find('#pos-popup-brand').length === 1) { 56366 var plid = jpop.find('#Product_Line_id').val(); 56367 var vid = jpop.find('#Vendor_id').val(); 56368 56369 if (imgid == plid) { 56370 jbox = _conPos.getPLineObject(plid); 56371 } else if (imgid == vid) { 56372 jbox = _conPos.getVendorObject(vid); 56373 } 56374 } else if (jpop.find('#pos-popup-category').length === 1) { 56375 var tid = jpop.find('#Inventory_Type_id').val(); 56376 var ctid = jpop.find('#Category_id').val(); 56377 56378 if (imgid == tid) { 56379 jbox = _conPos.getObject(SA.POS.inventory_json.types, "id", tid); 56380 } else if (imgid == ctid) { 56381 jbox = _conPos.getObject(SA.POS.inventory_json.categories, "id", ctid); 56382 } 56383 } else if (jpop.find('#pos-popup-product').length === 1) { 56384 var iid = jpop.find('#Inventory_id').val(); 56385 56386 if (imgid == iid) { 56387 jbox = _conPos.getProductObject(iid); 56388 } 56389 } 56390 56391 if (jbox !== null) { 56392 $('#pos-header-edit-box').find('.pos-product-box').css({ "background-image": img }); 56393 jbox.image_vc = fileName; 56394 56395 jpop.find('.pos-popup-box').addClass('edit-image'); 56396 _clickBreadcrumbEnd(null, null, true); 56397 } 56398 } 56399 56400 _conPosEdit.openHelp = function() { 56401 if (!$('#pos-container').hasClass('edit-pos')) { 56402 SA.POS.Edit.changeMode(); 56403 } 56404 56405 GLO.Popup.closeIfExist($('#pop-pos-edit-help').closest('.glopop')); 56406 GLO.Popup.closeIfExist($('#pop-pos-help').closest('.glopop')); 56407 56408 var arrow = '<b class="arrow-right">➜</b>'; 56409 var htmContact = '<h5 id="pop-pos-contact-sa" onclick="GLO.Log.openContactSAPopup(null, null, null, true)"> <i>Contact</i> ' + GLO.Info.getScheduleAnyoneHtm(true) + '</h5>'; 56410 var msgServiceCustomDisclaimer = ''; 56411 56412 if (innerWidth < 1500) { 56413 msgServiceCustomDisclaimer = ' <b class="narrow-text" style="padding: 2px 4px; border-radius: 4px; background-color: yellow;">requires minimum screen width of 1500px, your screen width is: ' + innerWidth + 'px</b>'; 56414 } 56415 56416 var hService = '<h3>Sort + Customize Services</h3>' 56417 var aProfileService = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, null, true)">Profile ' + arrow + ' Services</a>' 56418 var msgServiceAuto = '<p>Can use the <b class="narrow-text">Automatic</b> sorting of services <i class="narrow-text">(setup at ' + aProfileService + ')</i>'; 56419 var msgServiceCustom = '<p>Can further <b class="narrow-text">Customize</b> the layout of services using <b class="narrow-text">Custom Service Layout</b>' + msgServiceCustomDisclaimer + '</p>'; 56420 56421 var htmServiceColor = '<p>Click any service to change the color and image <i class="narrow-text">the service icon or thumbnail image is used from the service gallery</i></p>'; 56422 var htmServiceSort = '<p>' + msgServiceAuto + msgServiceCustom + '</p>'; 56423 var htmServiceSort2 = '<p>When <b class="narrow-text">Custom Service Layout</b> selected can grab <b class="narrow-text">top-left</b> of any service and drag it to the desired location</p>'; 56424 var htmService = hService + htmServiceSort + htmServiceSort2 + htmServiceColor; 56425 56426 var hProduct = '<h3>Sort + Customize Products</h3>' 56427 var msgCategoryList = '<i class="narrow-text">(Shampoo, Conditioner, Cutical Oil, Massage Oil, etc..)</i>'; 56428 var msgProductSortBrand = 'Can sort products by <b class="narrow-text">Brand</b> <i class="narrow-text">(like Keven Murphy, OPI, Keratase, etc)</i>'; 56429 var msgProductSortCategory = ' <span style="white-space: nowrap;">or <b class="narrow-text">Category</b> ' + msgCategoryList; 56430 var htmProductSort = '<p>' + msgProductSortBrand + msgProductSortCategory + '</p>'; 56431 56432 var htmProductColor = '<p>Click any product to change the color and image</p>'; 56433 var htmProductCustomize = '<p>Can also create/edit product brands, product lines, categories, and sub-categories</p>'; 56434 56435 var onclickProductNew = ' onclick="GLO.Uri.gotoUriWithSpinner(\'provider/inventory#action=new-product\', this, null, true)"'; 56436 var aProductNew = '<a class="narrow-text"' + onclickProductNew + '>Manage Inventory ' + arrow + ' Create ' + arrow + ' Product</a>'; 56437 var htmProductNew = '<p>To create a new product available to sell in the P.O.S. go to ' + aProductNew + '</p>'; 56438 56439 var htmProduct = hProduct + htmProductSort + htmProductColor + htmProductCustomize + htmProductNew; 56440 56441 var hStaff = '<h3>Sort + Customize Staff</h3>'; 56442 56443 var btnSortStaff = '<span class="btnAdd"> <a onclick="GLO.RunningTotal.OrderCalendar.openPopup()"><b style="color: inherit;">Staff Order</b></a> </span>'; 56444 var helpSortStaff = '<span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Advanced.Help.C
56444alendar.openStaffOrder()" title=""></span>'; 56445 var msgSortStaff = 'Staff sorted by arrival time <i class="narrow-text">(clock-in time or scheduled start time)</i>' 56446 + ', if staff arrive at same time <i class="narrow-text">(+ do NOT clock-in)</i> uses '; 56447 var htmSortStaff = '<p>' + msgSortStaff + btnSortStaff + helpSortStaff + '</p>'; 56448 56449 var urlProfileStaffGallery = GLO.Data.provider.urikey + '/gallery/Staff/edit?imgsize=thumb'; 56450 var labelProfileStaffGallery = 'Profile ' + arrow + ' Website ' + arrow + ' Staff Gallery'; 56451 var aProfileStaffGallery = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlProfileStaffGallery + '\', this, null, true)">' + labelProfileStaffGallery + '</a>'; 56452 var htmProfileStaffGallery = '<p style="margin: 16px 0;">Can add staff images to the P.O.S. Screen by going to ' + aProfileStaffGallery + ' and uploading an icon or thumbnail image for each staff</p>'; 56453 56454 var labelProfileStaff = 'Profile ' + arrow + ' Staff'; 56455 var aProfileStaff = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5\', this, null, true)">' + labelProfileStaff + '</a>'; 56456 var htmProfileStaff = '<p>Can change staff card background color go to ' + aProfileStaff + ' and press the staff name then in staff popup ' + arrow + ' press the color wheel</p>'; 56457 56458 var htmStaff = hStaff + htmSortStaff + htmProfileStaffGallery + htmProfileStaff; 56459 56460 var htm = '<div id="pop-pos-edit-help">' + htmContact + htmService + htmProduct + htmStaff + '</div>'; 56461 var h1 = GLO.Info.getScheduleAnyoneHtm(true) + ' Customize P.O.S. Screen'; 56462 var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos'); 56463 56464 jpop.find('h1').css({ "background-color": "darkmagenta" }); 56465 GLO.Popup.Custom.singleButton(jpop, 'Close'); 56466 } 56467 56468 return _conPosEdit; 56469 })(); 56470 56471 return _conPos; 56472})(); 56473 56474SA.POS.PAX = (function() { 56475 //default 56476 var paxApiSvcBaseUrl = 'http://localhost:9000/'; 56477 var COMPorts; 56478 var paxDevices; 56479 var uuid; 56480 var osVersion; 56481 var _jpopAddPaxWifiDevice; 56482 56483 function _pax(paxapiurl) { 56484 paxApiSvcBaseUrl = paxapiurl; 56485 } 56486 56487 _pax.init = function(deviceId) { 56488 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56489 if (paxDeviceId == "") { 56490 if (deviceId == "") { 56491 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56492 return; 56493 } 56494 else { 56495 paxDeviceId = deviceId; 56496 } 56497 } 56498 56499 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getinitrequest/' + paxDeviceId; 56500 56501 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56502 .success(function(data, textStatus, jqXHR) { 56503 window.onbeforeunload = null; 56504 // GLO.UI.Form.resetProcessing(); 56505 var jsonMR = JSON.stringify(data); 56506 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56507 }) 56508 .error(function(jqXHR, textStatus, errorThrown) { 56509 GLO.UI.Form.resetProcessing(); 56510 new GLO.Popup.Error('Unable to get GETVAR request'); 56511 }); 56512 56513 } 56514 56515 //get the merchantId and TSYS deviceId associated with device 56516 _pax.getvar = function(deviceId) { 56517 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56518 if (paxDeviceId == "") { 56519 if (deviceId == "") { 56520 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56521 return; 56522 } 56523 else { 56524 paxDeviceId = deviceId; 56525 } 56526 } 56527 56528 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getgetvarrequest/' + paxDeviceId; 56529 56530 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56531 .success(function(data, textStatus, jqXHR) { 56532 window.onbeforeunload = null; 56533 var jsonMR = JSON.stringify(data); 56534 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56535 }) 56536 .error(function(jqXHR, textStatus, errorThrown) { 56537 GLO.UI.Form.resetProcessing(); 56538 new GLO.Popup.Error('Unable to get GETVAR request'); 56539 }); 56540 } 56541 56542 //link device with merchantId 56543 _pax.setvar = function(deviceId) { 56544 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56545 if (paxDeviceId == "") { 56546 if (deviceId == "") { 56547 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56548 return; 56549 } 56550 else { 56551 paxDeviceId = deviceId; 56552 } 56553 } 56554 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getsetvarrequest/' + paxDeviceId; 56555
56556 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56557 .success(function(data, textStatus, jqXHR) { 56558 window.onbeforeunload = null; 56559 56560 var jsonMR = JSON.stringify(data); 56561 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56562 setTimeout(_pax.updateimage(paxDeviceId), 5000); 56563 }) 56564 .error(function(jqXHR, textStatus, errorThrown) { 56565 new GLO.Popup.Error('Unable to get SETVAR request'); 56566 }); 56567 } 56568 56569 _pax.updateimage = function(deviceId) { 56570 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56571 if (paxDeviceId == "") { 56572 if (deviceId == "") { 56573 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56574 return; 56575 } 56576 else { 56577 paxDeviceId = deviceId; 56578 } 56579 } 56580 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getupdateimagerequest/' + paxDeviceId; 56581 56582 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56583 .success(function(data, textStatus, jqXHR) { 56584 window.onbeforeunload = null; 56585 56586 var jsonMR = JSON.stringify(data); 56587 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56588 }) 56589 .error(function(jqXHR, textStatus, errorThrown) { 56590 new GLO.Popup.Error('Unable to get UPDATEIMAGE request'); 56591 }); 56592 } 56593 56594 //clear screen message 56595 _pax.reset = function(deviceId) { 56596 56597 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56598 if (paxDeviceId == "") { 56599 if (deviceId == "") { 56600 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56601 return; 56602 } 56603 else { 56604 paxDeviceId = deviceId; 56605 } 56606 } 56607 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getresetrequest/' + paxDeviceId; 56608 56609 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56610 .success(function(data, textStatus, jqXHR) { 56611 window.onbeforeunload = null; 56612 56613 var jsonMR = JSON.stringify(data); 56614 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56615 }) 56616 .error(function(jqXHR, textStatus, errorThrown) { 56617 new GLO.Popup.Error('Unable to get RESET request'); 56618 }); 56619 } 56620 56621 //reboot the device 56622 _pax.reboot = function(deviceId) { 56623 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getrebootrequest/' + deviceId; 56624 56625 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56626 .success(function(data, textStatus, jqXHR) { 56627 window.onbeforeunload = null; 56628 56629 var jsonMR = JSON.stringify(data); 56630 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56631 }) 56632 .error(function(jqXHR, textStatus, errorThrown) { 56633 new GLO.Popup.Error('Unable to get REBOOT request'); 56634 }); 56635 } 56636 56637 function _getAuthUrl(isCredit, deviceId, isSale, cid, smid, scid, amount, tip) { 56638 if (isCredit) { 56639 var authType = 'credit'; 56640 } else { 56641 var authType = 'debit'; 56642 } 56643 56644 var url = GLO.Link.WebsiteDomain + 'api/PAX/get' + authType + 'authrequest/' + deviceId + '?isSale=' + isSale + '&cid=' + cid; 56645 56646 if (scid) { 56647 url += '&scid=' + scid; 56648 } 56649 56650 return url + '&smid=' + UTIL.coalesceString(smid, '0') + '&amount=' + amount + '&tip=' + UTIL.coalesceMoney(tip); 56651 } 56652 56653 _pax.getprepaydialog = function(deviceId) { 56654 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56655 if (paxDeviceId == "") { 56656 if (deviceId == "") { 56657 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56658 return; 56659 } 56660 else { 56661 paxDeviceId = deviceId; 56662 } 56663 } 56664 56665 var uri = GLO.Link.WebsiteDomain + 'api/PAX/getprepaymentdialogrequest/' + paxDeviceId; 56666 56667 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56668 .success(function(data, textStatus, jqXHR) { 56669 window.onbeforeunload = null; 56670 var jsonMR = JSON.stringify(data); 56671 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56672 }) 56673 .error(function(jqXHR, textStatus, errorThrown) { 56674 GLO.UI.Form.resetProcessing(); 56675 new GLO.Popup.Error('Unable to get SHOWDIALOG request'); 56676 }); 56677 } 56678 56679 _pax.gettipdialog = function(deviceId) { 56680 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 56681 if (paxDeviceId == "") { 56682 if (deviceId == "") { 56683 new GLO.Popup.Error('Unable to find device. Please make sure device is connected.'); 56684 return; 56685 } 56686 else { 56687 paxDeviceId = deviceId; 56688 } 56689 } 56690 56691 var uri = GLO.Link.WebsiteDomain + 'api/PAX/gettipdialogrequest/' + paxDeviceId; 56692
56693 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56694 .success(function(data, textStatus, jqXHR) { 56695 window.onbeforeunload = null; 56696 var jsonMR = JSON.stringify(data); 56697 _pax.postManageRequestToPAXApi(jsonMR,paxDeviceId); 56698 }) 56699 .error(function(jqXHR, textStatus, errorThrown) { 56700 GLO.UI.Form.resetProcessing(); 56701 new GLO.Popup.Error('Unable to get SHOWDIALOG request'); 56702 }); 56703 } 56704 56705 _pax.creditauth = function(deviceId, isSale, cid, smid, scid, amount, tip) { 56706 var uri = _getAuthUrl(true, deviceId, isSale, cid, smid, scid, amount, tip); 56707 56708 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56709 .success(function(data, textStatus, jqXHR) { 56710 window.onbeforeunload = null; 56711 56712 var jsonPR = JSON.stringify(data); 56713 _pax.postPaymentRequestToPAXApi(jsonPR, deviceId, isSale, cid, smid, scid, amount); 56714 }) 56715 .error(function(jqXHR, textStatus, errorThrown) { 56716 _displayEmvCommunicateError('Unable to connect to payment device', null, false); 56717 56718 /* 56719 setTimeout(function() { 56720 var jwarn = $('#pop-warn-emv-communicate').closest('.glopop'); 56721 56722 if (jwarn.length) { 56723 GLO.Popup.close(jwarn); 56724 } 56725 56726 UserPortal.Price.Payment.openCreditCard(); 56727 }, 2500); 56728 */ 56729 }); 56730 } 56731 56732 _pax.debitauth = function(deviceId, isSale, cid, smid, scid, amount, tip) { 56733 var uri = _getAuthUrl(false, deviceId, isSale, cid, smid, scid, amount, tip); 56734 56735 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 56736 .success(function(data, textStatus, jqXHR) { 56737 window.onbeforeunload = null; 56738 56739 var jsonPR = JSON.stringify(data); 56740 _pax.postPaymentRequestToPAXApi(jsonPR, deviceId, isSale, cid, smid, scid, amount); 56741 }) 56742 .error(function(jqXHR, textStatus, errorThrown) { 56743 _displayEmvCommunicateError('Unable to get DEBIT AUTH request', null, true); 56744 }); 56745 } 56746 //cancel transaction in progess 56747 _pax.canceltrans = function(deviceId) { 56748 _pax.postCancelTransToPAXApi(); 56749 } 56750 //get devices on terminal's serial port 56751 _pax.getCOMPortsFromPAXApi = function(paxMacAddr, _callback) { 56752 var uri = paxApiSvcBaseUrl + 'api/PAX/portinfo?mac=' + paxMacAddr; 56753 56754 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" }) 56755 .success(function(data, textStatus, jqXHR) { 56756 window.onbeforeunload = null; 56757 //call pax api 56758 //COMPorts = data; 56759 if (data.length > 0) { 56760 COMPorts = new Array(0); 56761 for (var i = 0; i < data.length; i++) { 56762 var COMPort = { 56763 "Name":data[i].Name, 56764 "Port":data[i].Port, 56765 "Direction":data[i].Direction, 56766 "TerminalUniqueId": SA.POS.PAX.uuid, 56767 "OSVersion":SA.POS.PAX.osVersion, 56768 "token":"", 56769 "IPAddress":"", 56770 "MacAddress":"" 56771 }; 56772 COMPorts.push(COMPort); 56773 } 56774 } 56775 56776 return _callback(COMPorts); 56777 56778 }) 56779 .error(function(jqXHR, textStatus, errorThrown) { 56780 new GLO.Popup.Error('No payment devices found'); 56781 }); 56782 } 56783 56784 56785 _pax.clearPAXDevice = function() { 56786 document.cookie = 'paxdevice=; Max-Age=0; path=/; domain=' + location.host; 56787 setTimeout(function() { 56788 location.reload(); 56789 }, 3100); 56790 } 56791 56792 _pax.openAddWifiDevice = function() { 56793 if (UTIL.isEmpty(_jpopAddPaxWifiDevice)) { 56794 _jpopAddPaxWifiDevice = $('#pax-wifi-setup').outerHTML(); 56795 $('#pax-wifi-setup').remove(); 56796 } 56797 56798 56799 var jpop = GLO.Popup.Custom.openSimple(_jpopAddPaxWifiDevice, 'Connect Wifi Device', function () { return SA.POS.PAX.savePaxWifiDevice(); }); 56800 56801 } 56802 56803 _pax.getWifiDevices = function(_callback) { 56804 var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPaxDevices'; 56805
56806 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" }) 56807 .success(function(data, textStatus, jqXHR) { 56808 window.onbeforeunload = null; 56809 //call pax api 56810 //paxDevices = data; 56811 56812 if (data.length > 0) { 56813 if ((typeof(paxDevices) == 'undefined') || (paxDevices == null)) { paxDevices = new Array(0); } 56814 for (var i = 0; i < data.length; i++) { 56815 if (data[i].IPAddress !== '') { 56816 var COMPort = { 56817 "Name":data[i].DeviceName, 56818 "Port":"", 56819 "Direction":"", 56820 "TerminalUniqueId": SA.POS.PAX.uuid, 56821 "OSVersion":SA.POS.PAX.osVersion, 56822 "token":"", 56823 "IPAddress":data[i].IPAddress, 56824 "MacAddress":"" 56825 }; 56826 paxDevices.push(COMPort); 56827 } 56828 56829 } 56830 } 56831 //console.log(data); 56832 return _callback(paxDevices); 56833 56834 }) 56835 .error(function(jqXHR, textStatus, errorThrown) { 56836 new GLO.Popup.Error('No Wifi PAX devices found'); 56837 }); 56838 } 56839 _pax.savePaxWifiDevice = function() { 56840 56841 var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice'; 56842 56843 var jpop = $('#pax-wifi-setup').closest('.glopop'); 56844 var ipAddress = jpop.find('#pax-wifi-ip').val(); 56845 //remove leading zeros from ip 56846 var cleanIPAddress = ipAddress.replace(/(^|\.)0+(?=[^.])/g, '.'); 56847 56848 var wifiDevice = { 56849 "Name":"Wifi device", 56850 "Port":"", 56851 "Direction":"", 56852 "TerminalUniqueId": SA.POS.PAX.uuid, 56853 "OSVersion":SA.POS.PAX.osVersion, 56854 "token":"", 56855 "IPAddress":cleanIPAddress, 56856 "MacAddress":"" 56857 }; 56858 56859 var jsonCOMPort = JSON.stringify(wifiDevice); 56860 56861 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" }) 56862 .success(function(data, textStatus, jqXHR) { 56863 window.onbeforeunload = null; 56864 //update the device list table 56865 _pax.ShowSelectedWifiDeviceInDeviceList(data); 56866 //_pax.setvar(data.DeviceId); 56867 new GLO.Popup.Success('Device connected.', 19000); 56868 }) 56869 .error(function(jqXHR, textStatus, errorThrown) { 56870 GLO.UI.Form.resetProcessing(); 56871 new GLO.Popup.Error('Unable to Connect to Selected Device'); 56872 }); 56873 } 56874 56875 _pax.getMacOSFromPAXApi = function(_callback) { 56876 var uri = paxApiSvcBaseUrl + 'api/info/macos'; 56877 56878 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" }) 56879 .success(function(data, textStatus, jqXHR) { 56880 window.onbeforeunload = null; 56881 //call pax api 56882 _callback(data); 56883 56884 }) 56885 .error(function(jqXHR, textStatus, errorThrown) { 56886 new GLO.Popup.Error('Error getting UUID and OS version from local terminal'); 56887 }); 56888 } 56889 56890 56891 _pax.postManageRequestToPAXApi = function(manageRequest,deviceId) { 56892 var uri = paxApiSvcBaseUrl + 'api/PAX/manage'; 56893 56894 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: manageRequest, contentType: "application/json" }) // , timeout:30000 56895 .success(function(data, textStatus, jqXHR) { 56896 window.onbeforeunload = null; 56897 if (data.transResult.Code != "1") { 56898 new GLO.Popup.Error(data.transResult.Msg); 56899 } 56900 else { 56901 //call SA api 56902 var jsonMR = JSON.stringify(data.manageResponse); 56903 _pax.postManageResponseToSA(jsonMR,deviceId); 56904 56905 //testing - proof of concept changes 56906 // if (data.manageResponse.ResultCode == "000000" && data.manageResponse.ButtonNum == "1") { 56907 // //http://www.test2.com/api/PAX/getcreditauthrequest/6?isSale=false&cid=36574&smid=156468&amount=55 56908 // _pax.creditauth(deviceId,false,36574,156468,null,55); 56909 // } 56910 } 56911 }) 56912 .error(function(jqXHR, textStatus, errorThrown) { 56913 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 56914 GLO.Popup.Error.open('Error communicating with PAX device', 'Device Unavailable'); 56915 }); 56916 } 56917 56918 function _displayEmvCommunicateError(msg, h1, isCloseSwipePopup) { //only display warning if has swipe popup open (+ not processing card-on-file)
56919 if ($('#appt-price-swipe-ready').closest('.glopop').length > 0) { 56920 if ($('#pop-card-on-file-view').closest('.glopop').length === 0 && $('#btnUseCardOnFile.btnProcessing4').length === 0) { 56921 if ($('#pop-warn-emv-communicate').length === 0 && $('.pop-error.glopop, .pop-warning.glopop').length === 0) { 56922 h1 = UTIL.coalesceString(h1, 'Payment Processing Warning'); 56923 var htmEnterManually = '<div id="enter-card-manually"> <a onclick="UserPortal.Price.Payment.openCreditCard()">Enter Card Manually</a> </div>'; 56924 var htm = '<div id="pop-warn-emv-communicate">' + msg + htmEnterManually + '</div>'; 56925 56926 var jpop = GLO.Popup.Warning.open(htm, h1).getPopup(); 56927 56928 if (isCloseSwipePopup) { 56929 UserPortal.Price.Payment.closeSwipePopup(true); 56930 } else { 56931 _addReconnectButton(); 56932 56933 var btnConnect = '<span id="btnConnectEmv" class="btnAdd" style="float: right; margin: 0;"><a onclick="SA.POS.PAX.addConnectButton()">Connect Payment Device</a></span>'; 56934 var btnOk = jpop.find('.btnOk'); 56935 56936 btnOk.find('> a').text('Cancel').click(function() { UserPortal.Price.Payment.closeSwipePopup(true); }); 56937 btnOk.after(btnConnect); 56938 } 56939 56940 //_pax.postCancelTransToPAXApi(); 56941 return true; 56942 } 56943 } 56944 } 56945 56946 return false; 56947 } 56948 56949 function _addReconnectButton() { 56950 var jpop = $('#appt-price-swipe-ready').closest('.glopop'); 56951 var btn = '<span id="btnConnectEmv" class="btnAdd"><a onclick="SA.POS.PAX.addConnectButton()">Connect EMV</a></span>'; 56952 56953 if (jpop.find('#btnConnectEmv').length === 0) { 56954 jpop.find('#enter-card-manually').after(btn); 56955 } 56956 } 56957 _pax.addConnectButton = function() { 56958 GLO.Popup.closeIfExist($('#pop-warn-emv-communicate').closest('.glopop')); 56959 56960 UserPortal.Price.Payment.quickReopenSwipePopup(); 56961 } 56962 _pax.addConnectingSpinner = function(timeoutWait) { 56963 var imgThrobber = '<img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="margin: 4px;"/>'; 56964 var blueThrobber = '<div class="blue-throbber" style="margin-top: 32px;">' + imgThrobber + '<i>Connecting Payment Device</i></div>'; 56965 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 56966 jPopSwipe.find('#enter-card-manually').after(blueThrobber); 56967 jPopSwipe.find('#enter-card-manually').css('display','none'); 56968 var jSwipeThrobber = jPopSwipe.find('.blue-throbber'); 56969 56970 setTimeout(function() { 56971 jSwipeThrobber.remove(); 56972 jPopSwipe.find('#enter-card-manually').css('display','block'); 56973 }, timeoutWait); 56974 } 56975 56976 _pax.postManageResponseToSA = function(manageResponse,deviceId) { 56977 var uri = GLO.Link.WebsiteDomain + 'api/PAX/ProcessManageResponse?device=' + deviceId; 56978 56979 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: manageResponse, contentType: "application/json" }) 56980 .success(function(data, textStatus, jqXHR) { 56981 window.onbeforeunload = null; 56982 56983 GLO.Popup.Success.open(data, 'Manage Device', 19000); 56984 }) 56985 .error(function(jqXHR, textStatus, errorThrown) { 56986 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 56987 GLO.Popup.Error.open('Unable to POST Manage response', 'Payment Processing Warning', ); 56988 }); 56989 } 56990 56991 _pax.postPaymentRequestToPAXApi = function(paymentRequest, deviceId, isSale, cid, smid, scid, amount) { 56992 var uri = paxApiSvcBaseUrl + 'api/PAX/payment'; 56993 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 56994 var startConnect = new Date(); 56995 56996 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: paymentRequest, contentType: "application/json" }) // , timeout:30000 56997 .success(function(data, textStatus, jqXHR) { 56998 window.onbeforeunload = null; 56999 jPopSwipe.find('.blue-throbber').remove(); 57000 57001 if (data.paymentResponse) { 57002 var resultText = data.paymentResponse.ResultTxt; 57003 57004 if (jPopSwipe.length && resultText !== 'ABORTED' && resultText !== 'TIMEOUT') { 57005 var throb = UI.getBlueThrobber(); 57006 jPopSwipe.find('#enter-card-manually').addClass('hide').after(throb); 57007 jPopSwipe.find('#store-card-container').addClass('hide'); 57008 } 57009 57010 _pax.postPaymentResponseToSA(data.paymentResponse, deviceId, isSale, cid, smid, scid, amount); 57011 } else { 57012 var logMsg = 'Connect time: ' + startConnect + ' thru ' + new Date() + ' is ' + UTIL.numberWithCommas(new Date() - startConnect) + 'milliseconds'; 57013 GLO.Log.insert(logMsg, 'PAX Response Empty', smid, 'warning'); 57014 57015 _displayEmvCommunicateError('Unable to Connect to Payment Device', 'Unable to Connect', false); 57016 } 57017 }) 57018 .error(function(jqXHR, textStatus, errorThrown) { 57019 jPopSwipe.find('.blue-throbber').remove(); 57020 _displayEmvCommunicateError('Error communicating with PAX device. Please try again.'); 57021 //this does not work -> SA.POS.PAX.postCancelTransToPAXApi(true); //might not have properly cancelled previous request, so instead of having to wait for timeout of current screen can call this 57022 57023 var keywords = smid + ' $' + amount 57024 var msg = '_pax.postPaymentRequestToPAXApi() ' + errorThrown + ': ' + paymentRequest; 57025 57026 if (jqXHR && jqXHR.responseJSON) { 57027 msg += ' -> ' + jQuery.parseJSON(jqXHR.responseJSON); 57028 } 57029 57030 msg = UTIL.htmlEncode(msg); 57031 GLO.Log.insert(msg, 'PAX Response Error', keywords, 'error'); 57032 }); 57033 } 57034 57035 _pax.postPaymentResponseToSA = function(jsonPayResponse, deviceId, isSale, cid, smid, scid, amount) { 57036 var jsonPR = JSON.stringify(jsonPayResponse); 57037 var uri = GLO.Link.WebsiteDomain + 'api/PAX/ProcessPaymentResponse?device=' + deviceId + '&isSale=' + isSale + '&client=' + cid + '&smid='
57037+ smid + '&amount=' + amount; 57038 57039 if (scid) { 57040 uri += '&scid=' + scid; 57041 } 57042 57043 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonPR, contentType: "application/json" }) 57044 .success(function(data, textStatus, jqXHR) { 57045 window.onbeforeunload = null; 57046 GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop')); 57047 57048 if (jsonPayResponse.ResultTxt === 'OK') { 57049 UserPortal.Price.Payment.saveCreditCard_complete(data, true); 57050 _displayPaymentResponseWarning(jsonPayResponse); 57051 _checkForTipOnPayment(jsonPayResponse, data); 57052 //GLO.Popup.Success.open(data, 'Payment Successful', 19000); 57053 } else if (data !== '') { 57054 UserPortal.Price.Payment.saveCreditCard_error(data); 57055 UserPortal.reloadTicket(smid); 57056 _lookupMissingTsysTransaction(isSale, cid, smid, scid, amount); 57057 } else { 57058 _displayEmvCommunicateError(jsonPayResponse.ResultTxt, 'Payment Failed', true); 57059 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 57060 57061 if (jPopSwipe.length) { 57062 jPopSwipe.find('#imgThrobberContainer').remove(); 57063 jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide'); 57064 } 57065 57066 _lookupMissingTsysTransaction(isSale, cid, smid, scid, amount); 57067 } 57068 }) 57069 .error(function(jqXHR, textStatus, errorThrown) { 57070 var fn = function() { 57071 UserPortal.reloadTicket(smid); 57072 } 57073 57074 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 57075 GLO.Popup.Error.open('Unable to process all card transactions', 'Multi-Merchant Transaction Failed', fn); 57076 }); 57077 } 57078 function _lookupMissingTsysTransaction(isSale, cid, smid, scid, amount) { 57079 var uri = GLO.Link.WebsiteDomain + 'payment/FindOrphanTsysTransaction?isSale=' + isSale + '&client=' + cid + '&smid=' + smid + '&scid=' + scid + '&amount=' + amount; 57080 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false }) 57081 .success(function(data, textStatus, jqXHR) { 57082 }) 57083 .error(function(jqXHR, textStatus, errorThrown) { 57084 }); 57085 } 57086 function _checkForTipOnPayment(jsonPayResponse, data) { //= if tip is added from EMV device, then re-load ticket so tip correctly added to services 57087 if (UTIL.coalesceMoney(jsonPayResponse.ApprovedAmount/100) > 0) { 57088 var jdata = $(data); 57089 var newTip = UTIL.coalesceMoney(jdata.find('li').attr('tip_mn')); 57090 57091 if (newTip > 0 && !UserPortal.Class.isClass()) { 57092 if (UTIL.isEmpty(jdata.attr('error_cd')) && UTIL.isEmpty(jdata.attr('warning_cd'))) { 57093 var smid = jdata.attr('schedule_multi_id'); 57094 57095 window.setTimeout(function() { //put in setTimeout so receipt is printed 57096 UserPortal.reloadTicket(smid); 57097 }, 150); 57098 } 57099 } 57100 } 57101 } 57102 function _displayPaymentResponseWarning(jsonPayResponse) { 57103 var pmtRequest = UTIL.coalesceMoney(jsonPayResponse.RequestedAmount/100); 57104 var pmtApproved = UTIL.coalesceMoney(jsonPayResponse.ApprovedAmount/100); 57105 57106 if (Math.abs(pmtRequest - pmtApproved) > .02) { 57107 if (pmtRequest - pmtApproved > 0) { 57108 var label = 'less'; 57109 } else { 57110 var label = 'more'; 57111 } 57112 57113 var msg1 = '<p>' + UTIL.displayMoney(pmtRequest) + ' payment requested</p>'; 57114 var msg2 = '<p>' + UTIL.displayMoney(pmtApproved) + ' payment approved</p>'; 57115 var msg3 = '<p style="margin-top: 24px; font-weight: bold; color: red;">Actual payment ' + UTIL.displayMoney(pmtRequest - pmtApproved) + ' ' + label + ' than requested</p>'; 57116 var htm = '<div id="pop-pax-payment-warning">' + msg1 + msg2 + msg3 + '</p>'; 57117 57118 GLO.Popup.Warning.open(htm, 'Amount Different'); 57119 } 57120 } 57121 _pax.postCancelTransToPAXApi = function(isSilentMode) { 57122 var uri = paxApiSvcBaseUrl + 'api/PAX/cancel'; 57123
57124 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" }) 57125 .success(function(data, textStatus, jqXHR) { 57126 window.onbeforeunload = null; 57127 var htm = '<div id="pop-cancel-emv-connect">' + data.result + '</div>'; 57128 var isSilentMode = true; 57129 57130 if (!isSilentMode && $('#pop-cancel-emv-connect').length === 0) { 57131 GLO.Popup.Success.open(htm, 'Cancel PAX EMV Connection'); //toDo: comment this out after Beta goes live (this is just for testing) 57132 } 57133 }) 57134 .error(function(jqXHR, textStatus, errorThrown) { 57135 new GLO.Popup.Error('Error communicating with PAX device'); 57136 }); 57137 } 57138 //connect to selected device 57139 _pax.ConnectPAXDevice = function(i) { 57140 var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice'; 57141 57142 var COMPort = COMPorts[i]; 57143 COMPort.TerminalUniqueId= SA.POS.PAX.uuid; 57144 COMPort.OSVersion = SA.POS.PAX.osVersion; 57145 var jsonCOMPort = JSON.stringify(COMPort); 57146 57147 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" }) 57148 .success(function(data, textStatus, jqXHR) { 57149 window.onbeforeunload = null; 57150 //update the device list table 57151 _pax.ShowSelectedDeviceInDeviceList(data); 57152 //_pax.setvar(data.DeviceId); 57153 new GLO.Popup.Success('Device connected.', 19000); 57154 }) 57155 .error(function(jqXHR, textStatus, errorThrown) { 57156 GLO.UI.Form.resetProcessing(); 57157 new GLO.Popup.Error('Unable to Connect to Selected Device'); 57158 }); 57159 } 57160 57161 _pax.ShowSelectedDeviceInDeviceList = function(paxDevice) { 57162 57163 //loop thru device list table and reset the table 57164 $('#ComPortsList tr').each(function(i,row){ 57165 $(this).find('td').each(function(j,cell){ 57166 if (typeof cell !== 'undefined') { 57167 if (cell.innerHTML == '<span>Selected</span>') { 57168 cell.innerHTML = '<td><span id="btnConnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.ConnectPAXDevice(' + i + ')" tabindex="1" title="Select"><a>Select</a></span></td>'; 57169 } 57170 } 57171 }); 57172 }); 57173 57174 //loop thru device list table and mark the selected device 57175 $('#ComPortsList tr').each(function(i,row){ 57176 $(this).find('td').each(function(j,cell){ 57177 if (typeof cell !== 'undefined') { 57178 if (cell.innerText != "" && (cell.innerText == paxDevice.SerialPort || cell.innerText == paxDevice.IPAddress)) { 57179 row.cells[4].innerHTML = '<span>Selected</span>'; 57180 } 57181 } 57182 }); 57183 }); 57184 } 57185 57186 _pax.ShowSelectedWifiDeviceInDeviceList = function(paxDevice) { 57187 57188 //loop thru device list table and reset the table 57189 $('#PAXWifiDeviceList tr').each(function(i,row){ 57190 $(this).find('td').each(function(j,cell){ 57191 if (typeof cell !== 'undefined') { 57192 if (cell.innerHTML == '<span>Selected</span>') { 57193 cell.innerHTML = '<td><span id="btnConnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.ConnectPAXWifiDevice(' + i + ')" tabindex="1" title="Select"><a>Select</a></span></td>'; 57194 } 57195 } 57196 }); 57197 }); 57198 57199 //loop thru device list table and mark the selected device 57200 $('#PAXWifiDeviceList tr').each(function(i,row){ 57201 $(this).find('td').each(function(j,cell){ 57202 if (typeof cell !== 'undefined') { 57203 if (cell.innerText != "" && (cell.innerText == paxDevice.SerialPort || cell.innerText == paxDevice.IPAddress)) { 57204 row.cells[4].innerHTML = '<span>Selected</span>'; 57205 } 57206 } 57207 }); 57208 }); 57209 } 57210 57211 _pax.DisconnectPAXDevice = function(COMPort) { 57212 var uri = GLO.Link.WebsiteDomain + 'api/PAX/DisconnectPAXDevice'; 57213 57214 var COMPort = COMPorts[i]; 57215 var jsonCOMPort = JSON.stringify(COMPort); 57216 57217 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" }) 57218 .success(function(data, textStatus, jqXHR) { 57219 window.onbeforeunload = null; 57220 57221 GLO.Popup.Success.open(data, 'Disconnect Pax Emv Reader', 19000); 57222 }) 57223 .error(function(jqXHR, textStatus, errorThrown) { 57224 GLO.UI.Form.resetProcessing(); 57225 new GLO.Popup.Error('Unable to Disconnect Device'); 57226 }); 57227 } 57228 57229 _pax.getPAXDeviceIdFromCookie = function() { 57230 var name = 'paxdevice' + "="; 57231 var decodedCookie = decodeURIComponent(document.cookie); 57232 var ca = decodedCookie.split(';'); 57233 for(var i = 0; i <ca.length; i++) { 57234 var c = ca[i];
57235 while (c.charAt(0) == ' ') { 57236 c = c.substring(1); 57237 } 57238 if (c.indexOf(name) == 0) { 57239 return c.substring(name.length, c.length); 57240 } 57241 } 57242 return ""; 57243 } 57244 57245 _pax.getPAXDeviceByDeviceId = function(deviceId) { 57246 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 57247 if (paxDeviceId == "") { 57248 if (deviceId == "") { 57249 GLO.Popup.closeAll(); 57250 new GLO.Popup.Error('Unable to find last used device. Please make sure device is connected and selected.'); 57251 return; 57252 } 57253 else { 57254 paxDeviceId = deviceId; 57255 } 57256 } 57257 var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPAXDeviceSettings/' + paxDeviceId; 57258 57259 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57260 .success(function(data, textStatus, jqXHR) { 57261 window.onbeforeunload = null; 57262 57263 _pax.ShowSelectedDeviceInDeviceList(data); 57264 _pax.ShowSelectedWifiDeviceInDeviceList(data); 57265 }) 57266 .error(function(jqXHR, textStatus, errorThrown) { 57267 new GLO.Popup.Error('Unable to get PAX Device Settings'); 57268 }); 57269 } 57270 57271 _pax.getPAXCred = function(deviceId) { 57272 var paxDeviceId = _pax.getPAXDeviceIdFromCookie(); 57273 if (paxDeviceId == "") { 57274 if (deviceId == "") { 57275 new GLO.Popup.Error('Unable to find last used device. Please make sure device is connected and selected.'); 57276 return; 57277 } 57278 else { 57279 paxDeviceId = deviceId; 57280 } 57281 } 57282 var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPAXCred/' + paxDeviceId; 57283 57284 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57285 .success(function(data, textStatus, jqXHR) { 57286 window.onbeforeunload = null; 57287 57288 _pax.ShowSelectedDeviceInDeviceList(data); 57289 }) 57290 .error(function(jqXHR, textStatus, errorThrown) { 57291 new GLO.Popup.Error('Unable to get PAX Device Settings'); 57292 }); 57293 } 57294 57295 return _pax; 57296})(); 57297 57298SA.POS.CCBolt = (function() { 57299 var _isConnected = false; 57300 var _currentPaymentMerchantIdString = null; 57301 57302 function _bolt(mid) { } 57303 57304 _bolt.getCurrentPaymentMerchantIdString = function() { 57305 return _currentPaymentMerchantIdString; 57306 } 57307 57308 //get the list of terminals associated with a merchantId 57309 _bolt.listTerminals = function(ccMID) { 57310 if (!ccMID) { 57311 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57312 return; 57313 } 57314 57315 var uri = GLO.Link.WebsiteDomain + 'api/bolt/listTerminals/' + ccMID; 57316 57317 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57318 .success(function(data, textStatus, jqXHR) { 57319 window.onbeforeunload = null; 57320 return data; 57321 }) 57322 .error(function(jqXHR, textStatus, errorThrown) { 57323 GLO.UI.Form.resetProcessing(); 57324 new GLO.Popup.Error('Unable to get CardConnect Terminals for merchant'); 57325 }); 57326 } 57327 57328 _bolt.initEmvDeviceScreen = function() { 57329 var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase(); 57330 57331 if (popup == 'setup-tips') { 57332 $('#btnTipPercent').find('a').click(); 57333 } 57334 } 57335 57336 _bolt.listTerminalDetailsWithCallback = function(ccMID,_callback) { 57337 if (!ccMID) { 57338 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57339 return; 57340 } 57341 57342 var uri = GLO.Link.WebsiteDomain + 'api/bolt/terminalDetails/' + ccMID; 57343 57344 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57345 .success(function(data, textStatus, jqXHR) { 57346 window.onbeforeunload = null; 57347 return _callback(data); 57348 }) 57349 .error(function(jqXHR, textStatus, errorThrown) { 57350 GLO.UI.Form.resetProcessing(); 57351 new GLO.Popup.Error('Unable to get CardConnect Terminals Details for merchant'); 57352 }); 57353 } 57354 57355 _bolt.loadDeviceList = function(json) { 57356 var deviceCount = 0; 57357 57358 if (UTIL.isJson(json)) { //typeof json.length !== 'undefined' 57359 $('#pax-column-header').addClass('hide'); 57360 $('#bolt-column-header').removeClass('hide'); 57361 57362 var bolt = JSON.parse(json); 57363 var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print'));
57364 deviceCount = bolt.terminalDetails.length; 57365 57366 for (var i = 0; i < bolt.terminalDetails.length; i++) { //Append each row to html table 57367 var isConnected = bolt.terminalDetails[i].connected; 57368 var hasPrinter = bolt.terminalDetails[i].deviceCapabilities.printer; 57369 //var prettyName = SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType); 57370 var midString = bolt.terminalDetails[i].merchantId; 57371 var btnConnect = '<span id="btnConnect" class="btnAdd"><a onclick="SA.POS.CCBolt.SaveBoltDevice(\'' + midString + '\',\'' + bolt.terminalDetails[i].hsn + '\', this);">Select</a></span>'; 57372 57373 var tr = $('<tr/>'); 57374 tr.append('<td class="bolt-column-connect-device">' + btnConnect + '</td>'); 57375 tr.append('<td class="bolt-column-name">' + bolt.terminalDetails[i].hsn + '</td>'); 57376 tr.append('<td class="bolt-column-device-connected">' + UI.getCheckmark(isConnected) + '</td>'); 57377 tr.append('<td class="bolt-column-device-type">' + SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType) + '</td>'); 57378 tr.append('<td class="bolt-column-device-emv">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.emv) + '</td>'); 57379 tr.append('<td class="bolt-column-device-nfc">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.nfc) + '</td>'); 57380 tr.append('<td class="bolt-column-device-signature hide">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.signature) + '</td>'); 57381 tr.append('<td class="bolt-column-device-printer-has">' + UI.getCheckmark(hasPrinter) + '</td>'); 57382 //tr.append('<td>' + '<span id="btnDisconnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.DisconnectPAXDevice()" tabindex="1" title="Unselect"><a>Un-Select</a></span>' + '</td>'); 57383 $('table#ComPortsList').append(tr); 57384 57385 if (hasPrinter) { // && isConnected 57386 isDisplayPrintOptions = true; 57387 } 57388 } 57389 57390 //check if bolt device cookie exists 57391 var serialNo = SA.POS.CCBolt.getDeviceSerialNo(); 57392 57393 if (serialNo && serialNo.length > 1) { 57394 SA.POS.CCBolt.ShowSelectedBoltDeviceInDeviceList(serialNo); 57395 } 57396 57397 UI.initTableSorter($('#report-main table.tablesorter')); 57398 } 57399 57400 var jVivoPay = $('#btnCCMobileSdkEnabled #toggleCCMobileSdk'); 57401 57402 if (jVivoPay.length) { 57403 if (jVivoPay.prop('checked')) { 57404 var btnBlue = '<b style="display: inline-block; padding: 2px 24px; border-radius: 8px; background-color: blue; color: white;">'; 57405 var htmVivoSetupList = '<li>Open an appointment</li>' 57406 + '<li>In the Edit Appointment popup, press the price <small>(top left corner)</small></li>' 57407 + '<li>Press Credit</li>' 57408 + '<li>In the Checkout Screen <b class="arrow-right">➜</b> press the big blue button: ' + btnBlue + 'Next</b></li>' 57409 + '<li>Press <b class="arrow-right">➜</b> <b style="color: blue;">Connect a different card reader</b></li>' 57410 + '<li>Turn on you Vivo Pay card reader</li>' 57411 + '<li>In the <b>Select a Reader</b> popup, select your card reader</li>' 57412 + '<li>Press the blue button: ' + btnBlue + 'Charge Card</b></li>' 57413 + '<li>The first time the card reader connects to your device it might take up to 20-30 seconds, after that it will only take a couple seconds to connect</li>' 57414 + '<li>When the popup changes from <b>Searching</b> <i>to</i> <b>Please Swipe, Tag, or Insert</b> then you can process the card</li>'; 57415 57416 var htm = '<p>Your Vivo Pay Device is Enabled</p><p>To complete your Vivo Pay Device Setup</p><ol>' + htmVivoSetupList + '</ol>'; 57417 GLO.Popup.Info.open('<div id="pop-vivo-pay-enable">' + htm + '</div>', 'Vivo Pay Device Setup'); 57418 } else if ($('#ComPortsList tbody tr').length === 0) { 57419 var htm = '<p>Enable <b style="color: black;">Mobile Reader</b> to begin the setup of your Vivo Pay Device</p>'; 57420 GLO.Popup.Info.open('<div id="pop-vivo-pay-device-setup">' + htm + '</div>', 'Vivo Pay Device Setup'); 57421 } 57422 } else if (deviceCount == 0) { 57423 var merchantType = $('#manage-emv-header').attr('merchant_type_cd'); 57424 57425 if (merchantType == 50) { 57426 var htmVP3300 = 'No Vivo Pay <span class="narrow-text" style="color: inherit;">(ID-Tech VP3300)</span>'; 57427 var msg1 = '<p>' + htmVP3300 + ' credit card device found</p>'; 57428 57429 var uri = GLO.Link.WebsiteDomain + 'provider/manage/ManageEMV?clover=1'; 57430 var btnClover = '<span id="btnConnectClover" class="btnAdd">
57430<a onclick="GLO.Uri.gotoUri(\'' + uri + '\', this, event, true);">Load Clover Devices</a></span>'; 57431 var msg2 = '<p>Would you like to ' + btnClover + ' to connect to</p>'; 57432 } else { 57433 var msg1 = '<p>No credit card device found</p>'; 57434 var msg2 = '<p>If you need to connect a credit card reader please contact ' + GLO.Info.getScheduleAnyoneHtm() + '</p>'; 57435 } 57436 57437 var htm = '<div id="pop-error-emv-device-list-empty">' + msg1 + msg2 + '</div>'; 57438 GLO.Popup.Warning.open(htm, 'No Devices Found'); 57439 } 57440 57441 // if (isDisplayPrintOptions) { 57442 // SA.POS.CCBolt.displayPrinterOptions('Clover'); 57443 // } 57444 } 57445 _bolt.loadPrinterSettings = function(json) { 57446 if (UTIL.isJson(json)) { //typeof json.length !== 'undefined' 57447 57448 var bolt = JSON.parse(json); 57449 var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print')); 57450 57451 for (var i = 0; i < bolt.terminalDetails.length; i++) { //Append each row to html table 57452 var isConnected = bolt.terminalDetails[i].connected; 57453 var hasPrinter = bolt.terminalDetails[i].deviceCapabilities.printer; 57454 //var prettyName = SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType); 57455 var midString = bolt.terminalDetails[i].merchantId; 57456 57457 if (hasPrinter) { // && isConnected 57458 isDisplayPrintOptions = true; 57459 } 57460 } 57461 } 57462 57463 if (isDisplayPrintOptions) { 57464 SA.POS.CCBolt.displayPrinterOptions('Clover'); 57465 } 57466 } 57467 57468 _bolt.displayPrinterOptions = function(prettyName) { 57469 var rdoStart = '<input type="radio" name="emv_print_cd" onchange="SA.POS.CCBolt.changePrintSetting(this)" '; 57470 var cbAsNeededStaffPrint = '<input type="checkbox" name="emv_print_as_needed_staff_print_cd" onchange="SA.POS.CCBolt.changeStaffPrintSetting(this)" '; 57471 var aStandAlone = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'/provider/manage/receipt?helloback=advanced&tabback=payment\', this, event, true)">stand-alone printer</a>'; 57472 var smallNever = '<small>(suggested if have ' + aStandAlone + ' or prefer going green and just email/texting receipt)</small>'; 57473 var smallAsk = '<small style="white-space: pre-wrap;">(suggested if you have no other printer and want to print occasionally)</small>'; 57474 var labelAsNeeded = '<label for="emv_print_as_needed_staff_print_cd">Send staff prints to receipt printer</label>'; 57475 57476 if (innerWidth < 760) { 57477 var smallNever = '<small>(have ' + aStandAlone + ' or just email/text receipt)</small>'; 57478 } 57479 57480 var htm = '<div id="manage-emv-printer-options">' 57481 + '<h5>Use ' + prettyName + ' Printer</h5>' 57482 + '<div>' + rdoStart + 'id="emv_print_always"/><label for="emv_print_always"><b>Always for Credit Card Payments</b> <small>(suggested if you have no other printer)</small></label></div>' 57483 + '<div>' + rdoStart + 'id="emv_print_once"/><label for="emv_print_once"><b>After Credit Card Payment</b> <small>(good option if you also have ' + aStandAlone + ')</small></label></div>' 57484 + '<div>' + rdoStart + 'id="emv_print_as_needed"/><label for="emv_print_as_needed"><b>Ask Customer</b> ' + smallAsk + '</label>' 57485 + '<div id="emv_print_as_needed_staff_print" style="margin-left:40px" class="hide">' + cbAsNeededStaffPrint + ' id="emv_print_as_needed_staff_print_cd"/>' + labelAsNeeded + '</div>' 57486 + '</div>' 57487 + '<div>' + rdoStart + 'id="emv_print_never"/><label for="emv_print_never"><b>Never Use This Printer</b> ' + smallNever + '</label></div>' 57488 + '</div>'; 57489 57490 // $('#manage-emv-header-message').replaceWith(htm); 57491 $("#clover-receipt-printer-settings").html(htm); 57492 _setCurrentPrintSetting(); 57493 } 57494 57495 function _setCurrentPrintSetting() { 57496 var usePrinterDB = UTIL.parseBool($('#manage-emv-header').attr('use_builtin_receipt_printer')); 57497 var usePrinterCookie = $.cookies.get('emv-print'); 57498 57499 if (usePrinterCookie == 'once') { 57500 $('#emv_print_once').prop('checked', true); 57501 $('#emv_print_as_needed_staff_print').addClass('hide'); 57502 } else if (usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) { 57503 $('#emv_print_as_needed').prop('checked', true); 57504 $('#emv_print_as_needed_staff_print').removeClass('hide'); 57505 if (usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) { 57506 $('#emv_print_as_needed_staff_print_cd').attr('checked','checked'); 57507 } 57508 else { 57509 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked'); 57510 } 57511 57512 }else if (usePrinterCookie == 'always') { 57513 $('#emv_print_always').prop('checked', true); 57514 $('#emv_print_as_needed_staff_print').addClass('hide'); 57515 } else if (usePrinterCookie == 'never') { 57516 $('#emv_print_never').prop('checked', true); 57517 $('#emv_print_as_needed_staff_print').addClass('hide'); 57518 } else if (usePrinterDB) { 57519 $('#emv_print_once').prop('checked', true); 57520 $('#emv_print_as_needed_staff_print').addClass('hide'); 57521 } else { 57522 $('#emv_print_never').prop('checked', true); 57523 $('#emv_print_as_needed_staff_print').addClass('hide'); 57524 } 57525 } 57526 _bolt.changeStaffPrintSetting = function(checkbox) { 57527 var cookieValue = 'asneeded'; 57528 var useBuiltIn = true; 57529 if (checkbox.checked) { 57530 cookieValue = 'asneeded+' 57531 $('#emv_print_as_needed_staff_print_cd').attr('checked','checked'); 57532 } 57533 else { 57534 cookieValue = 'asneeded'; 57535 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked') 57536 } 57537 UTIL.setCookie("emv-print", cookieValue); 57538 GLO.Log.insertSimple('Set Emv Print Cookie', 'bolt.changePrintSetting: use-built-in-printer = ' + useBuiltIn + ' (cookieValue = ' + cookieValue + ')', 'warning'); 57539 var cookieValueEncoded = encodeURIComponent(cookieValue); 57540 _changePrintSetting(useBuiltIn,cookieValueEncoded); 57541 57542 } 57543 57544 _bolt.changePrintSetting = function(rdo) { //= save to DB + set cookie 57545 if (rdo.id == 'emv_print_once') { 57546 var cookieValue = 'once'; 57547 var useBuiltIn = true; 57548 //uncheck asneeded staff checkbox 57549 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked'); 57550 $('#emv_print_as_needed_staff_print').addClass('hide'); 57551 } else if (rdo.id == 'emv_print_as_needed') { 57552 var cookieValue = 'asneeded'; 57553 var useBuiltIn = true; 57554 $('#emv_print_as_needed_staff_print').removeClass('hide'); 57555 }else if (rdo.id == 'emv_print_always') { 57556 var cookieValue = 'always'; 57557 var useBuiltIn = true; 57558 //uncheck asneeded staff checkbox 57559 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked'); 57560 $('#emv_print_as_needed_staff_print').addClass('hide'); 57561 } else if (rdo.id == 'emv_print_never') { 57562 var cookieValue = 'never'; 57563 var useBuiltIn = false; 57564 //uncheck asneeded staff checkbox 57565 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked'); 57566 $('#emv_print_as_needed_staff_print').addClass('hide'); 57567 } else { 57568 var cookieValue = null; 57569 var useBuiltIn = false; 57570 //uncheck asneeded staff checkbox 57571 $('#emv_print_as_needed_staff_print_cd').removeAttr('checked'); 57572 $('#emv_print_as_needed_staff_print').addClass('hide'); 57573 } 57574 UTIL.setCookie("emv-print", cookieValue); 57575 GLO.Log.insertSimple('Set Emv Print Cookie', 'bolt.changePrintSetting: use-built-in-printer = ' + useBuiltIn + ' (cookieValue = ' + cookieValue + ')', 'warning'); 57576 _changePrintSetting(useBuiltIn,cookieValue); 57577 57578 } 57579 function _changePrintSetting(useBuiltIn, cookieValue) { 57580 var uri = GLO.Link.WebsiteDomain + 'provider/manage/SetEMVPrinter?useBuiltIn=' + useBuiltIn + '&printmode=' + cookieValue; 57581
57582 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" }) 57583 .success(function(data, textStatus, jqXHR) { 57584 GLO.Popup.Success.open('Print Setting Saved', 'Payment Device Printer'); 57585 }) 57586 .error(function(jqXHR, textStatus, errorThrown) { 57587 GLO.UI.Form.resetProcessing(); 57588 new GLO.Popup.Error('Unable to save to print setting'); 57589 }); 57590 } 57591 57592 function _getDeviceTypeCode(deviceTypeLabel) { 57593 if (UTIL.isEmpty(deviceTypeLabel)) { 57594 return ''; 57595 } 57596 57597 deviceTypeLabel = deviceTypeLabel.toLowerCase(); 57598 57599 if (deviceTypeLabel.indexOf('clover mini') !== -1) { 57600 return 35; 57601 } else if (deviceTypeLabel.indexOf('flex') !== -1) { 57602 return 38; 57603 } else if (deviceTypeLabel.indexOf('ingenico 3') !== -1) { 57604 return 51; 57605 } else if (deviceTypeLabel.indexOf('ismp4') !== -1) { 57606 return 52; 57607 } else if (deviceTypeLabel.indexOf('ingenico') !== -1) { 57608 return 50; 57609 } 57610 57611 return ''; 57612 } 57613 57614 _bolt.changeTipMode = function(rdo) { //= save to DB + set cookie 57615 if (rdo.id == 'tip-by-amount') { 57616 $('#tip-by-amount').attr('checked','checked'); 57617 $('#tip-by-percent').removeAttr('checked'); 57618 $('#tipPercentsFieldset').addClass('hide'); 57619 } else if (rdo.id == 'tip-by-percent') { 57620 $('#tip-by-percent').attr('checked','checked'); 57621 $('#tip-by-amount').removeAttr('checked'); 57622 $('#tipPercentsFieldset').removeClass('hide'); 57623 } 57624 57625 } 57626 57627 _bolt.SaveBoltDevice = function(ccMID, serialNo, element) { 57628 var deviceTypeLabel = $(element).closest('tr').find('.bolt-column-device-type').text(); 57629 var deviceTypeCode = _getDeviceTypeCode(deviceTypeLabel) 57630 //var json = { "devicetype": deviceTypeCode }; 57631 var uri = GLO.Link.WebsiteDomain + 'api/bolt/SaveBoltDevice/' + ccMID + '/' + serialNo + '?devicetype=' + deviceTypeCode; 57632 57633 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" }) 57634 .success(function(data, textStatus, jqXHR) { 57635 window.onbeforeunload = null; 57636 57637 _bolt.ShowSelectedBoltDeviceInDeviceList(serialNo); 57638 GLO.Popup.Success.open('Reloading Device List...', 'Device Selected', 19000); 57639 57640 setTimeout(function() { 57641 location.reload(); 57642 }, 3100); 57643 }) 57644 .error(function(jqXHR, textStatus, errorThrown) { 57645 GLO.UI.Form.resetProcessing(); 57646 new GLO.Popup.Error('Unable to save to Selected Device'); 57647 }); 57648 } 57649 57650 _bolt.isBoltMobileSdkEnabled = function() { 57651 var name = 'boltmobilesdk' + "="; 57652 var decodedCookie = decodeURIComponent(document.cookie); 57653 var ca = decodedCookie.split(';'); 57654 for(var i = 0; i <ca.length; i++) { 57655 var c = ca[i]; 57656 while (c.charAt(0) == ' ') { 57657 c = c.substring(1); 57658 } 57659 if (c.indexOf(name) == 0) { 57660 return c.substring(name.length, c.length); 57661 } 57662 } 57663 return ""; 57664 } 57665 57666 _bolt.SetMobileSdkStatus = function() { 57667 var boltMobileSdkStatus = SA.POS.CCBolt.isBoltMobileSdkEnabled(); 57668 57669 if (boltMobileSdkStatus == 'enabled') { 57670 $('#toggleCCMobileSdk').prop("checked",true); 57671 } 57672 else { 57673 $('#toggleCCMobileSdk').prop("checked",false); 57674 } 57675 } 57676 57677 _bolt.ToggleMobileSdk = function(ccMID) { 57678 var mobileSdkEnabled = 'disable'; 57679 var isEnabled = $('#toggleCCMobileSdk').prop("checked"); 57680 57681 if (isEnabled) { 57682 mobileSdkEnabled = 'enable'; 57683 } 57684 57685 var uri = GLO.Link.WebsiteDomain + 'api/bolt/ToggleMobileSdk/' + ccMID + '?isEnabled=' + mobileSdkEnabled; 57686 57687 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" }) 57688 .success(function(data, textStatus, jqXHR) { 57689 window.onbeforeunload = null; 57690 if (isEnabled) { 57691 GLO.Popup.Success.open('Enabled Mobile Reader...', 'Bolt Mobile', 19000); 57692 setTimeout(function() { location.reload(); }, 400); 57693 } 57694 else { 57695 GLO.Popup.Success.open('Disabled Mobile Reader...', 'Bolt Mobile', 19000); 57696 setTimeout(function() { location.reload(); }, 400); 57697 } 57698 }) 57699 .error(function(jqXHR, textStatus, errorThrown) { 57700 $('#toggleCCMobileSdk').prop("checked",!isEnabled);//previous state 57701 GLO.UI.Form.resetProcessing(); 57702 new GLO.Popup.Error('Unable to enable or disable Bolt Mobile'); 57703 }); 57704 } 57705 57706 _bolt.deviceTypePrettyName = function(deviceType) { 57707 if (deviceType == 'iPP320') { 57708 return 'iPP320 Ingenico'; 57709 } else if (UTIL.startsWith(deviceType, 'Mini')) { 57710 return 'Clover ' + deviceType; 57711 } else { 57712 return deviceType; 57713 } 57714 } 57715 57716 _bolt.ShowSelectedBoltDeviceInDeviceList = function(serialNo) { 57717 57718 //loop thru device list table and mark the selected device 57719 $('#ComPortsList tr').each(function(i,row){ 57720 $(this).find('td').each(function(j,cell){ 57721 if (typeof cell !== 'undefined') { 57722 if (cell.innerText != "" && (cell.innerText == serialNo)) { 57723 row.cells[0].innerHTML = UI.getCheckmark(true); // '<span>Selected</span>'; 57724 } 57725 } 57726 }); 57727 }); 57728 } 57729 57730 _bolt.postAuthResponseToBoltApi = async function(authResponse,ccMID,serialNo, isSale, tipAmount, cid, smid, scid, ccArr, isTipFromDevice) {
57731 var uri = GLO.Link.WebsiteDomain + 'api/bolt/payment/' + ccMID + '/' + serialNo + '?isSale=' + isSale + '&client=' + cid + '&smid=' + smid + '&tip=' + tipAmount; 57732 var tipSplit = UserPortal.Price.QuickTip.getSplit(); 57733 57734 if (scid) { 57735 uri += '&scid=' + scid; 57736 } 57737 57738 if (!UTIL.isEmpty(tipSplit)) { 57739 uri += '&tipSplit=' + tipSplit; 57740 } 57741 57742 if (UTIL.parseBool(isTipFromDevice)) { 57743 uri += '&isTipFromDevice=true'; 57744 } 57745 57746 var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml()); 57747 var ccArrJsonString = JSON.stringify(ccArr); 57748 var jsd = { "authResponse": authResponse, "discount_xml": dxml , "merchants": ccArrJsonString }; 57749 57750 UserPortal.Price.Payment.addPayMethDiscount(jsd, true, 10); 57751 57752 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsd, dataType: 'html', contentType: 'application/x-www-form-urlencoded; charset=UTF-8' }) 57753 .success(function(data, textStatus, jqXHR) { 57754 window.onbeforeunload = null; 57755 GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop')); 57756 57757 return data; 57758 }) 57759 .error(function(jqXHR, textStatus, errorThrown) { 57760 var fn = function() { 57761 UserPortal.reloadTicket(smid); 57762 } 57763 57764 GLO.UI.Form.resetProcessing(); 57765 GLO.Popup.Error.open('Unable to POST Payment response', 'Payment Warning', fn); 57766 }); 57767 57768 return await jqxhr; 57769 } 57770 57771 _bolt.postAddtionalPaymentsToBoltApi = function(serverResponse,ccMID,serialNo, isSale, tipAmount, cid, multiScheduleId, scid,ccArr) { 57772 var uri = GLO.Link.WebsiteDomain + 'api/bolt/multimerchantpayment/' + ccMID + '/' + serialNo + '?isSale=' + isSale + '&client=' + cid + '&smid=' + multiScheduleId + '&tip=' + tipAmount; 57773 57774 if (scid) { 57775 uri += '&scid=' + scid; 57776 } 57777 57778 var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml()); 57779 var ccArrJsonString = JSON.stringify(ccArr); 57780 var jsd = { "serverResponse": serverResponse, "discount_xml": dxml , "merchants": ccArrJsonString }; 57781 UserPortal.Price.Payment.addPayMethDiscount(jsd, true, 10); 57782 57783 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsd, dataType: 'html', contentType: 'application/x-www-form-urlencoded; charset=UTF-8' }) 57784 .success(function(data, textStatus, jqXHR) { 57785 window.onbeforeunload = null; 57786 GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop')); 57787 var paymentResponse = UTIL.safeParseJson(data); 57788 57789 if (!UserPortal.Price.Payment.saveCreditCard_complete(paymentResponse.receipthtml, true, true, 2)) { 57790 if (paymentResponse.receipthtml !== '') { 57791 UserPortal.Price.Payment.saveCreditCard_error(paymentResponse.receipthtml); 57792 UserPortal.reloadTicket(multiScheduleId); 57793 } else { 57794 var msg = $(paymentResponse.receipthtml).html(); 57795 _displayEmvCommunicateError(msg , 'Payment Failed', true); 57796 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 57797 57798 if (jPopSwipe.length) { 57799 jPopSwipe.find('#imgThrobberContainer').remove(); 57800 jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide'); 57801 } 57802 } 57803 } 57804 }) 57805 .error(function(jqXHR, textStatus, errorThrown) { 57806 var fn = function() { 57807 UserPortal.reloadTicket(multiScheduleId); 57808 } 57809 57810 GLO.UI.Form.resetProcessing(); 57811 GLO.Popup.Error.open('Unable to POST Payment response', 'Payment Warning', fn); 57812 }); 57813 57814 } 57815 57816 _bolt.connect = async function(ccMID,serialNo) { 57817 if (!ccMID) { 57818 new GLO.Popup.Error('<div><p>Fiserv merchant not connected to ' + GLO.Info.getScheduleAnyoneHtm(
57818) + '</p><p>Please refresh page and try again</p></div>', 'Merchant Id Missing'); 57819 return; 57820 } else if (UTIL.isEmpty(serialNo) && GLO.Info.roleType > 169) { 57821 //if ($('#pop-warn-bolt-connect').closest('.glopop').length === 0) { 57822 var labelConnect = '<label><i>Card Reader</i> Not Connected</label>'; 57823 var aConnect = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/ManageEMV\', this, event, true)" title="Press Here to Setup Card Reader">Setup Card Reader</a>'; 57824 var btnConnect = '<span class="btnAdd">' + aConnect + '</span>'; 57825 var htmHello = '<div id="hello-bar-warn-bolt-connect-inner">' + labelConnect + btnConnect + '</div>'; 57826 57827 var helloBarId = 'hello-bar-warn-bolt-connect', cssClass = 'hello-bar-warn'; 57828 var jpopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 57829 57830 GLO.Popup.addHelloBar(jpopSwipe, htmHello, helloBarId, cssClass); //GLO.Popup.Warning.open(htm, 'Card Reader Not Connected'); 57831 return; 57832 } 57833 57834 var uri = GLO.Link.WebsiteDomain + 'api/bolt/connect/' + ccMID + '/' + serialNo; 57835 57836 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57837 .success(function(data, textStatus, jqXHR) { 57838 window.onbeforeunload = null; 57839 return data; 57840 }) 57841 .error(function(jqXHR, textStatus, errorThrown) { 57842 GLO.UI.Form.resetProcessing(); 57843 var trswipe = $('#appt-price-popup').closest('.glopop').find('tr.swipe'); 57844 57845 if (trswipe.length) { 57846 if (UserPortal.Price.Payment.openCreditCard(false, true)) { 57847 setTimeout(UserPortal.Price.Payment.resetSaveButton, 200); 57848 } 57849 } 57850 57851 GLO.Popup.Error.open('Unable to connect to card reader', 'Payment Issue'); 57852 }); 57853 57854 return await jqxhr; 57855 } 57856 57857 _bolt.disconnect = async function(ccMID,serialNo) { 57858 if (!ccMID) { 57859 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57860 return; 57861 } 57862 57863 var uri = GLO.Link.WebsiteDomain + 'api/bolt/disconnect/' + ccMID + '/' + serialNo; 57864 57865 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57866 .success(function(data, textStatus, jqXHR) { 57867 window.onbeforeunload = null; 57868 return data; 57869 }) 57870 .error(function(jqXHR, textStatus, errorThrown) { 57871 GLO.UI.Form.resetProcessing(); 57872 new GLO.Popup.Error('Unable to disconnect CardConnect Terminal for merchant'); 57873 }); 57874 57875 return await jqxhr; 57876 } 57877 57878 _bolt.ping = async function(ccMID,serialNo) { 57879 57880 if (!ccMID) { 57881 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57882 return; 57883 } 57884 57885 var uri = GLO.Link.WebsiteDomain + 'api/bolt/ping/' + ccMID + '/' + serialNo; 57886 57887 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57888 .success(function(data, textStatus, jqXHR) { 57889 window.onbeforeunload = null; 57890 return data; 57891 }) 57892 .error(function(jqXHR, textStatus, errorThrown) { 57893 GLO.UI.Form.resetProcessing(); 57894 new GLO.Popup.Error('Unable to Ping device'); 57895 }); 57896 57897 return await jqxhr; 57898 } 57899 57900 _bolt.display = async function(ccMID,serialNo,displayText) { 57901 57902 if (!ccMID) { 57903 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57904 return; 57905 } 57906 57907 var uri = GLO.Link.WebsiteDomain + 'api/bolt/display/' + ccMID + '/' + serialNo + '?displayText=' + encodeURIComponent(displayText); 57908 57909 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57910 .success(function(data, textStatus, jqXHR) { 57911 window.onbeforeunload = null; 57912 return data; 57913 }) 57914 .error(function(jqXHR, textStatus, errorThrown) { 57915 GLO.UI.Form.resetProcessing(); 57916 new GLO.Popup.Error('Unable to Display on CardConnect Terminal for merchant'); 57917 }); 57918 57919 return await jqxhr; 57920 } 57921 57922 _bolt.clearDisplay = async function(ccMID,serialNo) { 57923 57924 if (!ccMID) { 57925 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57926 return; 57927 } 57928 57929 var uri = GLO.Link.WebsiteDomain + 'api/bolt/cleardisplay/' + ccMID + '/' + serialNo; 57930
57931 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 57932 .success(function(data, textStatus, jqXHR) { 57933 window.onbeforeunload = null; 57934 return data; 57935 }) 57936 .error(function(jqXHR, textStatus, errorThrown) { 57937 GLO.UI.Form.resetProcessing(); 57938 new GLO.Popup.Error('Unable to Clear Display on CardConnect Terminal for merchant'); 57939 }); 57940 57941 return await jqxhr; 57942 } 57943 57944 _bolt.tip = async function(ccMID,serialNo,multiScheduleId,amount, ticketTotal) { 57945 if (!ccMID) { 57946 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57947 return; 57948 } 57949 57950 let subTotal = (Math.round(amount * 100)); 57951 var uri = GLO.Link.WebsiteDomain + 'api/bolt/tip/' + ccMID + '/' + serialNo; 57952 var payload = { "multiScheduleId": multiScheduleId , "amount": subTotal, "total": (Math.round(ticketTotal * 100)) }; 57953 57954 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' }) 57955 .success(function(data, textStatus, jqXHR) { 57956 window.onbeforeunload = null; 57957 return data; 57958 }) 57959 .error(function(jqXHR, textStatus, errorThrown) { 57960 GLO.UI.Form.resetProcessing(); 57961 new GLO.Popup.Error('Unable to invoke tip function for merchant'); 57962 }); 57963 57964 return await jqxhr; 57965 } 57966 57967 _bolt.printReceiptOnBolt = async function(ccMID,serialNo,multiScheduleId) { 57968 if (!ccMID) { 57969 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57970 return; 57971 } 57972 57973 var uri = GLO.Link.WebsiteDomain + 'api/bolt/printreceipt/' + ccMID + '/' + serialNo; 57974 var payload = {"multiScheduleId": multiScheduleId , "amount": 0}; 57975 57976 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' }) 57977 .success(function(data, textStatus, jqXHR) { 57978 window.onbeforeunload = null; 57979 return data; 57980 }) 57981 .error(function(jqXHR, textStatus, errorThrown) { 57982 GLO.UI.Form.resetProcessing(); 57983 new GLO.Popup.Error('Unable to invoke print Receipt function for merchant'); 57984 }); 57985 57986 return await jqxhr; 57987 } 57988 57989 57990 _bolt.readConfirmation = async function(ccMID,serialNo,multiScheduleId,amount) { 57991 57992 if (!ccMID) { 57993 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 57994 return; 57995 } 57996 57997 var uri = GLO.Link.WebsiteDomain + 'api/bolt/readconfirmation/' + ccMID + '/' + serialNo; 57998 var payload = {"multiScheduleId": multiScheduleId }; 57999 58000 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' }) 58001 .success(function(data, textStatus, jqXHR) { 58002 window.onbeforeunload = null; 58003 return data; 58004 }) 58005 .error(function(jqXHR, textStatus, errorThrown) { 58006 GLO.UI.Form.resetProcessing(); 58007 new GLO.Popup.Error('Unable to read confirmation for merchant'); 58008 }); 58009 58010 return await jqxhr; 58011 } 58012 58013 _bolt.receiptConfirmation = async function(ccMID,serialNo,multiScheduleId) { 58014 58015 if (!ccMID) { 58016 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 58017 return; 58018 } 58019 58020 var uri = GLO.Link.WebsiteDomain + 'api/bolt/receiptconfirmation/' + ccMID + '/' + serialNo; 58021 var payload = {"multiScheduleId": multiScheduleId }; 58022 58023 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' }) 58024 .success(function(data, textStatus, jqXHR) { 58025 window.onbeforeunload = null; 58026 return data; 58027 }) 58028 .error(function(jqXHR, textStatus, errorThrown) { 58029 GLO.UI.Form.resetProcessing(); 58030 new GLO.Popup.Error('Unable to ask for receipt confirmation for merchant'); 58031 }); 58032 58033 return await jqxhr; 58034 } 58035 58036 _bolt.authCard = async function(ccMID,overrideMID,serialNo,multiScheduleId,amount,totalMultiMerchant) { 58037 58038 if (!ccMID) { 58039 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 58040 return; 58041 } 58042 58043 var uri = GLO.Link.WebsiteDomain + 'api/bolt/authCard/' + ccMID + '/' + serialNo; 58044 var payload = {"MultiScheduleId": multiScheduleId , "Amount": amount, "OverrideMid": overrideMID}; 58045 58046 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' }) 58047 .success(function(data, textStatus, jqXHR) { 58048 window.onbeforeunload = null; 58049 //var jd = JSON.parse(data); 58050 return data; 58051 }) 58052 .error(function(jqXHR, textStatus, errorThrown) { 58053 GLO.UI.Form.resetProcessing(); 58054 new GLO.Popup.Error('Unable to authorize card for merchant'); 58055 }); 58056 58057 return await jqxhr; 58058 } 58059 58060 _bolt.checkIfPaymentActuallyProcessed = function(smid) { 58061 if (smid > 0) { 58062 var price = UserPortal.Price.getPrice(true, true, true); 58063 var payment = UserPortal.Price.Payment.getTotalPaymentOnTicket(); 58064 var amount = UTIL.coalesceMoney(price - payment); 58065 58066 _checkIfPaymentActuallyProcessed(smid, amount); 58067 } 58068 } 58069 58070 function _checkIfPaymentActuallyProcessed(smid, amount, boltResponse) { 58071 if (smid == UserPortal.Price.Payment.getSMID()) { 58072 var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml()); 58073 var multiTicketXml = ''; 58074 58075 if (!UTIL.isEmptyObject(UserPortal.Price.multiTicketXml)) { 58076 multiTicketXml = UTIL.htmlEncode(UserPortal.Price.MultiTicket.saveTickets()); 58077 } 58078 58079 var jd = { "discount_xml": dxml, "multi_ticket_xml": multiTicketXml }; 58080 } else { 58081 var jd = {}; 58082 } 58083
58084 if (UTIL.isEmpty(smid)) { 58085 return; 58086 } 58087 58088 setTimeout(function() { //Add ~2 second wait to orphan check process 58089 SA.POS.CCBolt.checkIfPaymentActuallyProcessed2(smid, amount, boltResponse, jd); 58090 }, 1900); 58091 } 58092 _bolt.checkIfPaymentActuallyProcessed2 = function(smid, amount, boltResponse, jd) { 58093 //$('#appt-price-swipe-ready #enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber()); 58094 var uri = GLO.Link.WebsiteDomain + 'payment/LookupOrphanTransaction?smid=' + smid + '&price=' + amount; 58095 58096 if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 0) > 9) { 58097 uri += '&mid=' + GLO.Uri.url('mid'); 58098 } 58099 58100 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd }) 58101 .success(function(data, textStatus, jqXHR) { 58102 window.onbeforeunload = null; 58103 var jd = $(data); 58104 58105 if (jd.attr('id') == 'orphan-transaction-response') { 58106 var jwarn = jd.find('warning'); 58107 58108 if (jwarn.length && UserPortal.getAppt().length && UserPortal.Edit.scheduleMultiId == smid) { 58109 var jsonPostProcess = { "processing_header_vc": "Loading Payment", "processing_message_vc": "Updating Appointment" }; 58110 UserPortal.Edit.checkIfUpdated(smid, null, true, true, jsonPostProcess); 58111 } 58112 } 58113 58114 return data; 58115 }) 58116 .error(function(jqXHR, textStatus, errorThrown) { 58117 window.onbeforeunload = null; 58118 }); 58119 } 58120 58121 function _processConnectResponse(connectResponse, ccMID, serialNo) { 58122 console.log(connectResponse); 58123 58124 if (connectResponse.errorMessage) { 58125 var err = new Error(connectResponse.errorMessage); 58126 err.isConnectError = true; 58127 throw err; 58128 } 58129 58130 return _bolt.ping(ccMID, serialNo); 58131 } 58132 function _processPingResponseForPrint(pingResponse, ccMID, serialNo, multiScheduleId) { 58133 console.log(pingResponse); 58134 58135 if (UTIL.safeParseJson(pingResponse).errorMessage) { 58136 throw new Error(`${UTIL.safeParseJson(pingResponse).errorMessage}`); 58137 } 58138 58139 if (UTIL.safeParseJson(pingResponse).connected == true) { 58140 58141 return _bolt.printReceiptOnBolt(ccMID, serialNo, multiScheduleId); 58142 58143 } else { 58144 throw new Error(`Terminal not connected. Please make sure terminal is connected.`); 58145 } 58146 } 58147 58148 function _processPrintResponse(printResponse, ccMID, serialNo, multiScheduleId) { 58149 // console.log(printResponse); 58150 var json = UTIL.safeParseJson(printResponse); 58151 58152 if (Object.keys(json).length == 0) { 58153 return _bolt.disconnect(ccMID,serialNo); 58154 } 58155 58156 58157 if (json.errorMessage) { 58158 throw new Error(`${UTIL.safeParseJson(printResponse).errorMessage}`); 58159 } 58160 58161 if (json.hasOwnProperty('receiptData')) { //receipt print was successful 58162 return _bolt.disconnect(ccMID,serialNo); 58163 } else { 58164 throw new Error(`Receipt could not be printed. Please make sure terminal is available.`); 58165 } 58166 } 58167 58168 function _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,amount, tipEnabled, isGotoConfirm, ccArr,useListPrice,servicesTotalPrice) { 58169 // console.log(pingResponse); 58170 58171 if (UTIL.safeParseJson(pingResponse).errorMessage) { 58172 throw new Error(`${UTIL.safeParseJson(pingResponse).errorMessage}`); 58173 } 58174 58175 if (UTIL.safeParseJson(pingResponse).connected == true) { 58176 let confirmAmount = UTIL.displayMoney(amount, true); //(Math.round(amount * 100) / 100).toFixed(2); 58177 let originalAmount = UTIL.displayMoney(baseAmount, true); 58178 let servicesTotal = UTIL.displayMoney(servicesTotalPrice, true); 58179 58180 if (isGotoConfirm) { 58181 return _bolt.readConfirmation(ccMID, serialNo, multiScheduleId, confirmAmount); 58182 } else if (tipEnabled) { 58183 if (useListPrice) { 58184 if (UTIL.coalesceMoney(servicesTotal) > 0) { //&& ccArr && ccArr.length == 1 58185 return _bolt.tip(ccMID, serialNo, multiScheduleId, servicesTotal, confirmAmount); 58186 } 58187 } else if (UTIL.coalesceMoney(confirmAmount) > 0) { 58188 return _bolt.tip(ccMID, serialNo, multiScheduleId, confirmAmount, confirmAmount); 58189 } 58190 } 58191 58192 var totalAmount = Math.round(amount * 100); 58193 58194 if (ccArr && ccArr.length > 1) { 58195 confirmAmount = _getMultiMerchantFirstPaymentAmount(ccArr, ccMID); 58196 } else { 58197 confirmAmount = totalAmount; 58198 } 58199 58200 return _bolt.authCard(ccMID, overrideMID, serialNo, multiScheduleId, confirmAmount, totalAmount); 58201 } else { 58202 throw new Error(`Terminal not connected. Please make sure terminal is connected.`); 58203 } 58204 } 58205 function _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, amount, tipEnabled, ccArr, useListPrice, servicesTotalPrice) { 58206 console.log(readConfirmationResponse); 58207 58208 if (UTIL.safeParseJson(readConfirmationResponse).errorMessage) { 58209 throw new Error(`${UTIL.safeParseJson(readConfirmationResponse).errorMessage}`); 58210 } 58211 58212 if (UTIL.safeParseJson(readConfirmationResponse).confirmed == true) { 58213 let confirmAmount = UTIL.displayMoney(amount, true); //(Math.round(amount * 100) / 100).toFixed(2); 58214 let originalAmount = UTIL.displayMoney(baseAmount, true); 58215 let servicesTotal = UTIL.displayMoney(servicesTotalPrice, true); 58216 58217 //record client confirmation in appt update log 58218 SA.Profile.Payment.LogConfirmationToApptUpdateLog(multiScheduleId); 58219 58220 if (tipEnabled) { 58221 if (useListPrice) { // && ccArr && ccArr.length == 1 58222 if (UTIL.coalesceMoney(servicesTotal) > 0) { 58223 return _bolt.tip(ccMID, serialNo, multiScheduleId, servicesTotal, confirmAmount); 58224 } 58225 } else if (UTIL.coalesceMoney(confirmAmount) > 0) { 58226 return _bolt.tip(ccMID, serialNo, multiScheduleId, confirmAmount, confirmAmount); 58227 } 58228 } 58229 58230 var totalAmount = Math.round(amount * 100); 58231 58232 if (ccArr && ccArr.length > 1) { 58233 confirmAmount = _getMultiMerchantFirstPaymentAmount(ccArr, ccMID); 58234 } else { 58235 confirmAmount = totalAmount; 58236 } 58237 58238 return _bolt.authCard(ccMID, overrideMID, serialNo, multiScheduleId, confirmAmount, totalAmount); 58239 } else { 58240 throw new Error('Customer did not confirm question or message. Please check with customer.'); 58241 } 58242 } 58243 58244 function _getMultiMerchantFirstPaymentAmount(ccArr, ccMID) { 58245 var chargeMerchant = ccArr.filter(function(mc) { 58246 return mc.merchantid === ccMID; 58247 }); 58248 58249 if (UTIL.isEmptyObject(chargeMerchant) || chargeMerchant.length === 0) { 58250 chargeMerchant = ccArr; 58251 } 58252 58253 return UTIL.coalesceInt(UTIL.coalesceInt(chargeMerchant[0].amount * 100, 0) + UTIL.coalesceInt(chargeMerchant[0].tip * 100, 0)); 58254 } 58255 function _processConfirmResponse(confirmationResponse, ccMID, serialNo, multiScheduleId, amount) { 58256 console.log(confirmationResponse); 58257 58258 if (UTIL.safeParseJson(confirmationResponse).errorMessage) { 58259 throw new Error(`${UTIL.safeParseJson(confirmationResponse).errorMessage}`); 58260 } 58261 58262 if (UTIL.safeParseJson(confirmationResponse).confirmed == true){ 58263 return _bolt.tip(ccMID,serialNo,multiScheduleId,amount); 58264 } else { 58265 var warning = new Error('<div style="pop-error-card-connect"><p>Amount was not confirmed</p><p>Please check with client</p></div>'); 58266 warning.isWarning = true; 58267 throw warning; 58268 } 58269 } 58270 function _processTipResponse(tipResponse, ccMID, overrideMID,serialNo, multiScheduleId, amount, ccArr, servicesTotalPrice) { 58271 console.log(tipResponse); 58272 58273 if (UTIL.isEmpty(tipResponse)) { 58274 GLO.Log.insert(tipResponse, 'bolt.ProcessTipResponse', multiScheduleId, 'warning'); 58275 throw new Error('Card Reader Timeout'); 58276 } 58277 58278 var jsonTipResponse = UTIL.safeParseJson(tipResponse); 58279 58280 if (jsonTipResponse.errorMessage) { 58281 throw new Error(`${ jsonTipResponse.errorMessage}`); 58282 } else if (jsonTipResponse.respstat == 'A' && jsonTipResponse.token) { //= tipResponse is actually authResponse 58283 return tipResponse; 58284 } 58285 58286 if (UTIL.parseBool(GLO.Data.provider.useListPriceForTip)) { 58287 var total = UTIL.coalesceMoney(servicesTotalPrice); 58288 } else { 58289 var total = UTIL.coalesceMoney(jsonTipResponse.total); 58290 } 58291 58292 var totalTip = UTIL.coalesceMoney(jsonTipResponse.tip); 58293 58294 if (totalTip > 0 & ccArr.length > 1) { //divide tip equally among merchants 58295 for (const ccmerchant of ccArr) { 58296 //var merchantTipPercent = parseFloat(((ccmerchant.amount / total) * 100).toFixed(2)); 58297 //ccmerchant.tip = parseFloat((merchantTipPercent * (totalTip / 100)).toFixed(2)); 58298 _setTip(ccmerchant, total, totalTip); 58299 } 58300 58301 _verifyTip(ccArr, totalTip); 58302 } else { 58303 ccArr[0].tip = UTIL.coalesceMoney(totalTip/100); 58304 } 58305 58306 //multi-ticket scenario VERIFY 58307 if (ccArr.length == 1) { 58308 if (ccArr[0].amount !== amount) { 58309 ccArr[0].amount = amount; 58310 } 58311 } 58312 58313 var chargeMerchant = null; 58314 58315 if (overrideMID != '') { 58316 chargeMerchant = ccArr.filter(function(mc) { return mc.merchantid === overrideMID;}); 58317 } else { 58318 chargeMerchant = ccArr.filter(function(mc) { return mc.merchantid === ccMID;}); 58319 } 58320 58321 //var chargeTotal = (UTIL.coalesceInt(chargeMerchant[0].amount * 100, 0) + UTIL.coalesceInt(chargeMerchant[0].tip * 100, 0)).toString(); 58322 //var chargeTotal = UTIL.coalesceInt((UTIL.coalesceMoney(chargeMerchant[0].amount, 0) + UTIL.coalesceMoney(chargeMerchant[0].tip, 0)) * 100).toString(); //problem: this can cause a rounding issue where '401.99999999999994' is rounded to '401' 58323 var chargeTotal = Math.round((UTIL.coalesceMoney(chargeMerchant[0].amount, 0) + UTIL.coalesceMoney(chargeMerchant[0].tip, 0)) * 100); 58324 58325 return _bolt.authCard(ccMID, overrideMID,serialNo, multiScheduleId, chargeTotal, total); 58326 } 58327 58328 function _setTip(merchant, total, totalTip) { //= splits tip amount by service price (ignores products + outcall fee) 58329 var payto = merchant.pay_to; 58330 var amount = merchant.amount; 58331 58332 var jedit = UserPortal.getEditAppt(); 58333 var tr = jedit.find('.editServiceRow'); 58334 var serviceTotal = 0, merchantService = 0;
58335 var split = GLO.Data.provider.split_tip_cd; //UserPortal.Price.QuickTip.getSplit(); 58336 58337 for (var i=0; i < tr.length; i++) { 58338 var jstaff = tr.eq(i).find('.staffDD option:selected'); 58339 var mt = UTIL.coalesceInt(jstaff.attr('merchant_type_cd'), 99); 58340 var sid = jstaff.attr('value'); 58341 58342 //if (split == 110 || split == 100) { at this time: split tip = 'evenly' is NOT supported for multi-merchant transactions (when tipping on Clover device) 58343 if (split == 10) { 58344 var service = UTIL.coalesceMoney(UserPortal.Booking.service[i].price_mn); 58345 } else { 58346 var service = UTIL.coalesceMoney(UserPortal.Booking.service[i].price_mn) + UTIL.coalesceMoney(UserPortal.Booking.service[i].add_on_fee_mn) 58347 + -UTIL.coalesceMoney(UserPortal.Booking.service[i].new_discount_mn, UserPortal.Booking.service[i].discount_mn) 58348 + UTIL.coalesceMoney(UserPortal.Booking.service[i].tax_mn); 58349 } 58350 58351 serviceTotal += service; 58352 58353 if ((payto == 'h' && mt < 50) || (payto == sid)) { 58354 merchantService += service; 58355 } 58356 } 58357 58358 //var total = UTIL.coalesceMoney((total - totalTip)/100 - UserPortal.getOutcallFee()); 58359 var pct = UTIL.coalesceMoney(merchantService/serviceTotal); //round percent to 58360 58361 if (pct > 1 ) { 58362 pct = 1; 58363 } 58364 58365 merchant.tip = UTIL.coalesceMoney(pct * totalTip/100); 58366 } 58367 58368 function _verifyTip(ccArr, totalTip) { //= if tip has a rounding error (should not happen often, but could be off by +/- .01), then adjust first tip amount. 58369 totalTip = UTIL.coalesceMoney(totalTip/100); 58370 58371 for (const ccmerchant of ccArr) { 58372 totalTip = UTIL.coalesceMoney(totalTip - ccmerchant.tip); 58373 } 58374 58375 if (totalTip !== 0) { 58376 if (Math.abs(totalTip) > .01) { 58377 GLO.Log.insertFromAppt('Card Connect Multi-Merchant Verify Tip Adjustment: ' + totalTip); 58378 } 58379 58380 ccArr[0].tip = UTIL.coalesceMoney(ccArr[0].tip + totalTip); 58381 } 58382 } 58383 58384 function _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr, isTipFromDevice) { 58385 console.log(authResponse); 58386 var ojAuthResponse = UTIL.safeParseJson(authResponse); 58387 58388 if (ojAuthResponse.errorMessage) { 58389 if (ojAuthResponse.errorCode) { // == 8 58390 //errorMessage == 'Operation Cancelled' -> staff closes appointment (or client removes card) just before transaction finishes processing 58391 //errorMessage == 'Command Cancelled' -> client does not remove card after payment in timely manner 58392 58393 if (ojAuthResponse.authResponse && ojAuthResponse.errorMessage !== 'Authorization Voided') { 58394 //there was an error during the payment response but auth may have succeeded 58395 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 58396 jPopSwipe.find('#enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber()); 58397 jPopSwipe.find('#store-card-container').remove(); 58398 58399 var innerAuthResponse = JSON.stringify(ojAuthResponse.authResponse); 58400 ccMID = UTIL.coalesceString(overrideMID, ccMID); 58401 //innerAuthResponse.orderId = multiScheduleId; //set the orderId so it maps to the ticket 58402 return _bolt.postAuthResponseToBoltApi(innerAuthResponse, ccMID, serialNo, isSale, tipAmount, cid, multiScheduleId, scid, ccArr, isTipFromDevice); 58403 58404 } else if (ojAuthResponse.authResponse && ojAuthResponse.errorMessage === 'Authorization Voided') { 58405 //authorizaton was voided for some reason, notify staff 58406 var htm = '<div id="pop-error-bolt-auth=response"><p>Error Code ' + ojAuthResponse.errorCode + '</p><p>' + ojAuthResponse.errorMessage + '</p><p>Please retry the payment.</p></div>'; 58407 GLO.Popup.Warning.open(htm, 'Payment Processing Error'); 58408 58409 } else { 58410 //check for orphan xsaction 58411 _checkIfPaymentActuallyProcessed(multiScheduleId, amount, ojAuthResponse); 58412 } 58413 } else if (ojAuthResponse.errorMessage === 'Command Cancelled') { 58414 _checkIfPaymentActuallyProcessed(multiScheduleId, amount, ojAuthResponse); 58415 //} else if (jd.respstat != 'A' || jd.amount == 0) { //= handles expired card (and maybe other errors) 58416 // var htm = '<div id="pop-warn-bolt-auth"><p>Card Not Charged</p><p>' + jd.resptext + '</p></div>';
58417 // GLO.Popup.Warning.open(htm, 'Credit Card Response'); 58418 } else { 58419 var htm = '<div id="pop-error-bolt-auth=response"><p>Error Code ' + ojAuthResponse.errorCode + '</p><p>' + ojAuthResponse.errorMessage + '</p></div>'; 58420 GLO.Popup.Warning.open(htm, 'Payment Processing Error'); 58421 } 58422 58423 throw new Error(`${ojAuthResponse.errorMessage}`); 58424 } else if (ojAuthResponse.respstat != 'A') { 58425 throw new Error(ojAuthResponse.resptext); 58426 } 58427 58428 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 58429 jPopSwipe.find('#enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber()); 58430 jPopSwipe.find('#store-card-container').remove(); 58431 58432 ccMID = UTIL.coalesceString(overrideMID, ccMID); 58433 return _bolt.postAuthResponseToBoltApi(authResponse, ccMID, serialNo, isSale, tipAmount, cid, multiScheduleId, scid, ccArr, isTipFromDevice); 58434 58435 } 58436 58437 function _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr,isEnabledReceiptConfirmation) { 58438 console.log(serverResponse); 58439 var ojServerResponse = UTIL.safeParseJson(serverResponse); 58440 var xmlDoc = $.parseXML(ojServerResponse.receipthtml); 58441 58442 if (ojServerResponse.receipthtml === '') { 58443 var msg = UTIL.coalesceString(ojServerResponse.warning, 'Payment Response Invalid'); 58444 58445 if (!UTIL.isEmpty(ojServerResponse.warning)) { 58446 var h1 = 'Unable to Process Tip'; 58447 58448 setTimeout(function() { 58449 UserPortal.reloadTicket(multiScheduleId); 58450 }, 2500); 58451 } else { 58452 var h1 = 'Payment Failed'; 58453 } 58454 58455 _displayEmvCommunicateError(msg, h1, true); 58456 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 58457 58458 if (jPopSwipe.length) { 58459 jPopSwipe.find('#imgThrobberContainer').remove(); 58460 jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide'); 58461 } 58462 } else if (ojServerResponse.multimerchant == 'true') { //= IF MULTIMERCHANT IS TRUE, THEN SEND THE SECOND/ADDITIONAL TRANSACTIONS TO SERVER 58463 if (UserPortal.Price.Payment.saveCreditCard_complete(ojServerResponse.receipthtml, true, true, 1)) { 58464 ojServerResponse.receipthtml = ''; 58465 var serverResponseJsonNoHtml = JSON.stringify(ojServerResponse); 58466 var jProgressBar = $('#appt-price-swipe-ready #enter-card-manually'); 58467 58468 var remainingAmount = _remainingAmountAfterFirstTransaction(ccArr); 58469 var msg = '<p>First transaction completed successfuly</p><p>Processing ' + UTIL.pluralLabel(ccArr.length - 1, ' other transaction') + ' for ' + remainingAmount + '</p>'; 58470 var boltMessage = 'First Transaction Successful\n\nProcessing ' + UTIL.pluralLabel(ccArr.length - 1, ' More Transaction') + ' for ' + remainingAmount + '...'; 58471 58472 UI.startProgressBar(jProgressBar, 36, msg); //wait for gateway timeout seconds 58473 58474 setTimeout(function () { 58475 _bolt.clearDisplay(ccMID,serialNo); 58476 var midString = UTIL.coalesceString(overrideMID, ccMID); 58477 _processAdditionalTransactions(serverResponseJsonNoHtml, midString, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr); 58478 }, ojServerResponse.gatewaytimeoutms); 58479 58480 return _bolt.display(ccMID,serialNo, boltMessage); 58481 /* } else { 58482 /* 58483 _displayEmvCommunicateError($xml.find("ul").attr('error_cd') , 'Payment Failed', true); 58484 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 58485 58486 if (jPopSwipe.length) { 58487 jPopSwipe.find('#imgThrobberContainer').remove(); 58488 jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide'); 58489 } 58490 */ 58491 } 58492 } else { 58493 UserPortal.Price.Payment.saveCreditCard_complete(ojServerResponse.receipthtml, true, true); 58494 } 58495 58496 var usePrinterCookie = $.cookies.get('emv-print'); 58497 //ask for receipt if enabled and clover receipt is set to asneeded 58498 if ((usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) && isEnabledReceiptConfirmation) { 58499 return _bolt.receiptConfirmation(ccMID,serialNo,multiScheduleId); 58500 } 58501 else { 58502 return _bolt.disconnect(ccMID, serialNo); 58503 } 58504 } 58505
58506 function _remainingAmountAfterFirstTransaction(ccArr) { 58507 var total = 0; 58508 58509 for (var i=1; i < ccArr.length; i++) { 58510 total += UTIL.coalesceMoney(ccArr[1].amount) + UTIL.coalesceMoney(ccArr[1].tip); 58511 } 58512 58513 return UTIL.displayMoney(total); 58514 } 58515 58516 function _processAdditionalTransactions(serverResponse, ccMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr) { 58517 var ojServerResponse = UTIL.safeParseJson(serverResponse); 58518 58519 _bolt.postAddtionalPaymentsToBoltApi(serverResponse,ccMID,serialNo, isSale, tipAmount, cid, multiScheduleId, scid,ccArr); 58520 58521 } 58522 function _processDisconnectResponse(disconnectResponse) { 58523 console.log(disconnectResponse); 58524 58525 if (Object.keys(UTIL.safeParseJson(disconnectResponse)).length == 0) { 58526 return; 58527 } 58528 58529 if (UTIL.safeParseJson(disconnectResponse).errorMessage) { 58530 throw new Error(`${UTIL.safeParseJson(disconnectResponse).errorMessage}`); 58531 } 58532 58533 if (UTIL.safeParseJson(disconnectResponse).disconnected == true){ 58534 console.log('disconnected'); 58535 } else { 58536 throw new Error(`{"errorMessage":"Disconnect failed!"}`); 58537 } 58538 } 58539 function _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation) { 58540 console.log(disconnectOrReceiptResponse); 58541 //response can be receipt, disconnect or display 58542 58543 if (disconnectOrReceiptResponse == '') { 58544 return ''; 58545 } 58546 58547 var usePrinterCookie = $.cookies.get('emv-print'); 58548 //Print Receipt response 58549 if ((usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) && isEnabledReceiptConfirmation) { 58550 var receiptConfirmationResponse = disconnectOrReceiptResponse; 58551 58552 if (UTIL.safeParseJson(receiptConfirmationResponse).errorMessage) { 58553 throw new Error(`${UTIL.safeParseJson(receiptConfirmationResponse).errorMessage}`); 58554 } 58555 58556 if (UTIL.safeParseJson(receiptConfirmationResponse).confirmed == true) { 58557 return _bolt.printReceiptOnBolt(ccMID, serialNo, multiScheduleId); 58558 } 58559 58560 // return _bolt.disconnect(ccMID,serialNo); 58561 } 58562 else { 58563 //disconnect response 58564 if (UTIL.safeParseJson(disconnectOrReceiptResponse).errorMessage) { 58565 throw new Error(`${UTIL.safeParseJson(disconnectOrReceiptResponse).errorMessage}`); 58566 } 58567 58568 if (UTIL.safeParseJson(disconnectOrReceiptResponse).disconnected == true){ 58569 console.log('disconnected'); 58570 return; 58571 } else { 58572 throw new Error(`{"errorMessage":"Disconnect failed!"}`); 58573 } 58574 } 58575 } 58576 function _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId) { 58577 console.log(printOrDisconnectResponse); 58578 58579 if (printOrDisconnectResponse == '') { 58580 return; 58581 } 58582 58583 //Print Receipt response 58584 if (Object.keys(UTIL.safeParseJson(printOrDisconnectResponse)).length == 0 || typeof UTIL.safeParseJson(printOrDisconnectResponse).receiptData !== "undefined") { 58585 return _bolt.disconnect(ccMID,serialNo); 58586 } 58587 58588 if (UTIL.safeParseJson(printOrDisconnectResponse).errorMessage) { 58589 throw new Error(`${UTIL.safeParseJson(printOrDisconnectResponse).errorMessage}`); 58590 } 58591 58592 //disconnect response 58593 if (typeof UTIL.safeParseJson(printOrDisconnectResponse).disconnected !== "undefined") { 58594 if (UTIL.safeParseJson(printOrDisconnectResponse).disconnected == true){ 58595 console.log('disconnected'); 58596 } else { 58597 throw new Error(`{"errorMessage":"Disconnect failed!"}`); 58598 } 58599 } 58600 58601 return _bolt.disconnect(ccMID,serialNo); 58602 58603 } 58604 function _processErrorResponse(e, ccMID, serialNo, isPrint) { 58605 console.log(e); 58606 GLO.UI.Form.resetProcessing(); 58607 58608 var isBoltConnectWarning = $('#pop-warn-bolt-connect').closest('.glopop').length; 58609 var isInMerchantMode = (e && e.message && e.message.indexOf('in merchant mode') !== -1); 58610 var isAlreadyInUse = (e && e.message && e.message.indexOf('already in use') !== -1); 58611 58612 if (isBoltConnectWarning) { //= if bolt connect error, allow entering card manually 58613 var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop'); 58614 jPopSwipe.find('#imgThrobber, .blue-throbber').remove(); 58615 58616 GLO.Log.insertJSErrorSimple(e, 'Bolt Connect Fail', 'warning', ccMID + '/' + serialNo); 58617 return; 58618 } else if (isInMerchantMode) { 58619 _isConnected = false; 58620 } else if (isAlreadyInUse) { 58621 _bolt.resetTerminal(ccMID, serialNo); 58622 _isConnected = false; 58623 } else { 58624 //if (UTIL.parseBool(e.isConnectError) && !isPrint) { _isConnected = true; } 58625 GLO.Log.insertJSErrorSimple(e, 'Bolt Process Error Response', 'high', ccMID + '/' + serialNo); 58626 //UserPortal.Price.Payment.closeSwipePopup(true); 58627 } 58628 58629 if (_isConnected) { 58630 _isConnected = false; 58631 e.isConnectError = true; 58632 GLO.Log.insertJSErrorSimple(e, 'Bolt Process Error Response'); 58633 58634 _processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode, true); 58635 return _bolt.disconnect(ccMID,serialNo); 58636 } 58637 58638 _processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode); 58639 } 58640 58641 function _processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode, isConnectError) { 58642 if (isAlreadyInUse || isInMerchantMode || (UTIL.parseBool(e.isConnectError) && !isPrint && e.message !== 'Command Cancelled' && e.message !== 'Card Reader Timeout')) { //= if cannot connect to clover reader then need to allow staff to enter manually 58643 UserPortal.Price.Payment.openCreditCard(false, isConnectError); 58644 } 58645 58646 if (isInMerchantMode) { 58647 GLO.Log.insertJSErrorSimple(e, 'Bolt In Merchant Mode', 'warning', ccMID + '/' + serialNo); 58648 var msg2 = 'Please change Card Reader to <b style="padding: 4px 8px; color: black; background-color: rgb(0,255,0);">Customer Mode</b>'; 58649 _displayBoltWarningMessge(e, 'Device in Merchant Mode', 'pop-bolt-warn-merchant-mode', msg2); 58650 } else if (isAlreadyInUse) { 58651 _displayBoltWarningMessge(e, 'Device Already in Use by another Session', 'pop-bolt-warn-in-use'); 58652 GLO.Log.insertJSErrorSimple(e, 'Bolt Is Already Connected to another Session', 'warning', ccMID + '/' + serialNo); 58653 } else if (e.message) { 58654 if (e.message === 'Command Cancelled' || e.message === 'Card Reader Timeout') { 58655 _isConnected = false; 58656 } else { 58657 var msg2 = '', header = 'Payment failed'; 58658 var isNotConnected = (e && e.message.indexOf('Terminal not connected') !== -1); //thrown by SA in pingResponse when ping returns not connected, toDo: why is Connect succeeding ?? 58659 var isPrintReceiptError = (e && e.message.indexOf('PrintReceiptResponse') !== -1); 58660 58661 if (isNotConnected) { 58662 msg2 = 'Please verify another session not connected to device'; 58663 } 58664 58665 if (e.isConnectError) { 58666 header = 'Unable to Connect to Clover'; 58667 } 58668 58669 if (isPrintReceiptError) { 58670 msg2 = 'Please check printer paper is present and terminal is connected to a power supply and try again.' 58671 } 58672 58673 if (e.isConnectError && e.message.indexOf('No request queue registered for') !== -1) { 58674 var msg = '<p>Unable to Connect to Clover ' + serialNo + '</p><p>Please check Clover screen to verify device is in <b class="narrow-text">Customer Mode</b></p>'; 58675 _displayBoltWarningMessge(e, header, 'pop-bolt-warn', msg); 58676 } else if (e.isWarning) { 58677 _displayBoltWarningMessge(e, header, 'pop-bolt-warn', msg2); 58678 } else { 58679 _displayBoltWarningMessge(e, header, 'pop-bolt-error', msg2); 58680 } 58681 } 58682 58683 GLO.Log.insertSimple('Bolt Process Error Response', e.message, 'high'); 58684 } else if ($('.pop-error').closest('.glopop').length === 0) { 58685 GLO.Popup.Error.open('<p>Unable to process payment</p><p>Please try again</p>', 'Credit Card Reader'); 58686 GLO.Log.insertSimple('Unable to Process Payment', ccMID + ' | ' + serialNo, 'high'); 58687 } 58688 } 58689 58690 function _displayBoltWarningMessge(e, h1, popid, msg2) { 58691 if ($('#hello-bar-warn-bolt-connect').closest('.glopop').length) { return; } 58692 58693 var msgTry = '', msg = 'Unable to Communicate with Clover Connect Device'; 58694 popid = UTIL.coalesceString(popid, 'pop-bolt-warning'); 58695 58696 if (e && e.message) { 58697 msg = e.message; 58698 58699 try { 58700 msgTry = JSON.parse('{ '+ e.message + '}').errorMessage; 58701 } catch (e) { } 58702 } 58703 58704 h1 = UTIL.coalesceString(h1, 'Payment Device Issue'); 58705 msg = UTIL.coalesceString(msgTry, msg); 58706 msg2 = UTIL.coalesceString(msg2, 'Please Try Again'); 58707 58708 var htm = '<div id="' + popid + '"><p>' + msg + '</p><p style="text-align: center;">' + msg2 + '</p></div>'; 58709 58710 if (popid.indexOf('error') !== -1) { 58711 var ojpop = GLO.Popup.Error.open(htm, h1); 58712 } else { 58713 var ojpop = GLO.Popup.Warning.open(htm, h1); 58714 } 58715 58716 ojpop.getPopup().addClass('pop-fail-cc-pay-bolt'); 58717 } 58718 58719 _bolt.resetTerminal = function(mid, serialNumber) { 58720 if (UTIL.isEmpty(serialNumber)) { 58721 serialNumber = $.cookies.get('boltdevice'); 58722 } 58723 58724 if (UTIL.isEmpty(mid)) { 58725 mid = GLO.Data.provider.merchants[0].idString; 58726 } 58727 58728 SA.POS.CCBolt.clearDisplay(mid, serialNumber); 58729 58730 setTimeout(function () { 58731 SA.POS.CCBolt.disconnect(mid, serialNumber); 58732 }, 2000); 58733 58734 58735 } 58736 58737 _bolt.startTakePayment = function(ccArr, cid, smid, scid, baseAmount, amount, tipAmount, totalPrice, isForceDisableTip, servicesTotalPrice) { 58738 let serialNo = SA.POS.CCBolt.getDeviceSerialNo(); 58739 let ticketHasHouseAccount = true; 58740 ccArr = _convertMerchantArrayForBolt(ccArr); 58741 var isEnabledDeviceGetConfirmation = false; 58742 var isEnabledReceiptConfirmation = false; 58743 58744 var houseAccount = ccArr.filter(function(item) { //get the house account mid if on ticket else get the first chair mid on ticket 58745 return item.pay_to === 'h'; 58746 }); 58747 58748 if (houseAccount.length > 0) { 58749 //ticket has house account 58750 } else { 58751 ticketHasHouseAccount = false;
58752 houseAccount = GLO.Data.provider.merchants.filter(function(item) { return item.type === 10;}) 58753 } 58754 58755 var cloverMerchantId = (ticketHasHouseAccount) ? houseAccount[0].merchantid : ccArr[0].merchantid; 58756 58757 //get device confirmation settings 58758 var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetConfirmationSettings/' + cloverMerchantId; 58759 58760 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 58761 .success(function(data, textStatus, jqXHR) { 58762 isEnabledDeviceGetConfirmation = data.GetConfirmationEnabled; 58763 isEnabledReceiptConfirmation = data.ReceiptConfirmationEnabled; 58764 58765 //get device tip settings 58766 var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetTipPercents/' + cloverMerchantId; 58767 58768 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 58769 .success(function(data, textStatus, jqXHR) { 58770 var isEnableTip = _isEnableTip(data.TipEnabled, ccArr, tipAmount, totalPrice, isForceDisableTip); 58771 var useListPrice = data.UseListPrice; 58772 if (isEnableTip && tipAmount > 0) { 58773 tipAmount = 0; 58774 } 58775 58776 SA.POS.CCBolt.TakePayment(cloverMerchantId,ccArr, serialNo, true, cid, smid, scid, baseAmount ,amount, tipAmount, isEnableTip, isEnabledDeviceGetConfirmation,isEnabledReceiptConfirmation,useListPrice, servicesTotalPrice); 58777 }) 58778 .error(function(jqXHR, textStatus, errorThrown) { 58779 new GLO.Popup.Error('Unable to get Tip Settings for device'); 58780 }); 58781 }) 58782 .error(function(jqXHR, textStatus, errorThrown) { 58783 new GLO.Popup.Error('Unable to get Confirmation Settings for device'); 58784 }); 58785 58786 58787 } 58788 58789 function _isEnableTip(isEnableTip, ccArr, tipAmount, totalPrice, isForceDisableTip) { 58790 if (!isEnableTip) { 58791 return false; 58792 } 58793 58794 if (UTIL.parseBool(isForceDisableTip)) { 58795 return false; 58796 } else if (isEnableTip && tipAmount > 0) { 58797 if (ccArr.length > 1) { 58798 return false; 58799 } 58800 58801 var payto = ccArr[0].pay_to; 58802 var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 0); 58803 58804 var jPricePop = $('#appt-price-popup').closest('.glopop'); 58805 var trpay = jPricePop.find('tr.appt-price-payment-row'); 58806 58807 for (var i=0; i < trpay.length; i++) { 58808 var trPayTo = trpay.eq(i).attr('payment_to_staff_id'); 58809 58810 if (!trpay.eq(i).hasClass('swipe')) { 58811 if (mt < 10 || (mt < 20 && payto == 'h') || (mt < 50 && payto == 'p') || (mt == 50 && payto == trPayTo) ) { 58812 tipAmount = UTIL.coalesceMoney(tipAmount - UTIL.coalesceMoney(trpay.eq(i).attr('original_tip_mn'), trpay.eq(i).attr('tip_mn'))); 58813 } 58814 } 58815 } 58816 58817 if (tipAmount > .01) { 58818 return false; 58819 } else { 58820 ccArr[0].amount = UTIL.coalesceMoney(ccArr[0].amount + ccArr[0].tip); 58821 ccArr[0].tip = tipAmount = 0; 58822 } 58823 } 58824 58825 return isEnableTip; 58826 } 58827 58828 function _convertMerchantArrayForBolt(ccArr) { 58829 if (ccArr && ccArr.length) { 58830 for (var i=ccArr.length-1; i >= 0; i--) { 58831 if (UTIL.coalesceMoney(ccArr[i].amount) === 0) { 58832 ccArr.splice(i, 1); 58833 } else { 58834 ccArr[i].amount = UTIL.coalesceMoney(UTIL.coalesceMoney(ccArr[i].amount) - UTIL.coalesceMoney(ccArr[i].tip)); 58835 } 58836 } 58837 } 58838 58839 return ccArr; 58840 } 58841 58842 _bolt.TakePayment = async function(ccMID,ccArr,serialNo,isSale,cid,multiScheduleId,scid,baseAmount,totalAmount,totalTipAmount,tipOnDeviceEnabled, isEnabledDeviceGetConfirmation,isEnabledReceiptConfirmation,useListPrice,servicesTotalPrice) { 58843 _isConnected = false; 58844 _currentPaymentMerchantIdString = ccMID; 58845 58846 let chargeAmount = 0; 58847 let chargeTipAmount = 0; 58848 let ticketHasHouseAccount = true; 58849 let overrideMID = ''; //auth override 58850 var isTipFromDevice = false; 58851 58852 //get the house account mid if on ticket else get the first chair mid on ticket 58853 var houseAccount = ccArr.filter(function(item) { return item.pay_to === 'h';}) 58854 if (houseAccount.length > 0 ) { 58855 //ticket has house account 58856 //ccMID = house account MID 58857 } 58858 else 58859 { 58860 ticketHasHouseAccount = false; 58861 houseAccount = GLO.Data.provider.merchants.filter(function(item) { return item.type === 10;}) 58862 58863 if (houseAccount[0].co == 30) { 58864 overrideMID = ccMID; 58865 ccMID = houseAccount[0].idString; 58866 } 58867 } 58868 58869 if (ccArr.length == 1) { 58870 chargeAmount = totalAmount; 58871 chargeTipAmount = totalTipAmount; 58872 } 58873 else { 58874 chargeAmount = (ticketHasHouseAccount) ? houseAccount[0].amount : ccArr[0].amount; 58875 chargeTipAmount = (ticketHasHouseAccount) ? UTIL.coalesceMoney(houseAccount[0].tip) : UTIL.coalesceMoney(ccArr[0].tip); 58876 } 58877 58878 //Steps: 58879 //1. call connect endpoint and get session key 58880 //2. if session key returned, ping device 58881 //3. ask for confirmation if enabled 58882 //4. ask for tip if enabled 58883 //5. run auth 58884 //66. disconnect device and expire session keyS 58885 58886 if (!tipOnDeviceEnabled && !isEnabledDeviceGetConfirmation) { //tipping disabled on device 58887 _bolt.connect(ccMID,serialNo) 58888 .then((connectResponse) => { 58889 var json = _processConnectResponse(connectResponse, ccMID, serialNo); 58890 _isConnected = true; 58891 return json; 58892 }).then((pingResponse) => { 58893 var gotoConfirmPrompt = false; 58894 return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice); 58895 }).then((authResponse) => { 58896 return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, chargeTipAmount,ccArr); 58897 }).then((serverResponse) => { 58898 return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation); 58899 }).then((disconnectOrReceiptResponse) => { 58900 return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation); 58901 }).then((printOrDisconnectResponse) => { 58902 return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId); 58903 }).catch(e => { 58904 return _processErrorResponse(e, ccMID, serialNo); 58905 }); 58906 } else if (tipOnDeviceEnabled && !isEnabledDeviceGetConfirmation) { 58907 _bolt.connect(ccMID,serialNo) 58908 .then((connectResponse) => { 58909 var json = _processConnectResponse(connectResponse, ccMID, serialNo); 58910 _isConnected = true; 58911 return json; 58912 }).then((pingResponse) => { 58913 var gotoConfirmPrompt = false; 58914 return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice, servicesTotalPrice); 58915 }).then((tipResponse) => { 58916 var json = _processTipResponse(tipResponse, ccMID, overrideMID, serialNo, multiScheduleId, totalAmount, ccArr, servicesTotalPrice); 58917 totalTipAmount = UTIL.coalesceMoney(Math.round(UTIL.safeParseJson(tipResponse).tip) / 100); 58918 isTipFromDevice = (totalTipAmount > 0); 58919 return json; 58920 }).then((authResponse) => { 58921 return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr, isTipFromDevice); 58922 }).then((serverResponse) => { 58923 return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation); 58924 }).then((disconnectOrReceiptResponse) => { 58925 return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation); 58926 }).then((printOrDisconnectResponse) => { 58927 return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId); 58928 }).catch(e => { 58929 return _processErrorResponse(e, ccMID, serialNo); 58930 }); 58931 } else if (!tipOnDeviceEnabled && isEnabledDeviceGetConfirmation) { 58932 _bolt.connect(ccMID,serialNo) 58933 .then((connectResponse) => { 58934 var json = _processConnectResponse(connectResponse, ccMID, serialNo); 58935 _isConnected = true; 58936 return json; 58937 }).then((pingResponse) => { 58938 var gotoConfirmPrompt = true; 58939 return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice); 58940 }).then((readConfirmationResponse) => { 58941 return _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, ccArr, useListPrice, servicesTotalPrice); 58942 }).then((authResponse) => { 58943 return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, chargeTipAmount,ccArr); 58944 }).then((serverResponse) => { 58945 return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation); 58946 }).then((disconnectOrReceiptResponse) => { 58947 return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation); 58948 }).then((printOrDisconnectResponse) => { 58949 return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId); 58950 }).catch(e => { 58951 return _processErrorResponse(e, ccMID, serialNo); 58952 }); 58953 } else if (tipOnDeviceEnabled && isEnabledDeviceGetConfirmation) { 58954 _bolt.connect(ccMID,serialNo) 58955 .then((connectResponse) => { 58956 var json = _processConnectResponse(connectResponse, ccMID, serialNo); 58957 _isConnected = true; 58958 return json; 58959 }).then((pingResponse) => { 58960 var gotoConfirmPrompt = true; 58961 return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice); 58962 }).then((readConfirmationResponse) => { 58963 return _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, ccArr, useListPrice, servicesTotalPrice); 58964 }).then((tipResponse) => { 58965 var json = _processTipResponse(tipResponse, ccMID, overrideMID, serialNo, multiScheduleId, totalAmount, ccArr, servicesTotalPrice); 58966 totalTipAmount = UTIL.coalesceMoney(Math.round(UTIL.safeParseJson(tipResponse).tip) / 100); 58967 isTipFromDevice = (totalTipAmount > 0); 58968 return json; 58969 }).then((authResponse) => { 58970 return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr, isTipFromDevice); 58971 }).then((serverResponse) => { 58972 return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation); 58973 }).then((disconnectOrReceiptResponse) => { 58974 return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation); 58975 }).then((printOrDisconnectResponse) => { 58976 return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId); 58977 }).catch(e => { 58978 return _processErrorResponse(e, ccMID, serialNo); 58979 }); 58980 } else { 58981 //do nothing 58982 } 58983 } 58984 58985 58986 _bolt.PrintReceipt = async function(ccMID, serialNo, multiScheduleId, retryAttempt) { 58987 _isConnected = false; 58988 var isConnectInProgress = true; 58989 58990 //Steps: 58991 //1. call connect endpoint and get session key 58992 //2. if session key returned, ping device 58993 //3. run print receipt 58994 //4. disconnect device and expire session keyS 58995 58996 _bolt.connect(ccMID,serialNo) 58997 .then((connectResponse) => { 58998 var json = _processConnectResponse(connectResponse, ccMID, serialNo); 58999 _isConnected = true; 59000 isConnectInProgress = false; 59001 return json; 59002 }).then((pingResponse) => { 59003 return _processPingResponseForPrint(pingResponse, ccMID, serialNo, multiScheduleId); 59004 }).then((printResponse) => { 59005 return _processPrintResponse(printResponse, ccMID, serialNo, multiScheduleId); 59006 }).then((disconnectResponse) => { 59007 return _processDisconnectResponse(disconnectResponse); 59008 }).catch(e => { 59009 if (isConnectInProgress && UTIL.coalesceInt(retryAttempt, 0) === 0) { //= if client very quickly removes card after card processed clover mini often still in use. 59010 setTimeout(function() { 59011 SA.POS.CCBolt.PrintReceipt(ccMID, serialNo, multiScheduleId, 1); 59012 }, 2500); 59013 } else { 59014 return _processErrorResponse(e, ccMID, serialNo, true); 59015 } 59016 }); 59017 } 59018 59019 _bolt.cancel = function(serialNo) { 59020 var ccMID = GLO.Data.provider.merchants[0].idString; //UTIL.coalesceString(_currentPaymentMerchantIdString, GLO.Data.provider.merchants[0].idString); 59021
59022 if (!ccMID) { 59023 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 59024 return; 59025 } 59026 59027 if (UTIL.isEmpty(serialNo)) { 59028 GLO.Log.insertSimple('Bolt.Cancel with No Serial Number', 'Bolt.Cancel with Empty Serial Number', 'medium'); 59029 return; 59030 } 59031 59032 var uri = GLO.Link.WebsiteDomain + 'api/bolt/cancel/' + ccMID + '/' + serialNo; 59033 59034 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' }) 59035 .success(function(data, textStatus, jqXHR) { 59036 window.onbeforeunload = null; 59037 return data; 59038 }) 59039 .error(function(jqXHR, textStatus, errorThrown) { 59040 GLO.UI.Form.resetProcessing(); 59041 59042 if ($('.pop-error.glopop').length === 0) { 59043 GLO.Popup.Error.open('Unable to cancel cardconnect transaction', 'Credit Card Reader'); 59044 } 59045 }); 59046 59047 } 59048 59049 _bolt.getDeviceSerialNo = function() { 59050 var name = 'boltdevice' + "="; 59051 var decodedCookie = decodeURIComponent(document.cookie); 59052 var ca = decodedCookie.split(';'); 59053 for(var i = 0; i <ca.length; i++) { 59054 var c = ca[i]; 59055 while (c.charAt(0) == ' ') { 59056 c = c.substring(1); 59057 } 59058 if (c.indexOf(name) == 0) { 59059 return c.substring(name.length, c.length); 59060 } 59061 } 59062 return ""; 59063 } 59064 59065 _bolt.getReceipt = function(ccMID,serialNo,multiScheduleId,amount) { 59066 59067 if (!ccMID) { 59068 new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.'); 59069 return; 59070 } 59071 59072 var uri = GLO.Link.WebsiteDomain + 'api/bolt/getreceiptjson/' + ccMID + '/' + serialNo; 59073 var payload = {"multiScheduleId": multiScheduleId , "amount": amount}; 59074 var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: payload, dataType: 'json' }) 59075 .success(function(data, textStatus, jqXHR) { 59076 window.onbeforeunload = null; 59077 return data; 59078 }) 59079 .error(function(jqXHR, textStatus, errorThrown) { 59080 GLO.UI.Form.resetProcessing(); 59081 new GLO.Popup.Error('Unable to Ping device'); 59082 }); 59083 59084 } 59085 59086 _bolt.ClientCheckIn = function() { 59087 //TODO: CLIENT CHECK-IN FLOW 59088 } 59089 59090 function _displayEmvCommunicateError(msg, h1, isCloseSwipePopup) { //only display warning if has swipe popup open (+ not processing card-on-file) 59091 if ($('#appt-price-swipe-ready').closest('.glopop').length > 0) { 59092 if ($('#pop-card-on-file-view').closest('.glopop').length === 0 && $('#btnUseCardOnFile.btnProcessing4').length === 0) { 59093 if ($('#pop-warn-emv-communicate').length === 0 && $('.pop-error.glopop, .pop-warning.glopop').length === 0) { 59094 h1 = UTIL.coalesceString(h1, 'Payment Processing Warning'); 59095 msg = '<div id="pop-warn-emv-communicate">' + msg + '</div>'; 59096 GLO.Popup.Warning.open(msg, h1); 59097 59098 if (isCloseSwipePopup) { 59099 UserPortal.Price.Payment.closeSwipePopup(true); 59100 } 59101 59102 return true; 59103 } 59104 } 59105 } 59106 } 59107 59108 return _bolt; 59109})(); 59110 59111SA.Ticket = (function() { 59112 function _conTicket() { } 59113 var _addLineToHeaderTimeout = null, _isLoading = false, _time = null; 59114 59115 var _timeoutApplyDiscounts = null; 59116 var _serviceXml = ''; //<tr> 59117 var _productXml = ''; //<ul> <li> 59118 var _paymentXml = ''; //<ol> <lp> 59119 var _discountXml = ''; //<dl> <dd> 59120 var _multiTicketXml = ''; //<ml> <mt> 59121 var _clientTagXml = null, _clientTagRelationshipXml = null; //<tags> <tag> | <rl> <li> 59122 59123 _conTicket.discountDelArray = []; 59124 _conTicket.bookingNumber = null; _conTicket.createDate = null; _conTicket.lastUpdateDate = null; 59125 _conTicket.clientId = null; _conTicket.clientName = null; _conTicket.clientType = null; //POS only supports client buyers: _conTicket.staffId = null; _conTicket.staffName = null; 59126 _conTicket.promoCode = null; _conTicket.isCustomDiscount = false; _conTicket.waitId = null; 59127 _conTicket.memberServiceXml = null; 59128 59129 var _deleteInventoryXml = '', _deleteScheduleIds = ''; 59130 var _initialPayment = 0, _originalTotal = 0, _productTip = 0; 59131 var _cftid = null, _membershipId = null, _giftBalance = 0, _birthDays = null; 59132 var _clientLoyalty = 0, _ticketLoyalty = 0, _availableLoyalty = 0; 59133 var _lastServiceStart = null, _lastServiceEnd = null; //= only used when open/save ticket. 59134 59135 var _apptStatus = null, _dtCheckin = null, _dtCheckout = null, _dtSignin = null; 59136 var _clientNote = '', _staffNote = '', _dtDue = null, _scheduleRecurId = null, _imageCount = 0, _providerReferral = null; 59137 var _discountCount = 0; _referralDiscount = 0; 59138 59139 _conTicket.getTotalPrice = function() { 59140 var jticket = $('#pos-ticket'); 59141 return UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 59142 } 59143 _conTicket.getTotalPayment = function() { 59144 var lp = $('<ol>' + _paymentXml + '</ol>').find('lp'); 59145 var payment = 0; 59146 59147 for (var i=0; i < lp.length; i++) { 59148 payment += UTIL.coalesceMoney(lp.eq(i).attr('payment_mn')); 59149 } 59150 59151 return UTIL.coalesceMoney(payment); 59152 } 59153 _conTicket.getTime = function() { 59154 return _time; 59155 } 59156 _conTicket.getPaymentDate = function() { 59157 var lp = $('<ol>' + _paymentXml + '</ol>').find('lp'); 59158 59159 for (var i=0; i < lp.length; i++) { 59160 var payment = UTIL.coalesceMoney(lp.eq(i).attr('payment_mn')); 59161 59162 if (payment > 0) { 59163 return new Date(lp.eq(i).attr('create_dt'));
59164 } 59165 } 59166 59167 return null; 59168 } 59169 59170 _conTicket.getPaymentXml = function() { 59171 return _paymentXml; // $('<ol>' + _paymentXml + '</ol>').find('lp'); 59172 } 59173 function _getDiscountXml(isAddActive) { 59174 if (!UTIL.isEmpty(_discountXml)) { 59175 var dxml = $('<dl>' + _discountXml + '</dl>'); 59176 59177 if (isAddActive) { 59178 var dd = dxml.find('dd'); 59179 59180 for (var i=0; i < dd.length; i++) { 59181 dd.eq(i).attr('is_active_fl', '1'); 59182 } 59183 } 59184 59185 return dxml.outerHTML(); 59186 } else { 59187 return ''; 59188 } 59189 } 59190 _conTicket.getDiscountArray = function() { 59191 var isPaid = UserPortal.Price.isTicketHasCheckout(); 59192 var dxml = $('<dl>' + _discountXml + '</dl>'); 59193 59194 return UserPortal.Price.Discount.addXml(dxml, isPaid); 59195 } 59196 _conTicket.setDiscountXml = function(discountArray, discountXml) { 59197 if (!UTIL.isEmpty(discountXml)) { 59198 if (discountXml.html) { 59199 _discountXml = discountXml.html(); 59200 } else { 59201 _discountXml = discountXml; 59202 } 59203 } else if (discountArray && discountArray.length) { 59204 var dxml = UserPortal.Price.Discount.arrayToXml(discountArray); 59205 59206 if (!UTIL.isEmpty(dxml)) { 59207 _discountXml = $(dxml).html(); 59208 } else { 59209 _discountXml = ''; 59210 } 59211 } else { 59212 _discountXml = ''; 59213 return; 59214 } 59215 59216 _conTicket.recalculateDiscountTotal(); 59217 } 59218 _conTicket.getDiscountValues = function() { 59219 var jlines = $('#pos-ticket-order').find('.pos-ticket-line-item'); 59220 var totalLineItemDiscount = 0, totalLineItemFee = 0; 59221 59222 for (var l=0; l < jlines.length; l++) { 59223 var jl = jlines.eq(l); 59224 var cnt = UTIL.coalesceInt(jl.find('.line-item-amount').val(), 1); 59225 59226 var addOnFee = UTIL.coalesceMoney(jl.attr('add_on_fee_mn')); 59227 var discount = UTIL.coalesceMoney(jl.attr('new_discount_mn'), jl.attr('discount_mn')); 59228 59229 totalLineItemFee = UTIL.coalesceMoney(cnt * addOnFee + totalLineItemFee); 59230 totalLineItemDiscount = UTIL.coalesceMoney(cnt * discount + totalLineItemDiscount); 59231 } 59232 59233 return { "discount_mn": totalLineItemDiscount, "add_on_fee_mn": totalLineItemFee }; 59234 } 59235 _conTicket.updateDiscountAttributes = function() { //= use for debugging 59236 var dds = $('<dl>' + _discountXml + '</dl>').find('dd'); 59237 var totalDiscount = 0, totalFee = 0; 59238 59239 for (var i=0; i < dds.length; i++) { 59240 var dd = dds.eq(i); 59241 var dmn = UTIL.coalesceMoney(dd.attr('discount_mn')), dpct = UTIL.coalesceFloat(dd.attr('discount_pct')); 59242 59243 _setDiscountTicketAttributes(dd); 59244 59245 if (dmn < 0 || dpct < 0) { 59246 totalFee = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('fee_amount_mn'), dd.attr('amount_mn')) + totalFee); 59247 } else { 59248 totalDiscount = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('amount_mn')) + totalDiscount); 59249 } 59250 } 59251 59252 return { "discount_mn": totalDiscount, "add_on_fee_mn": totalFee }; 59253 } 59254 _conTicket.recalculateDiscountTotal = function() { 59255 if (UserPortal.Price.isTicketHasCheckout()) { 59256 return; 59257 } 59258 59259 var totalFromLineItems = _conTicket.getDiscountValues();
59260 var totalFromDiscountItems = _conTicket.updateDiscountAttributes(); 59261 59262 var dLine = totalFromLineItems.discount_mn; 59263 var fLine = totalFromLineItems.add_on_fee_mn; 59264 59265 var dItem = totalFromDiscountItems.discount_mn; 59266 var fItem = totalFromDiscountItems.add_on_fee_mn; 59267 59268 /* if (!_isLoading && (dLine != dItem || fLine != fItem)) { 59269 var msg = 'P' + _conTicket.bookingNumber + ' diff in POS, discount = ' + UTIL.displayMoney(dLine - dItem) + ': ' + dLine + ' / ' + dItem; 59270 msg += ' | add-on fee = ' + UTIL.displayMoney(fLine - fItem) + ': ' + fLine + ' / ' + fItem; 59271 GLO.Log.insertSimple('Recalculate Discount Diff in POS', msg, 'high'); 59272 } */ 59273 59274 //totalFromLineItems.discount_mn = UTIL.coalesceMoney(totalFromLineItems.discount_mn + _conTicket.getReferralDiscount()); 59275 _conTicket.setDiscountUI(totalFromLineItems); 59276 } 59277 _conTicket.removeDiscount = function(providerDiscountId, scheduleDiscountId) { 59278 var arrd = _conTicket.getDiscountArray(); 59279 59280 for (var i=0; i < arrd.length; i++) { 59281 if (scheduleDiscountId = arrd[i].schedule_discount_id || (UTIL.isEmpty(scheduleDiscountId) && providerDiscountId == arrd[i].provider_discount_id)) { 59282 arrd.splice(i, 1); 59283 } 59284 } 59285 59286 _conTicket.setDiscountXml(arrd); 59287 } 59288 _conTicket.updateDiscountAttribute = function(pdid, sdid, rowIndex, attributeName, attributeValue) { 59289 var arrd = _conTicket.getDiscountArray(); 59290 59291 for (var i=0; i < arrd.length; i++) { 59292 if (sdid = arrd[i].schedule_discount_id) { 59293 arrd[i][attributeName] = attributeValue; 59294 break; 59295 } else if (UTIL.isEmpty(sdid) && pdid == arrd[i].provider_discount_id && i == rowIndex) { 59296 arrd[i][attributeName] = attributeValue; 59297 break; 59298 } 59299 } 59300 59301 _conTicket.setDiscountXml(arrd); 59302 _conTicket.recalculateDiscountTotal(); 59303 } 59304 _conTicket.getServiceAttribute = function(rowIndex, attributeName) { 59305 return $('#pos-ticket').find('.pos-service-line-item').eq(rowIndex).attr(attributeName); 59306 } 59307 _conTicket.setServiceAttribute = function(rowIndex, attributeName, attributeValue) { 59308 $('#pos-ticket').find('.pos-service-line-item').eq(rowIndex).attr(attributeName, attributeValue); 59309 } 59310 _conTicket.setDiscountAttribute = function(rowIndex, attributeName, attributeValue) { 59311 var arrd = SA.Ticket.getDiscountArray(); 59312 59313 if (arrd && arrd[rowIndex]) { 59314 arrd[rowIndex][attributeName] = attributeValue; 59315 SA.Ticket.setDiscountXml(arrd); 59316 } 59317 } 59318 function _setDiscountTicketAttributes(dd) { 59319 var promo = dd.attr('promo_code_vc'); 59320 _conTicket.promoCode = UTIL.coalesceString(promo, _conTicket.promoCode); 59321 59322 if (UTIL.parseBool(dd.attr('custom_discount_fl'))) { 59323 _conTicket.isCustomDiscount = true; 59324 } 59325 } 59326 _conTicket.addDiscountToXml = function(discountObject) { 59327 var arr = _conTicket.getDiscountArray(); 59328 arr.push(discountObject); 59329 _conTicket.setDiscountXml(arr); 59330 } 59331 59332 _conTicket.getCheckoutDate = function() { 59333 var svcCount = $('#pos-ticket').find('.pos-service-line-item').length; 59334 59335 if (svcCount > 0) { 59336 return _dtCheckout; 59337 } else if (SA.Ticket.getTotalPayment() >= SA.Ticket.getTotalPrice()) { 59338 return _conTicket.getPaymentDate(); 59339 } 59340 } 59341 _conTicket.getReferralId = function() { 59342 return _providerReferral; 59343 } 59344 _conTicket.getMembershipId = function() { 59345 return _membershipId; 59346 } 59347 _conTicket.getBirthDays = function() { 59348 return _birthDays; 59349 } 59350 59351 function _getTicketInventoryXml(jproducts, isIncludeUL, serviceCount) { 59352 if (jproducts.length > 0) { 59353 var ixml = ''; 59354 59355 for (var i=0; i < jproducts.length; i++) { 59356 var jp = jproducts.eq(i); 59357 ixml += _openAddLineItem(jp); 59358 } 59359 59360 if (isIncludeUL) { 59361 return '<ul>' + ixml + '</ul>'; 59362 } else { 59363 return ixml; 59364 } 59365 } else { 59366 return ''; 59367 } 59368 } 59369 _conTicket.getProductXml = function() { 59370 var jtix = $('#pos-ticket'); 59371 var jproducts = jtix.find('.pos-ticket-line-item:not(.pos-service-line-item)'); //.pos-product-line-item 59372 var serviceCount = jtix.find('.pos-ticket-line-item.pos-service-line-item').length; 59373 59374 return _getTicketInventoryXml(jproducts, false, serviceCount); //UserPortal.Price.inventoryXml 59375 //return _productXml; 59376 } 59377 _conTicket.setProductXml = function(xml) { 59378 var jproducts = $('#pos-ticket').find('.pos-product-line-item'); 59379 var jli = $('<ul>' + xml + '</ul>').find('li'); 59380 var hasUpdate = false; 59381 59382 for (var p=0; p < jproducts.length; p++) { 59383 for (var i=0; i < jli.length; i++) { 59384 var siid = jproducts.eq(p).attr('schedule_inventory_id'); 59385 59386 if (siid == jli.eq(i).attr('schedule_inventory_id') || (UTIL.isEmpty(siid) && jproducts.eq(p).attr('inventory_id') == jli.eq(i).attr('inventory_id')) ) { 59387 hasUpdate = true; 59388 var addOnFee = jli.eq(i).attr('add_on_fee_mn'); 59389 var discount = jli.eq(i).attr('discount_mn'); 59390 var newDiscount = jli.eq(i).attr('new_discount_mn'); 59391 59392 if (!UTIL.isEmpty(addOnFee)) { 59393 jproducts.eq(p).attr('add_on_fee_mn', addOnFee); 59394 } else { 59395 jproducts.eq(p).removeAttr('add_on_fee_mn'); 59396 } 59397 59398 if (!UTIL.isEmpty(discount)) { 59399 jproducts.eq(p).attr('discount_mn', discount); 59400 } else { 59401 jproducts.eq(p).removeAttr('discount_mn'); 59402 } 59403 59404 if (!UTIL.isEmpty(newDiscount)) { 59405 jproducts.eq(p).attr('new_discount_mn', newDiscount); 59406 } else { 59407 jproducts.eq(p).removeAttr('new_discount_mn'); 59408 } 59409 } 59410 } 59411 } 59412 59413 if (hasUpdate) { 59414 //?? ToDo: update _productXml ?? 59415 } 59416 } 59417 59418 _conTicket.adjustMultiTicketTotal = function() { 59419 if (_multiTicketXml.length > 0 && _multiTicketXml.find('mt').length > 0) { 59420 var jticket = $('#pos-ticket'); 59421 var jtickets = jticket.find('.multi-ticket-row'); 59422 var totalDue = 0; 59423 //var thisTicketTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')) 59424 59425 for (var m = 0; m < jtickets.length; m++) { 59426 totalDue += UTIL.coalesceMoney(jtickets.eq(m).find('.multi-ticket-row-due').text().replace('$', '')) 59427 } 59428 59429 _setMultiTicketTotal(totalDue); 59430 } 59431 } 59432 59433 _conTicket.loadTicket = function(data) { 59434 _conTicket.reset(); 59435 var jticket = $('#pos-ticket').addClass('is-loading'); 59436 var btnViewTicket = jticket.find('#btnViewTicket'); 59437 59438 GLO.UI.Form.beginProcessing(btnViewTicket); 59439 _conTicket.displayTicket(); 59440 59441 setTimeout(function() { 59442 _isLoading = true; 59443 var isTicketDataLoaded = _loadTicketData(data); 59444 _isLoading = false; 59445 59446 if (isTicketDataLoaded) { 59447 _conTicket.recalculate(); 59448 _conTicket.recalculateDiscountTotal(); 59449 _originalTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 59450 59451 jticket.find('#btnSaveTicket > a.unsaved-change').removeClass('unsaved-change'); 59452 _setBookingNumber(); 59453 } 59454 59455 GLO.UI.Form.resetProcessing(btnViewTicket); 59456 GLO.Popup.closeIfExist($('#pop-processing-view-in-pos').closest('.glopop')); 59457 }, 20); 59458 } 59459 function _loadTicketData(data) { 59460 var jticket = $('#pos-ticket'); 59461 var jd = $('<div>' + data + '</div>'); 59462 var pnotes = jd.find('p'); //note fields on product-only ticket 59463 var h2 = jd.find('h2'); 59464 59465 if (h2.length === 0) { 59466 h2 = $(data).eq(0); //= use first <tr> 59467 } 59468 59469 _serviceXml = $('<tbody>' + data + '</tbody>').find('tr'); // $(data); 59470 _productXml = jd.find('ul li'); 59471 _multiTicketXml = jd.find('ml'); 59472 59473 _loadTagXml(jd); 59474 _loadMain(jticket, h2, pnotes); 59475 _loadDiscountRows(jticket, jd, h2); 59476 _loadPaymentRows(jd, h2); 59477 _loadServiceRows(); 59478 59479 if (_loadProductRows()) { //= has products that can be loaded in POS Screen or has no products 59480 _finishAddProductOrService(); 59481 59482 _conTicket.applyDiscounts(10, true); 59483 _originalTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 59484 _conTicket.setStaffHeader(); 59485 59486 setTimeout(function() { 59487 $('#pos-ticket').removeClass('is-loading'); 59488 }, 1500); 59489 59490 return true; 59491 } else { 59492 jticket.removeClass('is-loading'); 59493 return false; 59494 } 59495 } 59496 _conTicket.setStaffHeader = function() { 59497 var jticket = $('#pos-ticket'); 59498 var jservices = jticket.find('.pos-service-line-item'); 59499 59500 if (jservices.length > 0) { 59501 var tip = 0, isClientRequest = false, currentStaffId = jservices.eq(0).attr('staff_id'); 59502 59503 for (var i=0; i < jservices.length; i++) { 59504 var jsvc = jservices.eq(i); 59505 var newStaffId = jsvc.attr('staff_id'); 59506 59507 if (currentStaffId != newStaffId) { 59508 _setStaffHeader2(jticket, currentStaffId, tip, isClientRequest); 59509 currentStaffId = newStaffId;
59510 tip = isClientRequest = 0; 59511 } 59512 59513 //tip += UTIL.coalesceMoney(jsvc.attr('tip_mn')); 59514 //if (UTIL.parseBool(jsvc.attr('client_request_fl'))) { isClientRequest = true; } 59515 isClientRequest = _conTicket.getIsClientRequest(newStaffId); 59516 } 59517 59518 _setStaffHeader2(jticket, currentStaffId, tip, isClientRequest); 59519 } 59520 } 59521 function _setStaffHeader2(jticket, currentStaffId, tip, isClientRequest) { 59522 var jStaffRow = jticket.find('#staff-row-' + currentStaffId); 59523 _setStaffHeaderTip(jStaffRow, tip); 59524 _setStaffHeaderClientRequest(jStaffRow, isClientRequest); 59525 } 59526 function _setStaffHeaderTip(jStaffRow, tip) { 59527 if (tip > 0) { 59528 tip = UTIL.coalesceMoney(tip); 59529 var tipHtm = '<b class="staff-row-tip-amount" title="Tip = $' + tip + '"><i class="plus-sign">+</i><span class="dollar-sign">$</span><i>' + tip + '</i></b>'; 59530 59531 jStaffRow.append(tipHtm); 59532 } else { 59533 jStaffRow.find('.staff-row-tip-amount').remove(); 59534 } 59535 } 59536 function _setStaffHeaderClientRequest(jStaffRow, isClientRequest) { 59537 if (UTIL.parseBool(isClientRequest)) { 59538 var htm = '<span class="staff-row-client-request" title="Is Client Request"> <b class="checkmark-icon"></b> </span>'; 59539 59540 jStaffRow.addClass('is-client-request').prepend(htm); 59541 } else { 59542 jStaffRow.removeClass('is-client-request').find('.staff-row-client-request').remove(); 59543 } 59544 } 59545 function _loadMain(jticket, h2, pnotes) { 59546 SA.Ticket.resetDate(); 59547 var serviceCount = 0; 59548 59549 if (_serviceXml && _serviceXml.length > 0) { 59550 serviceCount = _serviceXml.length; 59551 } 59552 59553 if (h2.length > 0) { 59554 var jmain = h2; 59555 var day = h2.attr('appt_dt'), tm = h2.attr('time_vc'); 59556 //product_tip_mn 59557 } else if (_serviceXml && _serviceXml.length > 0) { 59558 var jmain = _serviceXml.eq(0); 59559 var day = _serviceXml.eq(0).attr('appt_dt'), tm = _serviceXml.eq(0).attr('time_vc'); 59560 //var _dtCheckin = null, _dtCheckout = null, _dtSignin = null, _scheduleRecurId = null; 59561 } else { 59562 return; 59563 } 59564 59565 if (UTIL.isDate(day) && UTIL.isValidTime(tm)) { 59566 SA.Ticket.setStartDate(day, tm); 59567 } 59568 59569 _loadTicketSpecific(jticket, jmain, serviceCount); 59570 _loadNotes(jmain, pnotes); 59571 _loadClientSpecific(jmain); 59572 _displayTags(); 59573 59574 var clientAttributes = _displayClientAttributes(); 59575 _loadMultiTicket(clientAttributes); 59576 } 59577 function _loadMultiTicket(clientAttributes) { 59578 if (_multiTicketXml.length > 0) { 59579 var jcontainer = $('#pos-ticket-client-attributes').removeClass('hide'); 59580 var mts = _multiTicketXml.find('mt'); 59581 var icon = '<span class="multi-ticket-icon-container" title="' + UTIL.pluralLabel(mts.length, 'Linked Ticket') + '"></span>'; //$('#pos-ticket-client-header').prepend(icon); 59582 var totalDue = 0; 59583 59584 for (var m = 0; m < mts.length; m++) { 59585 var mt = mts.eq(m); 59586 var smid = mt.attr('schedule_multi_id'); 59587 var svcCount = mt.attr('service_count_sr'); 59588 var cid = mt.attr('client_id'); 59589 var cname = mt.attr('client_vc'); 59590 59591 var due = UTIL.coalesceMoney(UTIL.coalesceMoney(mt.attr('service_mn')) + UTIL.coalesceMoney(mt.attr('product_mn')) 59592 - UTIL.coalesceMoney(mt.attr('discount_mn')) + UTIL.coalesceMoney(mt.attr('fee_mn')) 59593 + UTIL.coalesceMoney(mt.attr('tax_mn')) + UTIL.coalesceMoney(mt.attr('tip_mn')) - UTIL.coalesceMoney(mt.attr('payment_mn'))); 59594 var fn = 'UserPortal.Price.MultiTicket.gotoTicket(' + smid + ', null, ' + cid + ', ' + svcCount + ', false)'; 59595 59596 if (due > 0) { 59597 var htmDue = '<b class="multi-ticket-row-due">$' + due + '</b>'; 59598 } else { 59599 var htmDue = '<b class="multi-ticket-row-paid">PAID</b>'; 59600 } 59601 59602 var htmClient = '<b class="multi-ticket-row-client">' + UTIL.maxString(cname, 12, true) + '</b>'; 59603 var htm = '<div class="multi-ticket-row" onclick="' + fn + '">' + icon + htmClient + htmDue + '</div>'; 59604 jcontainer.append(htm); 59605 totalDue += due; 59606 } 59607 59608 _setMultiTicketTotal(totalDue); 59609 } 59610 } 59611 function _setMultiTicketTotal(totalDue) { 59612 var jcontainer = $('#pos-ticket-client-attributes'); 59613 var jticket = $('#pos-ticket'); 59614 59615 var thisTicketPrice = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 59616 var thisTicketPayment = UTIL.coalesceMoney(jticket.find('#pos-ticket-header-paid-amount').text().replace('$', '')); 59617 var due = UTIL.coalesceMoney(totalDue + thisTicketPrice - thisTicketPayment); 59618 59619 if (due > 0) { 59620 var cssTotal = 'multi-ticket-total-due', htmTotal = '<label>Total Due</label> <b class="multi-ticket-row-due">' + UTIL.displayMoney(due) + '</b>'; 59621 } else { 59622 var cssTotal = 'multi-ticket-total-paid', htmTotal = '<label>Total </label> <b class="multi-ticket-row-paid">PAID</b>'; 59623 } 59624 59625 jcontainer.find('.multi-ticket-row-total').remove(); 59626 jcontainer.append('<div class="multi-ticket-row-total ' + cssTotal + '">' + htmTotal + '</div>'); 59627 } 59628 function _loadTicketSpecific(jticket, jmain, serviceCount) { 59629 var smid = jmain.attr('schedule_multi_id'); 59630 jticket.attr('schedule_multi_id', smid); 59631 _apptStatus = _getApptStatus(smid, jmain.attr('appt_status_cd')); 59632 59633 _conTicket.bookingNumber = UTIL.cleanString(jmain.attr('booking_nr'));
59634 _conTicket.createDate = jmain.attr('create_dt'); 59635 _conTicket.lastUpdateDate = UTIL.coalesceString(jmain.attr('last_update_dt'), jmain.attr('update_dt')); 59636 59637 _imageCount = UTIL.coalesceInt(jmain.attr('image_count_sr'), 0); 59638 _productTip = UTIL.coalesceMoney(jmain.attr('product_tip_mn')); 59639 _providerReferral = jmain.attr('provider_referral_id'); 59640 _scheduleRecurId = jmain.attr('schedule_recur_id'); 59641 59642 if (UTIL.isDate(jmain.attr('checkin_dt'))) { _dtCheckin = jmain.attr('checkin_dt'); } 59643 if (UTIL.isDate(jmain.attr('checkout_dt'))) { _dtCheckout = jmain.attr('checkout_dt'); } 59644 if (UTIL.isDate(jmain.attr('signin_dt'))) { _dtSignin = jmain.attr('signin_dt'); } 59645 59646 if (UTIL.isDate(jmain.attr('due_dt'))) { 59647 _dtDue = new Date(jmain.attr('due_dt')); 59648 59649 if (serviceCount == 0) { 59650 $('#pos #Ticket_day').val(_dtDue.toGloDate()); 59651 } 59652 } 59653 } 59654 function _loadNotes(jmain, jnotes) { 59655 var clientNote = jmain.attr('special_request_vcl'); 59656 var staffNote = jmain.attr('staff_only_note_vc'); 59657 59658 for (var i=0; i < jnotes.length; i++) { 59659 if (jnotes.eq(i).attr('id') == 'ticket-client-note') { 59660 clientNote = UTIL.coalesceString(clientNote, jnotes.eq(i).text()); 59661 } 59662 59663 if (jnotes.eq(i).attr('id') == 'ticket-staff-note') { 59664 staffNote = UTIL.coalesceString(staffNote, jnotes.eq(i).text()); 59665 } 59666 } 59667 59668 if (!UTIL.isEmpty(clientNote)) { 59669 _clientNote = clientNote; 59670 SA.Ticket.loadClientNote('appt-request', _clientNote); 59671 } 59672 59673 if (!UTIL.isEmpty(staffNote)) { 59674 _staffNote = staffNote; 59675 SA.Ticket.loadClientNote('appt-staff-only', _staffNote); 59676 } 59677 59678 if (!UTIL.isEmpty(jmain.attr('staff_note_vcl'))) { 59679 var staffNotePopup = jmain.attr('staff_note_vcl'); 59680 59681 if (!UTIL.isEmpty(staffNotePopup)) { 59682 SA.Ticket.loadClientNote('client-important-note', staffNotePopup); //UserPortal.displayClientStaffNote(staffNotePopup, true); 59683 } 59684 } 59685 } 59686 function _loadClientSpecific(jmain) { 59687 _conTicket.clientId = UTIL.cleanString(jmain.attr('client_id')); 59688 _conTicket.clientName = UTIL.cleanString(jmain.attr('client_vc')); 59689 _conTicket.clientType = UTIL.cleanString(jmain.attr('client_type_cd')); 59690 59691 _clientLoyalty = UTIL.coalesceInt(jmain.attr('client_loyalty_nr'), 0); 59692 _ticketLoyalty = UTIL.coalesceInt(jmain.attr('ticket_loyalty_nr'), 0); 59693 _availableLoyalty = UTIL.coalesceInt(jmain.attr('available_loyalty_nr'), 0); 59694 59695 _cftid = UTIL.coalesceInt(jmain.attr('card_on_file_tid'), jmain.attr('cftid')); 59696 _membershipId = jmain.attr('membership_id'); 59697 _giftBalance = jmain.attr('gift_balance_mn'); 59698 _birthDays = jmain.attr('birth_sr'); 59699 59700 var hasNote = (UTIL.parseBool(jmain.attr('warning_see_note_fl'))); 59701 var tagCount = UTIL.coalesceInt(jmain.attr('tag_count_sr'), 0); 59702 _addClientComplete2(hasNote, tagCount); 59703 } 59704 function _displayClientAttributes() { 59705 //LATER: _scheduleRecurId, _imageCount, _providerReferral 59706 59707 var jch = $('#pos-ticket-client-header'); 59708 var jca = $('#pos-ticket-client-attributes'); 59709 var attributes = 0; 59710 59711 if (_conTicket.clientType == 1) { 59712 jch.prepend('<span class="new-client-text-icon" title="New Client"><b>new</b></span>'); 59713 ++attributes; 59714 } 59715 59716 if (!UTIL.isEmpty(_membershipId)) { 59717 var htmMemberIcon = GLO.Provider.Membership.getIcon(_membershipId, _conTicket.clientId, _conTicket.clientName); 59718 59719 jch.prepend(htmMemberIcon); //SA.Ticket.loadClientNote('client-membership', htmMember); 59720 ++attributes; 59721 } 59722 59723 if (!UTIL.isEmpty(_cftid)) { 59724 var fnCoF = 'UserPortal.displayCardOnFile(\'' + _conTicket.clientId + '\',' + _cftid + ', \'' + _conTicket.clientName + '\')'; 59725 var htmCardOnFile = '<span class="client-has-card-on-file" cftid="' + _cftid + '" onclick="' + fnCoF + '" title="Has Card On File"><span></span></span>'; 59726 59727 jch.prepend(htmCardOnFile); //SA.Ticket.loadClientNote('client-card-on-file', htmCardOnFile); 59728 ++attributes; 59729 } 59730 59731 if (!UTIL.isEmpty(_birthDays)) { 59732 var apptDay = SA.Ticket.getStartDate(); 59733 var birthdayMessage = UserPortal.getBirthdayMessage(_birthDays, apptDay, 60); 59734 59735 if (!UTIL.isEmpty(birthdayMessage)) { 59736 var htmBirth = '<span class="client-attribute-birthday">' + birthdayMessage + '</span>'; 59737 59738 SA.Ticket.loadClientNote('client-birthday', htmBirth); 59739 ++attributes; 59740 } 59741 } 59742 59743 if (_giftBalance > 0) { 59744 var htmGift = '<span class="client-attribute-gift"><span class="dollar-sign">$</span>' + UTIL.displayMoney(_giftBalance, true, false, true) + ' Gift Card Balance</span>'; 59745 59746 SA.Ticket.loadClientNote('client-gift', htmGift); 59747 ++attributes; 59748 } 59749 59750 if (_clientLoyalty > 0) { 59751 var loyaltyAttributes = ' client_loyalty_nr="' + _clientLoyalty + '" available_loyalty_nr="' + _availableLoyalty + '" ticket_loyalty_nr="' + _ticketLoyalty + '" title="' + _clientLoyalty + ' Loyalty Points"'; 59752 var htmLoyaltyIcon = '<span class="client-loyalty-points" onclick="UserPortal.displayLoyalty(this)"' + loyaltyAttributes + '><span>' + _clientLoyalty + '</span></span>'; 59753 var htmLoyalty = '<span class="client-attribute-loyalty"><label>
59753' + UTIL.makePlural('Loyalty Point', _clientLoyalty) + '</label>' + htmLoyaltyIcon + '</span>'; 59754 59755 SA.Ticket.loadClientNote('client-loyalty', htmLoyalty); 59756 ++attributes; 59757 } 59758 59759 return attributes; 59760 } 59761 function _displayTags() { 59762 if (_clientTagXml && _clientTagXml.length) { 59763 var htmTags = ''; 59764 59765 for (var i=0; i < _clientTagXml.length; i++) { 59766 var tagJson = UTIL.xmlToJson(_clientTagXml[i], 'tag'); 59767 htmTags += GLO.ClientProfile.Tag.getTagHtm(tagJson, _conTicket.clientId, _conTicket.clientName, true); 59768 } 59769 59770 _conTicket.loadClientNote('client-tag', htmTags, _clientTagXml.length); 59771 59772 if (_clientTagRelationshipXml.length) { 59773 var htmRelationshipWithAppt = UserPortal.getApptRelatedTagHtm(_clientTagRelationshipXml, true); 59774 _conTicket.loadClientNote('client-tag-appt', htmRelationshipWithAppt, _clientTagRelationshipXml.length); 59775 } 59776 } 59777 } 59778 59779 function _loadDiscountRows(jticket, jd, h2) { 59780 _discountXml = ''; 59781 _discountCount = 0; 59782 59783 var dds = jd.find('dl dd'); 59784 var total = { "discount_mn": 0, "add_on_fee_mn": 0 }; 59785 59786 if (h2 && h2.length > 0) { 59787 if (UTIL.parseBool(h2.attr('custom_discount_fl'))) { 59788 _conTicket.isCustomDiscount = true; 59789 } 59790 } 59791 59792 _addBasicDiscountAttributes(total, dds, h2); //is custom, count, promo code 59793 _calculateDiscountAndFees(total); //discount / fee on action line item is more reliable 59794 59795 _conTicket.setDiscountUI(total); 59796 } 59797 function _calculateDiscountAndFees(total) { 59798 var totalDiscount = 0, totalAddOnFee = 0; 59799 59800 for (var s=0; s < _serviceXml.length; s++) { 59801 totalDiscount += UTIL.coalesceMoney(_serviceXml.eq(s).attr('discount_mn')); 59802 totalAddOnFee += UTIL.coalesceMoney(_serviceXml.eq(s).attr('add_on_fee_mn')); 59803 } 59804 59805 for (var p=0; p < _productXml.length; p++) { 59806 totalDiscount += UTIL.coalesceMoney(_productXml.eq(p).attr('discount_mn')); 59807 totalAddOnFee += UTIL.coalesceMoney(_productXml.eq(p).attr('add_on_fee_mn')); 59808 } 59809 59810 total.discount_mn = UTIL.coalesceMoney(totalDiscount); 59811 total.add_on_fee_mn = UTIL.coalesceMoney(totalAddOnFee); 59812 } 59813 function _addBasicDiscountAttributes(total, dds, h2) { //is custom, count, promo code 59814 if (dds.length) { 59815 for (var i=0; i < dds.length; i++) { 59816 var dd = dds.eq(i); 59817 59818 if (UTIL.parseBool(dd.attr('is_active_fl'))) { 59819 var dmn = UTIL.coalesceMoney(dd.attr('discount_mn')), dpct = UTIL.coalesceFloat(dd.attr('discount_pct')); 59820 59821 if (dmn > 0 || dpct > 0) { 59822 total.discount_mn = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('amount_mn')) + total.discount_mn); 59823 } else { 59824 total.add_on_fee_mn = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('fee_amount_mn'), dd.attr('amount_mn')) + total.add_on_fee_mn); 59825 } 59826 59827 _discountXml += dd.outerHTML(); 59828 _setDiscountTicketAttributes(dd); 59829 ++_discountCount; 59830 } 59831 } 59832 } else if (h2.length > 0) { 59833 total.discount_mn = UTIL.coalesceMoney(h2.attr('total_discount_mn')); 59834 total.add_on_fee_mn = UTIL.coalesceMoney(h2.attr('total_addOnFee_mn')); 59835 59836 _discountCount = UTIL.coalesceInt(h2.attr('discount_count_sr'), 0); 59837 } 59838 } 59839 59840 _conTicket.sellProduct = function() { 59841 _conTicket.displayTicket(); 59842 SA.POS.toggleList('products'); 59843 } 59844 _conTicket.sellGiftCard = function() { 59845 _conTicket.sellProduct(); 59846 59847 var ctypeId = SA.POS.inventory_json.gift_card_type_id; 59848 SA.POS.filterBoxesCategoryType(ctypeId, false, false); 59849 59850 var jboxes = $('#pos-product-window .pos-product-box'); 59851 var jbox = jboxes.eq(0); 59852 var minInventoryId = jbox.attr('inventory_id'); 59853 59854 for (var i=1; i < jboxes.length; i++) { 59855 var inventoryId = jboxes.eq(i).attr('inventory_id'); 59856 59857 if (inventoryId < minInventoryId) { 59858 minInventoryId = inventoryId; 59859 jbox = jboxes.eq(i); 59860 } 59861 } 59862 59863 if (jbox.length) { 59864 SA.POS.addProductRowToTicket(minInventoryId, jbox); 59865 } else { 59866 var productBoxGiftVoucher = { "id": SA.POS.inventory_json.system_gift_voucher_id, "label":"Gift Voucher", "value":"Gift Voucher", "vend
59866or_id":"", "product_line_id":"", "vendor_merchant_id":"" 59867 , "inventory_type_id":"116", "category_id":"41", "tax_rate_pct":"0.00", "in_stock_dr":"", "sku_vc":"", "upc_vc":"", "vendor_name_vc":"", "size_vc":" " 59868 , "cost_mn":"0.00", "price_mn":"", "employee_price_mn":"", "is_sku_upc_match_fl":"0", "is_gift_card_fl":"1", "default_type_id": 115 }; 59869 59870 var productBox = { "id": SA.POS.inventory_json.system_gift_card_id, "label":"Gift Card", "value":"Gift Card", "vendor_id":"", "product_line_id":"", "vendor_merchant_id":"" 59871 , "inventory_type_id":"115", "category_id":"41", "tax_rate_pct":"0.00", "in_stock_dr":"", "sku_vc":"", "upc_vc":"", "vendor_name_vc":"", "size_vc":" " 59872 , "cost_mn":"0.00", "price_mn":"", "employee_price_mn":"", "is_sku_upc_match_fl":"0", "is_gift_card_fl":"1", "default_type_id": 115 }; 59873 var productName = UTIL.maxStringHtml(productBox.label, 25, false, 'span', '', 'line-item-name', ''); 59874 59875 _conTicket.addLine(productName, productBox.id, null, null, 1, productBox.price_mn, null, null, productBox); 59876 SA.POS.filterBoxesHome(); //press home button 59877 } 59878 } 59879 59880 _conTicket.getReferralDiscount = function() { 59881 return UTIL.coalesceMoney(_referralDiscount); 59882 } 59883 _conTicket.setReferralDiscount = function(referralDiscount) { 59884 _referralDiscount = UTIL.coalesceMoney(referralDiscount); 59885 _conTicket.recalculateDiscountTotal(); 59886 } 59887 _conTicket.setDiscountUI = function(total) { 59888 var addOnFee = UTIL.coalesceMoney(total.add_on_fee_mn); 59889 var discount = UTIL.coalesceMoney(total.discount_mn); 59890 59891 var jtotal = $('#pos-ticket-total-line'); 59892 var jdiscount = jtotal.find('#pos-ticket-total-discount'); 59893 59894 var jfeeAmount = jdiscount.find(' > b#pos-ticket-add-on-fee-amount'); 59895 var jdiscountAmount = jdiscount.find(' > b#pos-ticket-discount-amount'); 59896 59897 var currentFee = UTIL.coalesceMoney(jfeeAmount.text().replace('$', '')); 59898 var currentDiscount = UTIL.coalesceMoney(jdiscountAmount.text().replace('$', '')); 59899 59900 if (addOnFee > 0) { 59901 jdiscount.find(' > small').text('Add-On Fee'); 59902 jdiscount.addClass('has-add-on-fee'); 59903 jfeeAmount.text(UTIL.displayMoney(addOnFee)); 59904 } else { 59905 jdiscount.removeClass('has-add-on-fee'); 59906 jfeeAmount.text(''); 59907 } 59908 59909 if (discount > 0) { 59910 jdiscount.find(' > small').text('Discount'); 59911 jdiscount.addClass('has-discount'); 59912 jdiscountAmount.text(UTIL.displayMoney(discount)); 59913 } else { 59914 jdiscount.removeClass('has-discount'); 59915 jdiscountAmount.text(''); 59916 } 59917 59918 if (currentFee != addOnFee || currentDiscount != discount) { 59919 var subTotal = UTIL.coalesceMoney(jtotal.find('#pos-ticket-total-sub').find(' > b').text().replace('$', '')); 59920 var tax = UTIL.coalesceMoney(jtotal.find('#pos-ticket-total-tax').find(' > b').text().replace('$', '')); 59921 59922 var newTotal = UTIL.displayMoney(subTotal + tax - discount + addOnFee); 59923 var jTotalCell = jtotal.find('#pos-ticket-total-box').find(' > b'); 59924 59925 jTotalCell.text(newTotal); 59926 _styleTotalCell(jTotalCell); 59927 } 59928 } 59929 _conTicket.applyDiscounts = function(waitLen, includeReorder) { 59930 clearTimeout(_timeoutApplyDiscounts); 59931 waitLen = UTIL.coalesceInt(waitLen, 15); 59932 59933 var jdiscount = $('#pos-ticket-total-discount'); 59934 59935 if (!UTIL.isEmpty(jdiscount.find('b').text())) { 59936 jdiscount.addClass('is-processing'); 59937 } 59938 59939 _timeoutApplyDiscounts = setTimeout(function() { 59940 if (UserPortal.Price.Discount.applyDiscounts(null, true)) { 59941 if (includeReorder) { 59942 UserPortal.Price.Discount.reorderDiscounts(); 59943 } 59944 } 59945 59946 _conTicket.recalculateDiscountTotal(); 59947 $('#pos-ticket-total-discount').removeClass('is-processing'); 59948 _setCheckInButton(); 59949 }, waitLen); 59950 } 59951 function _setCheckInButton() { 59952 var jticket = $('#pos-ticket'); 59953 var smid = jticket.attr('schedule_multi_id'); 59954 var price = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 59955 var payment = UTIL.coalesceMoney(_initialPayment); 59956 59957 var jfooter = jticket.find('#pos-ticket-footer'); 59958 var btnCheckinTicket = jfooter.find('#btnCheckinTicket'); 59959 var btnPrintTicket = jfooter.find('#btnPrintTicket'); 59960 var jpaid = jfooter.find('#pos-ticket-paid').addClass('hide'); 59961 var jdue = jfooter.find('#pos-ticket-due').addClass('hide'); 59962 var serviceCount = jticket.find('.pos-service-line-item').length; 59963 var isToday = new Date($('#pos-ticket-datetime #Ticket_day').val()).toGloDate(
59963) == new Date().toGloDate(); 59964 59965 jticket.find('#btnDeleteTicket').addClass('hide'); 59966 59967 if (!isToday || serviceCount === 0) { 59968 btnCheckinTicket.addClass('hide'); 59969 btnPrintTicket.addClass('hide'); 59970 59971 if (serviceCount === 0 && UTIL.isEmpty(smid) && jticket.find('.pos-product-line-item').length == 0) { 59972 jticket.find('#btnDeleteTicket').removeClass('hide'); 59973 } 59974 } else if (UTIL.coalesceInt(_apptStatus, 0) < 13) { 59975 btnCheckinTicket.removeClass('hide'); 59976 btnPrintTicket.addClass('hide'); 59977 } else if (_apptStatus == 21 || _apptStatus == 25) { 59978 btnCheckinTicket.addClass('hide'); 59979 59980 if (payment > 0) { 59981 btnPrintTicket.addClass('hide'); 59982 } else { 59983 btnPrintTicket.removeClass('hide'); 59984 } 59985 } else { 59986 btnCheckinTicket.addClass('hide'); 59987 btnPrintTicket.addClass('hide'); 59988 } 59989 59990 if (payment > 0) { 59991 jticket.find('#pos-ticket-header-paid-amount').text(UTIL.displayMoney(payment, true, false, true)); 59992 59993 if (payment >= price) { 59994 var title = _getPaymentTitle(0); 59995 jpaid.removeClass('hide').attr('title', title); 59996 } else { 59997 var title = _getPaymentTitle(price - payment); 59998 var due = '<span class="dollar-sign">$</span>' + UTIL.displayMoney(price - payment, true, false, true); 59999 60000 if (innerWidth > 1680 || due.length < 8) { 60001 if (String(due).length < 3) { 60002 due = '<small>Due</small> ' + due; 60003 } 60004 } 60005 60006 jdue.removeClass('hide').attr('title', title).html(due); 60007 } 60008 60009 SA.Ticket.adjustMultiTicketTotal(); 60010 } else { 60011 jticket.find('#pos-ticket-header-paid-amount').text('0'); 60012 } 60013 } 60014 function _getPaymentTitle(amountDue) { 60015 var title = UTIL.displayMoney(_initialPayment, false, false, true); 60016 var lps = $('<ol>' + _paymentXml + '</ol>').find('lp'); 60017 60018 if (lps.length === 1) { 60019 title += _getPaymentDateTitle(lps.eq(0)); 60020 } else if (lps.length > 1) { 60021 title = 'Total payment ' + title; 60022 60023 for (var i=0; i < lps.length; i++) { 60024 title += ' | '; 60025 title += UTIL.displayMoney(lps.eq(i).attr('payment_mn'), false, false, true); 60026 title += _getPaymentDateTitle(lps.eq(i)); 60027 } 60028 } 60029 60030 if (amountDue > 0) { 60031 title = 'Due: ' + UTIL.displayMoney(amountDue, false, false, true) + ' | ' + title; 60032 } 60033 60034 return title; 60035 } 60036 function _getPaymentDateTitle(lp) { 60037 var dtPay = lp.attr('create_dt'); 60038 var title = ''; 60039 60040 if (UTIL.isDate(dtPay)) { 60041 title = ' paid on ' + new Date(dtPay).toPrettyDate(true) + ' ' + new Date(dtPay).toGloTime(); 60042 } 60043 60044 return title; 60045 } 60046 function _loadPaymentRows(jd, h2) { 60047 if (h2 && h2.attr) { 60048 _initialPayment = UTIL.coalesceMoney(h2.attr('total_payment_mn')); 60049 } 60050 60051 if (jd.find('ol lp').length) { 60052 _paymentXml = jd.find('ol').html(); 60053 //_initialPayment = 0; 60054 } else if (h2 && h2.attr) { 60055 var pmeth = h2.attr('payment_method_cd'); 60056 60057 if (_initialPayment != 0 && !UTIL.isEmpty(pmeth)) { 60058 var payXml = UserPortal.Price.getSinglePayment(h2, _initialPayment, pmeth); 60059 _paymentXml = payXml; 60060 } 60061 } 60062 } 60063 function _loadProductRows() { 60064 for (var p=0; p < _productXml.length; p++) { 60065 var jp = _productXml.eq(p); 60066 var iid = jp.attr('inventory_id'); 60067 var siid = jp.attr('schedule_inventory_id'); 60068 60069 var amount = UTIL.coalesceInt(jp.attr('amount_nr'), 1); 60070 var price = UTIL.coalesceMoney(jp.attr('price_mn')); 60071 //var tax = UTIL.coalesceMoney(jp.attr('tax_mn')); 60072 //vendor_merchant_id 60073 60074 var jline = SA.Ticket.addProductLine(iid, amount, price); 60075 60076 if (UTIL.isEmptyObject(jline) && $('.pop-processing.glopop').length) { //unable to add product (is-membership or deleted product) 60077 return false; 60078 } 60079 60080 var mid = jp.attr('membership_id'); 60081 var cstaff = jp.attr('commission_staff_id'); 60082 var ptype = jp.attr('inventory_purchase_type_cd'); 60083 60084 var tax = jp.attr('tax_mn'); 60085 var taxRate = jp.attr('tax_rate_pct'); 60086 var addOnFee = jp.attr('add_on_fee_mn'); 60087 var discount = jp.attr('discount_mn'); 60088 60089 var currSIIDs = jline.attr('schedule_inventory_ids'); 60090 60091 if (!UTIL.isEmpty(currSIIDs)) { 60092 siid = currSIIDs + ',' + siid; 60093 } 60094 60095 jline.attr('schedule_inventory_ids', siid); 60096 60097 if (!UTIL.isEmpty(mid)) { jline.attr('membership_id', mid); } 60098 if (!UTIL.isEmpty(cstaff)) { jline.attr('commission_staff_id', cstaff); } 60099 if (!UTIL.isEmpty(ptype)) { jline.attr('inventory_purchase_type_cd', ptype); } 60100 60101 if (!UTIL.isEmpty(tax)) { jline.attr('tax_mn', tax); } 60102 if (!UTIL.isEmpty(taxRate)) { jline.attr('tax_rate_pct', taxRate); } 60103 if (!UTIL.isEmpty(addOnFee)) { jline.attr('add_on_fee_mn', addOnFee); } 60104 if (!UTIL.isEmpty(discount)) { jline.attr('discount_mn', discount); } 60105 60106 if (UTIL.parseBool(jp.attr('is_gift_card_fl'))) { 60107 var giftNumber = $.trim(jp.attr('gift_number_vc')); 60108 60109 jline.attr('is_gift_card_fl', '1'); 60110 jline.attr('gift_card_id', $.trim(jp.attr('gift_card_id'))); 60111 jline.attr('to_client_id', $.trim(jp.attr('to_client_id'))); 60112 jline.attr('gift_number_vc', giftNumber); 60113 jline.attr('gift_original_mn', $.trim(jp.attr('gift_original_mn'))); 60114 jline.attr('gift_balance_mn', $.trim(jp.attr('gift_balance_mn'))); 60115 60116 if (!UTIL.isEmpty(giftNumber)) { 60117 var jname = jline.find('.line-item-name'); 60118 jname.text(jname.text() + ' #' + giftNumber); 60119 } 60120 } else { 60121 jline.removeAttr('is_gift_card_fl').removeAttr('gift_card_id').removeAttr('to_client_id').removeAttr('gift_number_vc').removeAttr('gift_original_mn').removeAttr('gift_balance_mn'); 60122 } 60123 } 60124 60125 return true; 60126 } 60127 function _loadServiceRows() { 60128 var faId, ticketResourceId, arrStaffId = []; 60129 60130 if (_serviceXml && _serviceXml.length) { 60131 if (_serviceXml.length === 1 && _serviceXml.attr && UTIL.isEmpty(_serviceXml.attr('service_id'))) { 60132 var staffId = _serviceXml.attr('staff_id'); 60133 _serviceXml = ''; 60134 60135 if (!UTIL.isEmpty(staffId) && !UserPortal.isFirstAvailable(staffId)
60135) { 60136 var sname = UserPortal.getStaffName(staffId); 60137 SA.POS.selectDefaultStaff(staffId, sname, false); 60138 } 60139 60140 return; 60141 } 60142 60143 for (var s=0; s < _serviceXml.length; s++) { 60144 var jsvc = _serviceXml.eq(s); 60145 var scheduleId = jsvc.attr('schedule_id'); 60146 var serviceId = jsvc.attr('service_id'); 60147 var sgid = jsvc.attr('service_group_id'); 60148 60149 var staffId = jsvc.attr('staff_id'); 60150 var isFA = UserPortal.isFirstAvailable(staffId); 60151 var price = UTIL.coalesceMoney(jsvc.attr('price_mn')); 60152 60153 var jline = SA.Ticket.addServiceLine(serviceId, sgid, staffId, isFA, price, scheduleId); 60154 60155 if (jline && jline.attr) { 60156 jline.attr('schedule_id', scheduleId); 60157 } else { 60158 return; 60159 } 60160 60161 _loadServiceRowLen(jsvc, jline); 60162 _loadServiceRowOther(jsvc, jline, scheduleId); 60163 ticketResourceId = _setTicketResourceId(ticketResourceId, jsvc, s); 60164 60165 if (isFA) { 60166 faId = staffId; 60167 } else if (UTIL.isNumber(staffId) && !arrStaffId.has(staffId)) { 60168 arrStaffId.push(staffId); 60169 } 60170 } 60171 60172 _setTicketLabel(ticketResourceId); 60173 _setApptIcon(_serviceXml); 60174 } 60175 60176 if (!$('#pos-header-staff').hasClass('selected') && (arrStaffId.length === 1 || (arrStaffId.length === 0 && UTIL.isNumber(faId)))) { 60177 if (arrStaffId.length === 1) { 60178 var sid = arrStaffId[0], isFaStaff = false; 60179 } else { 60180 var sid = faId, isFaStaff = true; 60181 } 60182 60183 var sname = UserPortal.getStaffName(sid); 60184 SA.POS.selectDefaultStaff(sid, sname, isFaStaff); 60185 } 60186 } 60187 function _setApptIcon(_serviceXml) { 60188 if (parseInt(_serviceXml.attr('schedule_multi_id')) > 0) { 60189 var dtCreate = new Date(_conTicket.createDate); //var dtCreate = new Date(_serviceXml.attr('create_dt')); 60190 var jdt = $('#pos-ticket-datetime'); 60191 var day = jdt.find('#Ticket_day').val(), time = jdt.find('#Ticket_tm').val(); 60192 60193 if (UTIL.isDate(day) && UTIL.isValidTime(time)) { 60194 var dtStart = new Date(day + ' ' + time); 60195 60196 if ( (dtStart - dtCreate) / (60*60*1000) > 1) { 60197 var icon = '<b class="appt-icon pre-booked-appointment-icon"><a onclick="ClientProfile.openAppointmentActivity(true)"></a></b>'; 60198 } else { 60199 var icon = '<span class="appt-icon walkin-icon"><b title="Walk-In">W</b></span>'; 60200 } 60201 60202 jdt.append(icon); 60203 } 60204 } 60205 } 60206 function _setTicketLabel(ticketResourceId) { 60207 var jlabel = $('#pos-header-staff-ticket-label'); 60208 60209 if (!UTIL.isEmpty(ticketResourceId)) { 60210 var resourceName = UserPortal.getResourceName(ticketResourceId); 60211 jlabel.addClass('ticket-resource-name').text(resourceName); 60212 } else if (_conTicket.bookingNumber > 0) { 60213 jlabel.addClass('ticket-booking-number').text('P' + _conTicket.bookingNumber); 60214 } 60215 } 60216 function _setTicketResourceId(ticketResourceId, jsvc, s) { 60217 var resourceId = jsvc.attr('service_resource_id'); 60218 60219 if (s === 0) { 60220 return resourceId; 60221 } else if (ticketResourceId == resourceId) { 60222 return ticketResourceId; 60223 } else { 60224 return null; 60225 } 60226 } 60227 function _loadServiceRowLen(jsvc, jline) { 60228 if (UTIL.isDate($.trim(jsvc.attr('appt_dt') + ' ' + jsvc.attr('time_vc')))) { 60229 jline.attr('appt_dt', jsvc.attr('appt_dt')); 60230 jline.attr('time_vc', jsvc.attr('time_vc')); 60231 60232 jline.attr('end_dt', jsvc.attr('end_dt')); 60233 } 60234 60235 jline.attr('service_length_nr', jsvc.attr('service_length_nr')); 60236 jline.attr('prep_nr', jsvc.attr('prep_nr')); 60237 jline.attr('prep_fl', jsvc.attr('prep_fl')); 60238 60239 jline.attr('processing_nr', jsvc.attr('processing_nr')); 60240 jline.attr('processing_fl', jsvc.attr('processing_fl')); 60241 jline.attr('finish_out_nr', jsvc.attr('finish_out_nr')); 60242 jline.attr('finish_out_fl', jsvc.attr('finish_out_fl')); 60243 } 60244 function _loadServiceRowOther(jsvc, jline, scheduleId) { 60245 var cr = UTIL.parseBool(jsvc.attr('client_request_fl')); 60246 var customD = UTIL.parseBool(jsvc.attr('custom_discount_fl')); 60247 var split = $.trim(jsvc.attr('commission_split_cd')); 60248 var splitPercent = $.trim(jsvc.attr('commission_split_pct'));
60249 60250 var addOnFee = UTIL.coalesceMoney(jsvc.attr('add_on_fee_mn')); 60251 var discount = UTIL.coalesceMoney(jsvc.attr('discount_mn')); 60252 var discountNew = UTIL.coalesceMoney(jsvc.attr('new_discount_mn')); 60253 60254 var resourceId = $.trim(jsvc.attr('service_resource_id')); 60255 var recurId = $.trim(jsvc.attr('schedule_recur_id')); 60256 var svcAttributeId = $.trim(jsvc.attr('service_attribute_id')); 60257 60258 var price = UTIL.coalesceMoney(jsvc.attr('price_mn')); 60259 var tip = UTIL.coalesceMoney(jsvc.attr('tip_mn')); 60260 var tax = UTIL.coalesceMoney(jsvc.attr('tax_mn')); 60261 var isOutcall = UTIL.parseBool(jsvc.attr('outcall_fl')); 60262 var outcallFee = UTIL.coalesceMoney(jsvc.attr('outcall_fee_mn')); 60263 60264 if (UTIL.isEmpty(scheduleId) && tax === 0 && GLO.serviceTax > 0) { 60265 tax = UTIL.coalesceMoney(GLO.serviceTax/100 * (price - discount + addOnFee)); 60266 } 60267 60268 if (discountNew !== 0) { 60269 jline.attr('new_discount_mn', discountNew); 60270 } 60271 60272 jline.attr('client_request_fl', cr).attr('custom_discount_fl', customD).attr('commission_split_cd', split).attr('commission_split_pct', splitPercent); 60273 jline.attr('discount_mn', discount).attr('add_on_fee_mn', addOnFee); 60274 jline.attr('service_resource_id', resourceId).attr('schedule_recur_id', recurId).attr('service_attribute_id', svcAttributeId); 60275 jline.attr('tip_mn', tip).attr('tax_mn', tax).attr('outcall_fl', isOutcall).attr('outcall_fee_mn', outcallFee); 60276 } 60277 60278 function _finishAddProductOrService() { 60279 var jticket = $('#pos-ticket-order'); 60280 var jproducts = jticket.find('.pos-product-line-item'); 60281 var jproductLabelRow = jticket.find('#pos-product-label-row'); 60282 60283 if (jticket.find('.pos-service-line-item').length > 0 && jproducts.length > 0) { 60284 if (jproductLabelRow.length == 0) { 60285 var htm = '<div id="pos-product-label-row"><span id="pos-product-label">Products</span></div>'; 60286 jproducts.before(htm); 60287 } 60288 } else { 60289 jproductLabelRow.remove(); 60290 } 60291 } 60292 60293 function _setBookingNumber() { 60294 var bkg = $.trim(_conTicket.bookingNumber); 60295 var jbtn = $('#pos-ticket #btnViewTicket').removeClass('appt-status-no-show').removeClass('appt-status-late-cancel').removeClass('appt-status-checked-in').removeClass('appt-status-checked-out'); 60296 var abtn = jbtn.find('>a').removeClass('is-narrow') 60297 60298 if (!UTIL.isEmpty(bkg)) { 60299 if (bkg.length > 5 && innerWidth < 1680) { 60300 abtn.addClass('is-narrow'); 60301 } 60302 60303 abtn.text(SA.Resource.View + ' P' + bkg); 60304 } else { 60305 abtn.text(abtn.attr('original_text')); 60306 } 60307 60308 if (_apptStatus == 13) { //_dtCheckin, _dtCheckout, _dtSignin 60309 jbtn.addClass('appt-status-no-show'); 60310 } else if (_apptStatus == 14) { 60311 jbtn.addClass('appt-status-checked-late-cancel'); 60312 } else if (_apptStatus == 21) { 60313 jbtn.addClass('appt-status-checked-in'); 60314 } else if (_apptStatus == 22) { 60315 jbtn.addClass('appt-status-checked-out'); 60316 } 60317 } 60318 60319 _conTicket.initOpenFromDB = function(data) { 60320 var returnData = $(data); 60321 var ul = $(data).find('ul'); 60322 var lis = ul.find('>li'); 60323 var jPricePop = $('#appt-price-popup'); 60324 var jtix = $('#pos-ticket'); 60325 var jlines = jtix.find('.pos-product-line-item'); 60326 60327 var tixUpdateDate = jtix.attr('last_update_dt'); 60328 var dataUpdateDate = returnData.find('h2').attr('update_dt'); 60329 var dateDiff = 0; 60330 60331 if (UTIL.isDate(tixUpdateDate) && UTIL.isDate(dataUpdateDate)) { 60332 dateDiff = new Date(tixUpdateDate).getTime() - new Date(dataUpdateDate).getTime(); 60333 } 60334 60335 for (var l=0; l < jlines.length; l++) { 60336 var iid = parseInt(jlines.eq(l).attr('inventory_id')); 60337 var quantity = UTIL.coalesceInt(jlines.eq(l).find('.line-item-amount').val(), 0); 60338 var price = UTIL.coalesceMoney(jlines.eq(l).find('.line-item-price').val(), 0); 60339 var foundCount = 0; 60340 60341 for (var q=0; q < quantity; q++) { 60342 for (var i=0; i < lis.length; i++) { 60343 if (iid === parseInt(lis.eq(i).attr('inventory_id'))) { 60344 if (price !== UTIL.coalesceMoney(lis.eq(i).attr('price_mn'))) { //use price on pos-ticket (not from DB). 60345 var siid = lis.eq(i).attr('schedule_inventory_id'); 60346 returnData.find('li[schedule_inventory_id="' + siid + '"]').attr('price_mn', price); 60347 } 60348 60349 ++foundCount; 60350 lis.eq(i).remove(); 60351 } 60352 } 60353 } 60354 60355 if (quantity > foundCount) { //add line from pos-ticket 60356 var newLis = _openAddLineItem(jlines.eq(l), foundCount); 60357 returnData.find('ul').append(newLis); 60358 } 60359 } 60360 60361 if (dateDiff === 0) { 60362 lis = ul.find('>li'); 60363 60364 for (var i=0; i < lis.length; i++) { 60365 var siid = lis.eq(i).attr('schedule_inventory_id'); 60366 returnData.find('li[schedule_inventory_id="' + siid + '"]').remove(); 60367 _deleteInventoryXml += '<li del_schedule_inventory_id="' + siid + '"/>'; 60368 } 60369 } 60370 60371 return returnData.outerHTML(); 60372 } 60373 60374 function _matchingActiveLine(inventoryId, jtix) { 60375 var activeRows = jtix.find('.pos-product-line-item'); 60376 60377 if (!_isLoading) { 60378 for (var i=0; i < activeRows.length; i++) { 60379 var jrow = activeRows.eq(i); 60380 60381 if (inventoryId === parseInt(jrow.attr('inventory_id')) && !jrow.find('.line-item-amount').prop('readonly')) { //= if gift card # generate is manual then only 1 gift card per row 60382 if (!jrow.hasClass('new-line-item')) { 60383 var lineId = jrow.attr('id'); 60384 var clickCnt = jrow.attr('click_count_nr') + 1; 60385 60386 jrow.addClass('new-line-item'); 60387 jrow.attr('click_count_nr', clickCnt); 60388 60389 setTimeout(function() { 60390 SA.Ticket.addLineEnd(lineId, clickCnt); 60391 }, 1500); 60392 } 60393 60394 return jrow; 60395 } 60396 } 60397 } 60398 60399 return false; 60400 } 60401 60402 function _incrementAmount(jActiveRow) { 60403 var amt = parseInt(jActiveRow.find('.line-item-amount').val()) + 1 60404 jActiveRow.find('.line-item-amount').val(amt); 60405 60406 var clicks = parseInt(jActiveRow.attr('click_count_nr')) + 1; 60407 jActiveRow.attr('click_count_nr', clicks); 60408 60409 _conTicket.recalculate(); 60410 } 60411 60412 function _serviceLineLabel(serviceId, staffId, isFA) { 60413 var svc = SA.POS.getServiceObject(serviceId); 60414 var span = '<span class="line-item-name pos-service-label"'; 60415 60416 if (UTIL.isEmpty(svc)) { 60417 var dsgid = $('#allServiceOptions option[value="' + serviceId + '"]').attr('default_service_group_id'); 60418 var divStart = '<div id="pop-warning-not-pos-ticket">'; 60419 60420 if (dsgid == 9 || dsgid == 1009) { 60421 if (dsgid == 9) { 60422 GLO.Popup.Warning.open(divStart + 'Cannot Process Staff\'s Off Time Ticket in P.O.S.</
60422div>', 'Ticket Not Allowed'); 60423 } else if (dsgid == 9) { 60424 GLO.Popup.Warning.open(divStart + 'Cannot Process Timecard Ticket in P.O.S.</div>', 'Ticket Not Allowed'); 60425 } 60426 60427 setTimeout(function() { 60428 SA.Ticket.hideChangeDue(); 60429 SA.Ticket.reset(); 60430 }, 90); 60431 } else { 60432 var msg = '<p>This Service Not Available in P.O.S.</p>'; 60433 var smid = $('#pos-ticket').attr('schedule_multi_id'); 60434 var day = $('#Ticket_day').val(); //var bkgNumber = _conTicket.bookingNumber; 60435 60436 if (smid > 0 && UTIL.isDate(day)) { 60437 var url = GLO.Link.WebsiteDomain + 'provider/calendar#vw=resourceDay&dt=' + day + '&ticketid=' + smid; 60438 var btn = '<span id="btnViewInCal" class="btnAdd"><a onclick="GLO.Uri.gotoUri(\'' + url + '\', this, event, true)">View in Calendar</a></span>'; 60439 60440 msg += '<p style="text-align: center;">' + btn + '</p>'; 60441 } 60442 60443 var htm = divStart + '<div id="pop-warn-pos-add-service">' + msg + '</div></div>'; 60444 GLO.Popup.Warning.open(htm, 'Service Not Found'); 60445 } 60446 60447 return ''; 60448 } 60449 60450 return span + '><b>' + svc.name + '</b></span>'; 60451 60452 /* if (isFA) { 60453 return span + '><b>' + svc.name + '</b></span>'; 60454 } else { 60455 var staffName = UserPortal.getStaffName(staffId); 60456 60457 if ((staffName + svc.name).length > 25) { 60458 return span + ' title="' + staffName + ' - ' + svc.name + '"><i>' + UTIL.maxString(staffName, 10, true) + '</i><b>' + svc.name + '</b></span>'; 60459 } else { 60460 return span + '><i>' + staffName + '</i><b>' + svc.name + '</b></span>'; 60461 } 60462 } */ 60463 } 60464 _conTicket.addServiceLineAfterAddStaff = function(serviceId) { 60465 if (serviceId > 0) { 60466 var sgid = UserPortal.getServiceGroupId(serviceId); 60467 60468 SA.Ticket.addServiceLine(serviceId, sgid); 60469 SA.Ticket.ticketChanged(); 60470 } 60471 } 60472 _conTicket.addServiceLine = function(serviceId, sgid, staffId, isFA, price, scheduleId) { 60473 serviceId = parseInt(serviceId); 60474 60475 if (UTIL.isEmpty(staffId)) { 60476 var jstaff = $('#btnSelectedStaff > a'); 60477 staffId = jstaff.attr('staff_id'); 60478 isFA = UTIL.parseBool(jstaff.attr('is_first_available_fl')); 60479 60480 if (UTIL.isEmpty(staffId)) { 60481 if (GLO.Data.provider.hasFirstAvailable) { 60482 staffId = UserPortal.getFirstAvailableStaffId(); 60483 isFA = true; 60484 } else { 60485 SA.POS.openSelectStaff(null, serviceId); 60486 return; 60487 } 60488 } 60489 } else { 60490 isFA = UserPortal.isFirstAvailable(staffId); 60491 } 60492 60493 if (UTIL.isEmpty(price)) { 60494 var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true); 60495 price = UserPortal.Booking.parseDefaultPrice(ojDefault["price"]); 60496 } 60497 60498 if (false && UTIL.isEmpty(scheduleId)) { //toDo: implement later 60499 var jtix = $('#pos-ticket-order'); 60500 var activeRow = _matchingActiveServiceLine(serviceId, staffId, jtix); 60501 60502 if (activeRow.length > 0) { 60503 _incrementAmount(activeRow); 60504 _addLineToHeader(); 60505 return; 60506 } 60507 } 60508 60509 var name = _serviceLineLabel(serviceId, staffId, isFA); 60510 return _conTicket.addLine(name, null, serviceId, sgid, 1, price, staffId, isFA, null); 60511 } 60512 _conTicket.addProductLine = function(inventoryId, amount, price) { 60513 amount = UTIL.coalesceMoney(amount, 1); 60514 inventoryId = parseInt(inventoryId); 60515 60516 var jtix = $('#pos-ticket-order'); 60517 60518 if (SA.POS.inventory_json.manual_entry && SA.POS.inventory_json.manual_entry.id === inventoryId) { 60519 var product = null, productName = '<span class="line-item-name">' + SA.Resource.ManualEntry + '</span>'; 60520 60521 if (!UTIL.isNumber(price)) { 60522 price = UTIL.displayMoney($('#pos-enter-product-or-amount').val(), true, false, true); 60523 } 60524 60525 $('#pos-product-header-enter #pos-enter-product-or-amount').val(''); 60526 $('#pos-product-header-enter .btnAction2').addClass('hide'); 60527 } else { 60528 var activeRow = _matchingActiveLine(inventoryId, jtix); 60529 60530 if (activeRow.length > 0) { 60531 _incrementAmount(activeRow); 60532 _addLineToHeader(); 60533 return activeRow; 60534 } 60535 60536 var product = SA.POS.getProductObject(inventoryId); 60537 60538 if (product) { 60539 var productName = UTIL.maxStringHtml(product.label, 25, false, 'span', '', 'line-item-name', ''); 60540 price = UTIL.coalesceMoney(price, product.price_mn); 60541 } else { 60542 var smid = $('#pos-ticket').attr('schedule_multi_id'); 60543 var bkgNumber = _conTicket.bookingNumber;
60544 var msg = 'Tickets with a membership sale or deleted product must be opened as a ticket popup'; 60545 var logMsg = msg + ', inventoryId = ' + inventoryId; 60546 60547 SA.Ticket.clearTicket(); 60548 UserPortal.getTicket(smid, bkgNumber, null, false, null, null, { "openInPopup": true, "processing_message_vc": msg }); 60549 60550 GLO.Log.insertSimple('POS Screen does NOT support Ticket', logMsg, 'warning'); 60551 return; 60552 } 60553 } 60554 60555 return _conTicket.addLine(productName, inventoryId, null, null, amount, price, null, null, product); 60556 } 60557 function _getLineId(jtix) { 60558 var jlines = jtix.find('.pos-ticket-line-item'); 60559 var maxNumber = 0; 60560 60561 for (var i = jlines.length - 1; i >= 0; i--) { 60562 var test = parseInt(jlines.eq(i).attr('id').replace('pos-line-', '')); 60563 60564 if (test > maxNumber) { 60565 maxNumber = test; 60566 } 60567 } 60568 60569 return 'pos-line-' + (maxNumber + 1); 60570 } 60571 _conTicket.addLine = function(name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox) { 60572 _conTicket.hideChangeDue(); 60573 60574 var jtix = $('#pos-ticket-order'); 60575 var lineId = _getLineId(jtix); 60576 var ln = _lineHtm(lineId, name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox); 60577 60578 ln = _addLineToPage(jtix, ln, lineId, staffId); 60579 60580 if (!GLO.Info.isMobile(true) && UTIL.coalesceMoney(price) === 0) { 60581 ln.find('.line-item-price').focus(); 60582 } else if (!GLO.Info.isMobile() && jtix[0].scrollHeight > jtix[0].clientHeight) { 60583 UI.scrollToElement(jtix, ln); 60584 } 60585 60586 $("#pos-product-header-enter").removeClass('is-numeric'); 60587 60588 _conTicket.recalculate(); 60589 _addLineToHeader(); 60590 _finishAddProductOrService(); 60591 _conTicket.enableOrDisableTicketScroll(); 60592 60593 if (_isLoading) { 60594 ln.removeClass('new-line-item'); 60595 } else { 60596 setTimeout(function() { 60597 SA.Ticket.addLineEnd(lineId, 1); 60598 }, 1500); 60599 60600 _addGiftCardToTicket(ln, productBox); 60601 } 60602 60603 return ln; 60604 } 60605 function _addLineToPage(jtix, ln, lineId, staffId) { 60606 var jline = $(ln); 60607 60608 if (jline.hasClass('pos-service-line-item')) { 60609 var staffRow = _conTicket.getStaffTicketLastRow(jtix, staffId, jline); 60610 staffRow.after(ln); 60611 } else { 60612 jtix.append(ln); 60613 } 60614 60615 ln = jtix.find('#' + lineId); //.new-line-item:last 60616 ln.find('.pos-service-label').click(SA.POS.openSelectStaff); 60617 return ln; 60618 } 60619 _conTicket.getStaffTicketLastRow = function(jtix, staffId, jline) { //= get staff row (if no staff row -> add it) 60620 var rowStaff = jtix.find('.pos-staff-line-item[staff_id="' + staffId + '"]'); 60621 60622 if (rowStaff.length === 0) { 60623 if (staffId > 0) { 60624 var staffName = UserPortal.getStaffName(staffId); 60625 var rowId = 'staff-row-' + staffId; 60626 var htmLabel = '<span class="pos-staff-label">' + staffName + '</span>'; 60627 var htm = '<div id="' + rowId + '" staff_id="' + staffId + '" class="pos-staff-line-item">' + htmLabel + '</div>'; 60628 var trsvc = jtix.find('.pos-service-line-item:last'); 60629 var isClientRequest = 0, tip = UTIL.coalesceMoney(jline.attr('tip_mn')); 60630 60631 if (trsvc.length) { 60632 trsvc.after(htm); 60633 } else { 60634 jtix.append(htm); 60635 } 60636 60637 rowStaff = jtix.find('#' + rowId); 60638 rowStaff.find('.pos-staff-label').click(SA.POS.openSelectStaff); 60639 60640 if (staffId = jline.attr('staff_id')) { 60641 var isClientRequest = UTIL.parseBool(jline.attr('client_request_fl')); 60642 } 60643 60644 _setStaffHeader2(jtix, staffId, tip, isClientRequest); 60645 return rowStaff; 60646 } else { 60647 return jtix.find('.pos-service-line-item:last'); 60648 } 60649 } else { 60650 return jtix.find('.pos-service-line-item[staff_id="' + staffId + '"]:last'); 60651 } 60652 } 60653 function _addGiftCardToTicket(ln, productBox) { 60654 if (GLO.Data.provider.gift_card_generate_cd == 20 && productBox && UTIL.parseBool(productBox.is_gift_card_fl)) { 60655 var gcnr = UTIL.cleanString(ln.attr('gift_number_vc')); 60656 60657 if (UTIL.isEmpty(gcnr)) { 60658 var gcid = ln.attr('gift_card_id'); 60659 var gcmn = ln.find('.line-item-price'); 60660 60661 ln.find('.line-item-amount').prop('readonly', true); 60662 UserPortal.Price.GiftCard.openEdit(gcid, gcnr, gcmn); 60663 } 60664 } 60665 } 60666 _conTicket.getIsClientRequest = function(staffId) { 60667 for (var s=0; s < _serviceXml.length; s++) { 60668 if (staffId == _serviceXml.eq(s).attr('staff_id')) { 60669 if (UTIL.parseBool(_serviceXml.eq(s).attr('client_request_fl'))) { 60670 return true; 60671 } 60672 } 60673 } 60674 60675 return false; 60676 } 60677 function _lineHtm(lineId, name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox) { 60678 var divAttributes = 'id="' + lineId + '"'; 60679 var numberInputType = "text", cssClass = ''; 60680 60681 if (!UTIL.isEmpty(inventoryId)) { 60682 divAttributes += ' inventory_id="' + inventoryId + '"'; 60683 cssClass = ' pos-product-line-item'; 60684 } else if (!UTIL.isEmpty(serviceId)) { 60685 divAttributes += ' service_id="' + serviceId + '" service_group_id="' + sgid + '"'; 60686 cssClass = ' pos-service-line-item'; 60687 } else { 60688 var warnMsg = '_lineHtm(' + name + ', ' + price + ', ' + staffId + ')'; 60689 GLO.Log.insertSimple(warnMsg, JSON.stringify(productBox), 'warning'); 60690 } 60691
60692 if (!UTIL.isEmpty(staffId)) { 60693 divAttributes += ' staff_id="' + staffId + '"'; 60694 60695 if (!isFA &&_conTicket.getIsClientRequest(staffId)) { 60696 divAttributes += ' client_request_fl="1"'; 60697 } 60698 } 60699 60700 if (isFA) { divAttributes += ' is_first_available_fl="1"'; } 60701 60702 if (productBox) { 60703 if (!UTIL.isEmpty(productBox.tax_rate_pct)) { 60704 divAttributes += ' custom_tax_rate_pct="' + productBox.tax_rate_pct + '"'; 60705 } 60706 60707 if (UTIL.parseBool(productBox.is_gift_card_fl)) { 60708 divAttributes += ' is_gift_card_fl="1"'; 60709 } 60710 } 60711 60712 if (GLO.Info.isAndroid) { numberInputType = "number"; } 60713 60714 price = UTIL.displayMoney(price, true, false, true); 60715 60716 return '<div ' + divAttributes + ' class="pos-ticket-line-item new-line-item' + cssClass + '" click_count_nr="1">' 60717 + '<span class="ticket-row-remove" onclick="SA.Ticket.removeLine(this)"> <span class="ui-icon ui-icon-circle-close"></span> </span>' 60718 + name 60719 + '<input type="' + numberInputType + '" class="line-item-amount" pattern="[0-9]*" maxlength="2" onkeypress="UI.numberOnly(event)" onkeyup="SA.Ticket.changeAmount(this)" value="' + amount + '">' 60720 + '<span class="dollar-sign">$</span>' 60721 + '<input type="' + numberInputType + '" class="line-item-price" pattern="[0-9]*" maxlength="9" onkeypress="UI.numberOnly(event)" onkeyup="SA.Ticket.changePrice(this)" onclick="SA.Ticket.clickPrice(this)" value="' + price + '">' 60722 + '</div>'; 60723 } 60724 60725 function _addLineToHeader() { 60726 clearTimeout(_addLineToHeaderTimeout); 60727 60728 var total = $('#pos-ticket-total-box > b').text(); 60729 var header = $('#header-ticket-info').addClass('lineAdded'); 60730 $('#header-ticket-total').text(total); 60731 60732 _addLineToHeaderTimeout = setTimeout(function() { 60733 $('#header-ticket-info').removeClass('lineAdded'); 60734 }, 400); 60735 } 60736 60737 _conTicket.addLineEnd = function(id, clickCnt) { 60738 var ln = $('#pos-ticket-order #' + id); 60739 var actualClicks = parseInt(ln.attr('click_count_nr'));
60740 60741 if (actualClicks === clickCnt) { 60742 ln.removeClass('new-line-item'); 60743 } else if (ln.length > 0) { 60744 setTimeout(function() { 60745 SA.Ticket.addLineEnd(id, actualClicks); 60746 }, 900); 60747 } 60748 } 60749 60750 _conTicket.hasUnsavedChange = function() { 60751 return $('#pos-ticket #btnSaveTicket').find('>a').hasClass('unsaved-change'); 60752 } 60753 _conTicket.ticketChanged = function() { 60754 $('#pos-ticket #btnSaveTicket').find('>a').addClass('unsaved-change'); 60755 60756 SA.Ticket.adjustMultiTicketTotal(); 60757 SA.Ticket.applyDiscounts(null, true); 60758 } 60759 _conTicket.ticketSaved = function(smid) { 60760 $('#pos-ticket #btnSaveTicket').find('>a').removeClass('unsaved-change'); 60761 //$('#pos-ticket').attr('schedule_multi_id', smid); 60762 } 60763 60764 function _setDeleteXml(row) { 60765 if (row.hasClass('pos-service-line-item')) { 60766 var scheduleId = row.attr('schedule_id'); 60767 60768 if (!UTIL.isEmpty(scheduleId)) { 60769 if (!UTIL.isEmpty(_deleteScheduleIds)) { 60770 _deleteScheduleIds += ',' + scheduleId; 60771 } else { 60772 _deleteScheduleIds = scheduleId; 60773 } 60774 } 60775 } else { 60776 var siids = UTIL.cleanString(row.attr('schedule_inventory_ids')).split(','); 60777 60778 for (var i=0; i < siids.length; i++) { 60779 if (!UTIL.isEmpty(siids[i])) { 60780 _deleteInventoryXml += '<li del_schedule_inventory_id="' + siids[i] + '"/>'; 60781 } 60782 } 60783 } 60784 } 60785 60786 _conTicket.getClientLoyaltyPoints = function() { 60787 return UTIL.coalesceInt(_clientLoyalty, 0); 60788 } 60789 60790 _conTicket.viewClientProfile = function(clientId, clientName) { 60791 if (!UTIL.isNumber(clientId)) { 60792 clientId = _conTicket.clientId; 60793 clientName = _conTicket.clientName; 60794 } 60795 60796 GLO.Popup.closeIfExist($('#pop-ticket-client-view').closest('.glopop')); 60797 GLO.Popup.closeIfExist($('#pop-edit-client-tag').closest('.glopop')); 60798 60799 ClientProfile.goto(clientId, 1, UTIL.replaceQuotes(clientName)); 60800 } 60801 _conTicket.addClientView = function() { 60802 var btnView = '<span class="btnAdd"><a onclick="SA.Ticket.viewClientProfile()">View Profile</a></span>'; 60803 var btnChange = '<span class="btnAdd"><a onclick="SA.Ticket.addClient(true)">Change Client</a></span>'; 60804 var htm = '<p style="margin: 8px; margin-left: 12px;">' + _conTicket.clientName + '</p>' + btnView + btnChange; 60805 var jpop = GLO.Popup.Custom.openSimple('<div id="pop-ticket-client-view">' + htm + '</div>', 'Client'); 60806 GLO.Popup.Custom.singleButton(jpop, 'Close'); 60807 } 60808 _conTicket.addClient = function(isForce) { 60809 var jbtn = $('#pos-add-client-button'); 60810 60811 if (!isForce && !UTIL.isEmpty(_conTicket.clientId)) { 60812 SA.Ticket.viewClientProfile(); //_conTicket.addClientView(); 60813 return; 60814 } 60815 60816 GLO.Popup.closeIfExist($('#pop-ticket-client-view').closest('.glopop')); 60817 60818 var h1 = 'Enter Client Name or Phone Number'; 60819 var htm = null, cssStyle = null; 60820 var uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1'; 60821 var jclient = jbtn.find('input'); 60822 60823 var jkeypad = UI.Keypad.openKeypadCharacter(h1, htm, jclient, cssStyle, false, SA.Ticket.addClientNewOpen, true).addClass('sa-keypad-name'); 60824 var jinput = jkeypad.find('input.sa-keypad'); 60825 60826 UI.initAutoComplete(jinput, uriClientSearch, UserPortal.importClientOpen, SA.Ticket.addClientSelected); 60827 60828 /* tried to set cursor to end, but didn't work 60829 setTimeout(function() { 60830 var input = jclient[0]; 60831 input.selectionStart = input.selectionEnd = input.value.length; 60832 }, 4500); 60833 60834 jinput.focus(function() { 60835 var that = this; 60836 60837 setTimeout(function() { 60838 that.selectionStart = that.selectionEnd = 10000; 60839 }, 0); 60840 }); */ 60841 } 60842 60843 function _getNoteLabel(cssClass, tagCount) { //cssClass: appt-request, appt-staff-only, client-important-note, client-tag, client-tag-appt 60844 if (cssClass == 'appt-request') { 60845 var label = 'Appointment Request' 60846 } else if (cssClass == 'appt-staff-only') { 60847 var label = 'Appointment Staff Only' 60848 } else if (cssClass == 'client-important-note') { 60849 var label = 'Important Note' 60850 } else if (cssClass == 'client-tag') { 60851 var label = UTIL.pluralLabel(tagCount, 'Client Tag'); 60852 } else { 60853 return ''; 60854 } 60855 60856 return '<b class="client-note-label">' + label + '</b>'; 60857 } 60858 60859 _conTicket.loadClientNote = function(cssClass, note, tagCount) { 60860 var htmLabel = _getNoteLabel(cssClass, tagCount); 60861 var htmNote = '<span class="client-note">' + note + '</span>'; 60862 var htm = '<div class="client-note-row ' + cssClass + '">' + htmLabel + htmNote + '</div>'; 60863 var jca = $('#pos-ticket-client-attributes').removeClass('hide'); 60864 60865 jca.find('.' + cssClass).html(''); 60866 60867 if (cssClass == 'client-tag' || cssClass == 'client-tag-appt' || cssClass == 'client-birthday' || cssClass == 'client-loyalty' || cssClass == 'client-gift') { 60868 jca.prepend(htm); 60869 } else { 60870 jca.append(htm); 60871 } 60872 60873 var rowCount = jca.find('.client-note-row').length; 60874 $('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4').addClass('client-note' + rowCount); 60875 } 60876 _conTicket.removeClient = function(smid, clientId, fnYes) { 60877 var jservices = $('#pos-ticket').find('.pos-ticket-line-item.pos-service-line-item'); 60878 60879 if (jservices.length) { 60880 UserPortal.Edit.removeClient(smid, clientId, fnYes); 60881 } else { 60882 UserPortal.Price.removeClient(smid, clientId, fnYes); 60883 } 60884 } 60885 60886 _conTicket.clientReset = function() { 60887 _clientTagXml = _clientTagRelationshipXml = null; 60888 _conTicket.clientId = _conTicket.clientName = _conTicket.clientType = null; 60889 _clientLoyalty = _availableLoyalty = _referralDiscount = 0; 60890 60891 _cftid = _membershipId = _birthDays = null; 60892 _giftBalance = 0; 60893 _providerReferral = null; 60894 60895 _resetClientAttributes(true); 60896 _setClientName(); 60897 } 60898 60899 _conTicket.addClientReset = function(clientNameOrPhone) { 60900 var jbtn = $('#pos-add-client-button'); 60901 var isNewClient = UTIL.isEmpty(clientNameOrPhone); 60902 60903 clientNameOrPhone = UTIL.coalesceString(clientNameOrPhone, jbtn.find('input').val()); 60904 60905 var smid = $.trim($('#pos-ticket').attr('schedule_multi_id')); 60906 var clientId = _conTicket.clientId; 60907
60908 if (!UTIL.isEmpty(smid)) { 60909 _setClientName(); 60910 _conTicket.removeClient(smid, clientId, SA.Ticket.clientReset); 60911 } else { 60912 _conTicket.clientReset(); 60913 } 60914 60915 return isNewClient; 60916 } 60917 _conTicket.addClientSelected = function(element, event, ui) { 60918 $('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4'); 60919 $('#pos-ticket-client-attributes').html('').addClass('hide'); //.find('.client-note-row').remove() 60920 60921 /* if (GLO.Data && GLO.Data.provider && UTIL.coalesceInt(ui.item.provider_id, GLO.Data.provider.id) != GLO.Data.provider.id) { 60922 UserPortal.importClientOpen(jclient, event, ui); 60923 return; 60924 } */ 60925 60926 if (!UTIL.isEmpty(ui.item.smid)) { 60927 UserPortal.Create.Checkout.openEdit(element, event, ui); 60928 } else { 60929 var clientId = ui.item.id; 60930 var clientName = ui.item.value; //ui.item.label 60931 var ctype = ui.item.client_type_cd; 60932 60933 _conTicket.addClientCompleteFromAutoComplete(clientId, clientName, ctype, ui.item); 60934 } 60935 60936 GLO.Popup.closeIfExist($('#pop-sa-keypad').closest('.glopop')); 60937 60938 if ($('#pos-container').hasClass('display-staff-screen')) { 60939 _conTicket.displayTicket(); 60940 $('#pos-staff-list-client').val(''); 60941 60942 setTimeout(function() { //= necessary since delay in auto-complete populating input box 60943 $('#pos-staff-list-client').val('').removeAttr('autoid').removeAttr('autoname'); 60944 }, 500); 60945 } 60946 } 60947 _conTicket.addClientNewOpen = function() { 60948 var clientNameOrPhone = $('#pos-add-client-button').find('input').val(); 60949 60950 if (SA.Ticket.addClientReset(clientNameOrPhone)) { 60951 return; 60952 } 60953 60954 var clientResult = UTIL.getNameAndPhone(clientNameOrPhone); 60955 _conTicket.addClientNewOpen2(clientResult); 60956 } 60957 _conTicket.addClientNewOpen2 = function(clientResult) { 60958 GLO.ClientProfile.openSimpleAdd(); 60959 var jpop = $('#simple-addclient').closest('.glopop'); 60960 //var clientResult = UTIL.getNameAndPhone(clientNameOrPhone); 60961 60962 if (clientResult || clientResult.phone) { 60963 if (UTIL.Validate.phone(clientResult.phone)) { 60964 jpop.find('#Mobile_Phone_vc').val(clientResult.phone).blur(); 60965 60966 if (clientResult.hasNameAndPhone) { 60967 jpop.find('#Client_Name_vc').val(clientResult.name); 60968 } 60969 } else { 60970 jpop.find('#Client_Name_vc').val(clientResult.text); 60971 } 60972 } 60973 } 60974 _conTicket.addClientLoad = function(clientId, clientName, jdata) { //called when client imported from another location by auto-complete 60975 var ctype = jdata.attr('client_type_cd'); 60976 var hasNote = jdata.attr('has_note_fl'); 60977 60978 var cftid = jdata.attr('cftid'); 60979 var membershipId = jdata.attr('membership_id'); 60980 var giftBalance = jdata.attr('gift_balance_mn'); 60981 var clientLoyalty = jdata.attr('client_loyalty_sr'); 60982 var tagCount = jdata.attr('tag_count_sr'); 60983 var birthDays = jdata.attr('birth_sr'); 60984 var referId = jdata.attr('provider_referral_id'); 60985 60986 _conTicket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId); 60987 } 60988 _conTicket.addClientFromPos = function(clientId, clientName, email, mobile, isNewUser, isOutcall) { 60989 if (UTIL.parseBool(isNewUser)) { 60990 var ctype = 1; 60991 } else { 60992 var ctype = 2; 60993 } 60994 60995 _conTicket.addClientComplete(clientId, clientName, ctype); 60996 _displayClientAttributes(); 60997 60998 if ($('#pos-container').hasClass('display-staff-screen')) { 60999 _conTicket.displayTicket(); 61000 $('#pos-staff-list-client').val(''); 61001 61002 setTimeout(function() { //= necessary since delay in auto-complete populating input box 61003 $('#pos-staff-list-client').val(''); 61004 }, 500); 61005 } 61006 } 61007 _conTicket.addClientCompleteFromAutoComplete = function(clientId, clientName, ctype, uiItem) { 61008 if (uiItem) { 61009 ctype = UTIL.coalesce(ctype, uiItem.client_type_cd); 61010 var hasNote = uiItem.has_note_fl; 61011 61012 var cftid = uiItem.cftid; 61013 var membershipId = uiItem.membership_id; 61014 var giftBalance = uiItem.gift_balance_mn; 61015 61016 var clientLoyalty = uiItem.loyalty_points_nr; 61017 var tagCount = uiItem.tag_count_sr; 61018 var birthDays = uiItem.birth_sr; 61019 var referId = uiItem.provider_referral_id; 61020 } else { 61021 ctype = UTIL.coalesce(ctype, 1); 61022 var hasNote = false, cftid = null, membershipId = null, giftBalance = null, clientLoyalty = null, tagCount = null, birthDays = null, referId = null; 61023 } 61024 61025 _conTicket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId); 61026 _displayClientAttributes(); 61027 } 61028 _conTicket.addClientComplete = function(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId) { 61029 clientName = $.trim(clientName); 61030 61031 _conTicket.clientName = clientName; 61032 _conTicket.clientId = $.trim(clientId); 61033 _conTicket.clientType = $.trim(ctype); 61034 61035 _clientLoyalty = $.trim(clientLoyalty); 61036 _ticketLoyalty = _availableLoyalty = 0; 61037 61038 _cftid = $.trim(cftid); 61039 _membershipId = $.trim(membershipId); 61040 _giftBalance = $.trim(giftBalance); 61041 _birthDays = $.trim(birthDays); 61042 _providerReferral = referId; 61043 61044 if (!_isLoading) { 61045 _clientTagXml = _clientTagRelationshipXml = null; 61046 _referralDiscount = 0; 61047 } 61048 61049 _addClientComplete2(hasNote, tagCount); 61050 } 61051 61052 function _setClientName() { 61053 var clientName = _conTicket.clientName; 61054 61055 //if (innerWidth < 1240) { clientName = UTIL.maxString(clientName, 24, true); } 61056 61057 if (!UTIL.isEmpty(clientName)) {
61058 var jticket = $('#pos-ticket').addClass('has-client'); 61059 jticket.find('#pos-add-client-button').attr('title', _conTicket.clientName).find('input').val(clientName); 61060 } else { 61061 var jticket = $('#pos-ticket').removeClass('has-client'); 61062 jticket.find('#pos-add-client-button').removeAttr('title').find('input').val(''); 61063 } 61064 } 61065 function _addClientComplete2(hasNote, tagCount) { 61066 _setClientName(); 61067 61068 if (UTIL.parseBool(hasNote)) { 61069 UserPortal.displayIfClientHasStaffNote(_conTicket.clientId, true); 61070 } 61071 61072 if (tagCount > 0 && (UTIL.isEmpty(_clientTagXml) || _clientTagXml.length === 0)) { 61073 UserPortal.lookupClientTags(_conTicket.clientId); 61074 } 61075 61076 if (!_isLoading && !UTIL.isEmpty(_conTicket.clientName)) { 61077 SA.Ticket.applyDiscounts(null, true); 61078 } 61079 } 61080 61081 _conTicket.addClientAttributesToJson = function(json) { 61082 json.client_loyalty_nr = _clientLoyalty; 61083 json.available_loyalty_nr = _availableLoyalty; 61084 61085 json.membership_id = _membershipId; 61086 json.birth_sr = _birthDays; 61087 } 61088 61089 _conTicket.clearDeleteInventoryXml = function(smid) { 61090 //var smid = UTIL.cleanString($('#appt-price-popup').closest('.glopop').find('#price-header').attr('schedule_multi_id')); 61091 61092 if (!_openTicketMatchesPOS(smid)) { return; } 61093 61094 _deleteInventoryXml = ''; 61095 } 61096 61097 _conTicket.getDeleteInventoryXml = function(priceDeleteXml) { 61098 var smid = UTIL.cleanString($('#appt-price-popup').closest('.glopop').find('#price-header').attr('schedule_multi_id')); 61099 61100 if (!_openTicketMatchesPOS(smid)) { return; } 61101 61102 var li = $('<ul>' + priceDeleteXml + '</ul>').find('li'); 61103 var posli = $('<ul>' + _deleteInventoryXml + '</ul>').find('li'); 61104 61105 for (var p=0; p < posli.length; p++) { 61106 var siid = posli.eq(p).attr('del_schedule_inventory_id'); 61107 61108 for (var i=0; i < li.length; i++) { 61109 if (siid == li.eq(i).attr('del_schedule_inventory_id')) { 61110 siid = null; 61111 } 61112 } 61113 61114 if (siid !== null) { 61115 priceDeleteXml += '<li del_schedule_inventory_id="' + siid + '"/>'; 61116 } 61117 } 61118 61119 return priceDeleteXml; 61120 } 61121 61122 _conTicket.removeLine = function(element) { 61123 if (!element) { element = this; } 61124 61125 var row = $(element).closest('.pos-ticket-line-item'); 61126 var staffId = row.attr('staff_id'); 61127 var jticket = $('#pos-ticket-order'); 61128 61129 _setDeleteXml(row); 61130 row.remove(); 61131 61132 if (jticket.find('.pos-service-line-item[staff_id="' + staffId + '"]').length === 0) { 61133 jticket.find('#staff-row-' + staffId).remove(); 61134 } 61135 61136 _conTicket.recalculate(); 61137 _conTicket.ticketChanged(); 61138 _finishAddProductOrService(); 61139 61140 _conTicket.setStaffHeader(); 61141 _conTicket.enableOrDisableTicketScroll() 61142 } 61143 61144 _conTicket.enableOrDisableTicketScroll = function() { 61145 var jtix = $('#pos-ticket-order'); 61146 var lineCount = jtix.find('.pos-ticket-line-item').length; 61147 var staffCount = jtix.find('.pos-staff-line-item').length; 61148 var productLabel = jtix.find('#pos-product-label-row').length; 61149 var allowedLines = parseInt(jtix.height()/40) - 1; //"-1" just to be extra safe 61150 61151 if (jtix.hasClass('scroll-active')) { 61152 if (lineCount + staffCount + productLabel < allowedLines) { 61153 jtix.removeClass('scroll-active'); 61154 } 61155 } else { 61156 if (lineCount + staffCount + productLabel >= allowedLines) { 61157 jtix.addClass('scroll-active'); 61158 } 61159 } 61160 } 61161 61162 _conTicket.changeAmount = function(element) { 61163 _conTicket.recalculate(); 61164 _conTicket.ticketChanged(); 61165 } 61166 _conTicket.changePrice = function(element) { 61167 _conTicket.recalculate(); 61168 _conTicket.ticketChanged(); 61169 } 61170 _conTicket.clickPrice = function(element) { 61171 element.select(); 61172 61173 if (UI.Keypad.isButtonBased()) { 61174 UI.Keypad.openKeypadPrice(element); 61175 } 61176 } 61177 61178 _conTicket.recalculate = function() { 61179 if (_isLoading) { return; } 61180 61181 var jtix = $('#pos-ticket'); 61182 var lns = jtix.find('.pos-ticket-line-item'); 61183 var hasCheckout = UserPortal.Price.isTicketHasCheckout(); 61184 var totalDiscount = 0, totalFee = 0, sub = 0, totalTax = 0, totalTip = 0; 61185 61186 for (var i=0; i < lns.length; i++) { 61187 var jline = lns.eq(i); 61188 var lineTotal = UTIL.coalesceMoney(jline.find('.line-item-amount').val() * UTIL.coalesceMoney(jline.find('.line-item-price').val())); 61189 var tip = UTIL.coalesceMoney(jline.attr('tip_mn')); 61190 var addOnFee = UTIL.coalesceMoney(jline.attr('add_on_fee_mn')); 61191 var discount = UTIL.coalesceMoney(jline.attr('new_discount_mn'), jline.attr('discount_mn')); 61192 var tax = _getLineItemTax(jline, hasCheckout, lineTotal, discount); 61193 61194 sub += lineTotal; 61195 totalDiscount = UTIL.coalesceMoney(discount + totalDiscount); 61196 totalFee = UTIL.coalesceMoney(addOnFee + totalFee); 61197 totalTax = UTIL.coalesceMoney(tax + totalTax); 61198 totalTip = UTIL.coalesceMoney(tip + totalTip); 61199 } 61200 61201 var totalRow = jtix.find('#pos-ticket-total-line'); 61202 var totalCell = totalRow.find('#pos-ticket-total-box b'); 61203 var jdiscount = totalRow.find('#pos-ticket-total-discount'); 61204 61205 var totalDiscount = UTIL.coalesceMoney(jdiscount.find('#pos-ticket-discount-amount').text().replace('$', '')); 61206 var totalAddOnFee = UTIL.coalesceMoney(jdiscount.find('#pos-ticket-add-on-fee-amount').text().replace('$', '')); 61207 var total = UTIL.displayMoney(UTIL.coalesceMoney(sub) + totalTax - totalDiscount + totalAddOnFee + totalTip, false, false, true); 61208 61209 totalRow.find('#pos-ticket-total-sub b').html(UTIL.displayMoney(sub, false, false, true)); 61210 totalRow.find('#pos-ticket-total-tax b').html(UTIL.displayMoney(totalTax, false, false, true)); //if (tax > 0 && !hasCheckout) { 61211 totalRow.find('#pos-ticket-total-tip b').html(UTIL.displayMoney(totalTip, false, false, true)); 61212 61213 if (totalTip == 0 && totalTax > 0) { 61214 totalRow.find('#pos-ticket-total-tip').addClass('hide'); 61215 totalRow.find('#pos-ticket-total-tax').removeClass('hide'); 61216 } else { 61217 totalRow.find('#pos-ticket-total-tax').addClass('hide'); 61218 totalRow.find('#pos-ticket-total-tip').removeClass('hide'); 61219 } 61220 61221 totalCell.html(total); 61222 //totalRow.find('.total-tip').html(''); 61223 61224 _styleTotalCell(totalCell); 61225 } 61226 61227 function _getLineItemTax(jline, hasCheckout, lineTotal, discount) { 61228 if (hasCheckout) { 61229 return UTIL.coalesceMoney(jline.attr('tax_mn')); 61230 } else { 61231 var customTaxRate = jline.attr('custom_tax_rate_pct'); 61232 61233 if (jline.hasClass('pos-service-line-item')) { 61234 itemTaxRate = UTIL.coalesceFloat(customTaxRate, GLO.serviceTax, 0)/100; 61235 } else { 61236 itemTaxRate = UTIL.coalesceFloat(customTaxRate, GLO.inventoryTax, 0)/100; 61237 } 61238 61239 if (itemTaxRate > 0) { 61240 return UTIL.coalesceMoney(itemTaxRate * (lineTotal - discount)); 61241 } 61242 } 61243 61244 return 0; 61245 } 61246 61247 function _styleTotalCell(jcell) { 61248 if (innerWidth > 1680) { return; } 61249 61250 var totalLen = jcell.text().length; 61251 61252 if (totalLen < 4) { 61253 var css = { "margin-top": "-4px", "font-size": "30px" }; 61254 } else if (totalLen < 6) { 61255 var css = { "font-size": "28px" }; 61256 } else if (totalLen < 8) { 61257 var css = { "margin-top": "2px", "font-size": "24px" }; 61258 } else if (totalLen < 10) { 61259 var css = { "margin-top": "4px", "font-size": "20px" }; 61260 } else if (totalLen < 11) { 61261 var css = { "margin-top": "6px", "font-size": "16px" }; 61262 } else if (totalLen < 12) { 61263 var css = { "margin-top": "8px", "font-size": "14px" }; 61264 } else { 61265 var css = { "margin-top": "8px", "letter-spacing": "0", "font-size": "13px" }; 61266 } 61267 61268 jcell.css(css); 61269 SA.Ticket.adjustMultiTicketTotal(); 61270 } 61271 61272 _conTicket.processSave = function(jPricePop) { //= when ticket opened by price.get from a save --> if matches POS ticket merge siid(s). 61273 var lis = $('<ul>' + UserPortal.Price.inventoryXml + '</ul>').find('li'); 61274 var jticket = $('#pos-ticket'); 61275 var jlines = jticket.find('.pos-ticket-line-item'); 61276 var smidPOS = jticket.attr('schedule_multi_id'); 61277 var smidPopup = jPricePop.find('#price-header').attr('schedule_multi_id'); 61278 var iid, siid, line; 61279 61280 if (lis.length === 0 || jlines.length === 0) { return; } 61281 if (smidPOS != smidPopup) { return; } 61282 61283 for (var i=0; i < lis.length; i++) { 61284 iid = UTIL.cleanString(lis.eq(i).attr('inventory_id')); 61285 siid = UTIL.cleanString(lis.eq(i).attr('schedule_inventory_id')); 61286 line = _findLineByInventoryId(jlines, iid); 61287 61288 if (line !== null) { 61289 _addToLine(line, siid); 61290 } else { 61291 _conTicket.addProductLine(iid); 61292 } 61293 } 61294 61295 _conTicket.recalculate(); 61296 } 61297 61298 function _addToLine(line, siid, iid) { 61299 var siids = UTIL.cleanString(line.attr('schedule_inventory_ids')) 61300 var arr = siids.split(','); 61301 var amt = UTIL.coalesceInt(line.find('.line-item-amount').val(), 0); 61302 61303 if (UTIL.isEmpty(siids)) { 61304 if (amt === 0) { 61305 return; 61306 } else { 61307 line.attr('schedule_inventory_id', siid); 61308 return true; 61309 } 61310 } 61311 61312 for (var i=0; i < arr.length; i++) { 61313 if (arr[i] == siid) { 61314 return false; 61315 } 61316 } 61317 61318 if (!UTIL.isEmpty(siids)) { siids += ',' + siid; } 61319 line.attr('schedule_inventory_id', siids); 61320 return true; 61321 } 61322 61323 function _findLineByInventoryId(jlines, iid) { 61324 for (var i=0; i < jlines.length; i++) { 61325 if (jlines.eq(i).attr('inventory_id') == iid) { 61326 return jlines.eq(i); 61327 } 61328 } 61329 61330 return null; 61331 } 61332 61333 _conTicket.hideChangeDue = function() { 61334 $('#pos-ticket-change-due').removeClass('display').text(''); 61335 } 61336 61337 _conTicket.openKeypad = function(amountInCents) { 61338 if (GLO.isPOS && GLO.Sale.Keypad.isIncludeTax()) { 61339 GLO.Sale.Keypad.includeTax();
61340 } 61341 61342 GLO.Sale.Keypad.openAsPopup(); 61343 61344 var li = '<li id=""> <span class="btnAdd" onclick="SA.Ticket.processKeypadAmount()"> <a>Complete Payment</a> </span> </li>'; 61345 61346 var jkeypad = $('#sale-keyboard').closest('#simplemodal-container'); 61347 jkeypad.find('#sale-keyboard-options').addClass('keypad-single-button').html(li); 61348 61349 if (innerWidth < 1400) { 61350 setTimeout(function() { 61351 jkeypad.css({ "top": "16px", "left": "inherit", "right": "14px" }); 61352 }, 80); 61353 } 61354 61355 if (amountInCents > 0) { 61356 var jtotal = $('#keyboard-running-total'); 61357 var amt = String(amountInCents); 61358 var len = amt.length; 61359 61360 if (parseInt(amountInCents) > 99) { 61361 amt = amt.substring(0, len-2) + '.' + amt.substring(len-2); 61362 } else if (amountInCents > 9) { 61363 amt = '.' + amt; 61364 } else { 61365 amt = '.0' + amt; 61366 } 61367 61368 jtotal.text('$' + amt); 61369 } 61370 } 61371 61372 _conTicket.processKeypadAmount = function() { 61373 var jmodal = $('#sale-keyboard').closest('#simplemodal-container'); 61374 var price = jmodal.find('#keyboard-running-total').text().replace('$', ''); 61375 var jproducts = $('#pos-ticket').find('.pos-ticket-line-item'); 61376 61377 if (jproducts.length === 0) { 61378 SA.Ticket.addProductLine(SA.POS.inventory_json.manual_entry.id, 1, price); 61379 } 61380 61381 $.modal.close(); 61382 SA.Ticket.openTicket(null, 1, price); 61383 } 61384 61385 _conTicket.openCashPayment = function(btn, amount) { 61386 var json = { "open_keypad_if_no_ticket": true }; 61387 61388 _conTicket.openTicket(btn, 1, amount, null, null, json); 61389 } 61390 61391 function _getTicketServiceById(jservices, scheduleId) { 61392 if (UTIL.isEmpty(scheduleId)) { 61393 return null; 61394 } 61395 61396 for (var i=0; i < jservices.length; i++) { 61397 if (scheduleId == jservices.eq(i).attr('schedule_id')) { 61398 return jservices.eq(i); 61399 } 61400 } 61401 61402 return null; 61403 } 61404 function _getServiceXml(jservices, isCheckout) { 61405 var xml = '', prevServiceId = null, serviceCount = jservices.length; 61406 var arrUniqueStaff = []; 61407 61408 for (var a=0; a < _serviceXml.length; a++) { 61409 var svcXml = _serviceXml.eq(a); 61410 var scheduleId = svcXml.attr('schedule_id'); 61411 var jsvc = _getTicketServiceById(jservices, scheduleId); 61412 61413 if (jsvc && jsvc.length) { //= if not found could add check to verify is in _deleteScheduleIds 61414 if (a > 0) { 61415 prevServiceId = _serviceXml.eq(a-1).attr('service_id'); 61416 } 61417 61418 xml += _getServiceXmlRow(svcXml, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId); 61419 } 61420 } 61421 61422 for (var b=0; b < jservices.length; b++) { 61423 var jsvc = jservices.eq(b); 61424 61425 if (UTIL.isEmpty(jsvc.attr('schedule_id'))) { 61426 if (b > 0) { 61427 prevServiceId = jservices.eq(b-1).attr('service_id'); 61428 } 61429 61430 xml += _getServiceXmlRow(null, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId); 61431 } 61432 } 61433 61434 return $(xml); 61435 } 61436 function _getBasicServiceRow(scheduleId, price, isCheckout) { 61437 var scheduleUpdateType = 1; 61438 61439 if (!UTIL.isEmpty(scheduleId)) { 61440 scheduleUpdateType = 9; 61441 } 61442 61443 //appt_status_cd="22" 61444 var xml = '<tr schedule_id="' + scheduleId + '" input_type_cd="6" sutype="' + scheduleUpdateType + '" price_mn="' + price + '"'; 61445 61446 if (isCheckout) { 61447 xml += ' quick_checkout_fl="1"'; 61448 } 61449 61450 return xml; 61451 } 61452 61453 function _getServiceXmlRow(svcXml, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId) { 61454 var scheduleId = $.trim(jsvc.attr('schedule_id')); 61455 var count = UTIL.coalesceInt(jsvc.find('.line-item-amount').val(), 0); 61456 var price = UTIL.coalesceMoney(jsvc.find('.line-item-price').val()); 61457 61458 var xml = _getBasicServiceRow(scheduleId, price, isCheckout); 61459 61460 xml += _clientLevelXml(); 61461 xml += _bookingLevelXml(serviceCount); 61462 xml += _serviceLenXml(svcXml, jsvc, isCheckout, arrUniqueStaff, prevServiceId); 61463 xml += _serviceOtherXml(jsvc, scheduleId); 61464 xml += _attributeSummaryXml(); 61465 xml += '/>'; 61466 61467 if (count === 0) { 61468 return ''; 61469 } else if (count > 1) { 61470 for (var i=1; i < count; i++) { 61471 xml += xml; 61472 } 61473 } 61474 61475 return xml; 61476 } 61477 function _attributeSummaryXml() { 61478 var attributes = '', productTotal = 0, paymentTotal = 0, discountTotal = 0, addOnFeeTotal = 0, discountCount = 0; 61479 var lis = $(_productXml).find('li'); 61480 61481 for (var p=0; p < lis.length; p++) { 61482 var j = lis.eq(p); 61483 var price = UTIL.coalesceMoney(j.attr('price_mn')), tax = UTIL.coalesceMoney(j.attr('tax_mn')); 61484 var discount = UTIL.coalesceMoney(j.attr('discount_mn')), addOnFee = UTIL.coalesceMoney(j.attr('add_on_fee_mn')); 61485 61486 productTotal += UTIL.coalesceMoney(price + tax - discount + addOnFee); 61487 } 61488 61489 var lps = $('<ol>' + _paymentXml + '</ol>').find('lp'); 61490 61491 for (var p=0; p < lps.length; p++) { 61492 paymentTotal += UTIL.coalesceMoney(lps.eq(p).attr('payment_mn')); 61493 } 61494 61495 if (lps.length > 1) { 61496 attributes += ' payment_dt="' + lps.eq(0).attr('payment_dt') + '"'; 61497 } 61498 61499 var dds = $('<dl>' + _discountXml + '</dl>').find('dd'); 61500 discountCount = dds.length; 61501 61502 for (var d=0; d < dds.length; d++) { 61503 var dAmt = UTIL.coalesceMoney(dds.eq(d).attr('amount_mn')), feeAmt = UTIL.coalesceMoney(dds.eq(d).attr('amount_mn'), dds.eq(d).attr('fee_amount_mn')); 61504 61505 if (dAmt > 0) { 61506 discountTotal += dAmt; 61507 } 61508 61509 if (feeAmt > 0) { 61510 addOnFeeTotal += feeAmt; 61511 } else if (dAmt < 0) { 61512 addOnFeeTotal -= dAmt; 61513 } 61514 } 61515 61516 return attributes + ' inventory_price_mn="' + UTIL.coalesceMoney(productTotal) + '" total_payment_mn="' + UTIL.coalesceMoney(paymentTotal) 61517 + '" total_addOnFee_mn="' + UTIL.coalesceMoney(addOnFeeTotal) + '" total_discount_mn="' + UTIL.coalesceMoney(discountTotal) + '" discount_count_sr="' + discountCount + '"'; 61518 } 61519 function _serviceOtherXml(jsvc, scheduleId) { 61520 var crequest = UTIL.parseBool(jsvc.attr('client_request_fl')); 61521 61522 if (!crequest && UTIL.isEmpty(scheduleId) && UTIL.isEmpty(jsvc.attr('client_request_fl'))) { 61523 var jstaff = $('#pos-ticket .pos-staff-line-item'); 61524 var staffId = jsvc.attr('staff_id'); 61525 61526 for (var i=0; i < jstaff.length; i++) { 61527 if (jstaff.eq(i).attr('staff_id') == staffId) {
61528 crequest = jstaff.eq(i).hasClass('is-client-request'); 61529 break; 61530 } 61531 } 61532 } 61533 61534 var customD = UTIL.parseBool(jsvc.attr('custom_discount_fl')); 61535 var split = $.trim(jsvc.attr('commission_split_cd')); 61536 var splitPercent = $.trim(jsvc.attr('commission_split_pct')); 61537 61538 var resourceId = $.trim(jsvc.attr('service_resource_id')); 61539 var recurId = $.trim(jsvc.attr('schedule_recur_id')); 61540 var svcAttributeId = $.trim(jsvc.attr('service_attribute_id')); 61541 61542 var addOnFee = UTIL.coalesceMoney(jsvc.attr('add_on_fee_mn')); 61543 var discount = UTIL.coalesceMoney(jsvc.attr('discount_mn')); 61544 var discountNew = UTIL.coalesceMoney(jsvc.attr('new_discount_mn')); 61545 61546 var tip = UTIL.coalesceMoney(jsvc.attr('tip_mn')); 61547 var tax = UTIL.coalesceMoney(jsvc.attr('tax_mn')); 61548 var outcallFee = UTIL.coalesceMoney(jsvc.attr('outcall_fee_mn')); 61549 var isOutcall = UTIL.parseBool(jsvc.attr('outcall_fl')); 61550 61551 var attributes = ' client_request_fl="' + crequest + '" custom_discount_fl="' + customD + '" commission_split_cd="' + split + '" commission_split_pct="' + splitPercent 61552 + '" service_resource_id="' + resourceId + '" schedule_recur_id="' + recurId + '" service_attribute_id="' + svcAttributeId 61553 + '" tip_mn="' + tip + '" tax_mn="' + tax + '" outcall_fl="' + isOutcall + '" outcall_fee_mn="' + outcallFee + '"'; 61554 61555 if (addOnFee > 0) { 61556 attributes += ' add_on_fee_mn="' + addOnFee + '"'; 61557 } 61558 61559 if (discount !== 0) { 61560 attributes += ' discount_mn="' + discount + '"'; 61561 } 61562 61563 if (discountNew !== 0) { 61564 attributes += ' new_discount_mn="' + discountNew + '"'; 61565 } 61566 61567 return attributes; 61568 } 61569 function _serviceLenXml(svcXml, jsvc, isCheckout, arrUniqueStaff, prevServiceId) { 61570 var isFA = UTIL.parseBool(jsvc.attr('is_first_available_fl')); 61571 61572 var staffId = $.trim(jsvc.attr('staff_id')); 61573 var serviceId = jsvc.attr('service_id'); 61574 var sgid = jsvc.attr('service_group_id'); 61575 61576 var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true); 61577 var svcLen = UTIL.coalesceInt(jsvc.attr('service_length_nr'), ojDefault.minutes_nr); 61578 var prepNR = UTIL.coalesceInt(jsvc.attr('prep_nr'), ojDefault.prep_nr, 0); 61579 var prepFL = UTIL.parseBool(jsvc.attr('prep_fl'), ojDefault.prep_fl); 61580 61581 var processingNR = UTIL.coalesceInt(jsvc.attr('processing_nr'), ojDefault.processing_nr, 0); 61582 var processingFL = UTIL.parseBool(jsvc.attr('processing_fl'), ojDefault.processing_fl); 61583 var finishOutNR = UTIL.coalesceInt(jsvc.attr('finish_out_nr'), ojDefault.finish_out_nr, 0); 61584 var finishOutFL = UTIL.parseBool(jsvc.attr('finish_out_fl'), ojDefault.finish_out_fl); 61585 61586 var attributes = ' staff_id="' + staffId + '" service_id="' + serviceId + '" service_group_id="' + sgid 61587 + '" service_length_nr="' + svcLen + '" prep_nr="' + prepNR + '" prep_fl="' + prepFL 61588 + '" processing_nr="' + processingNR + '" processing_fl="' + processingFL + '" finish_out_nr="' + finishOutNR + '" finish_out_fl="' + finishOutFL + '"'; 61589 61590 if (isFA) { 61591 attributes += ' is_first_available_fl="1"'; 61592 } 61593 61594 var totalServiceLen = _serviceTotalLen(svcLen, processingNR, processingFL, finishOutNR, finishOutFL); 61595 var isSameStart = UTIL.isNumber(prevServiceId) && GLO.Template.RequestAppt.isSameStart(prevServiceId, serviceId); 61596 61597 return attributes + _getStaffServiceDateTime(jsvc, isCheckout, arrUniqueStaff, staffId, isFA, totalServiceLen, isSameStart); 61598 } 61599 function _getStaffServiceDateTime(jsvc, isCheckout, arrUniqueStaff, staffId, isFA, totalServiceLen, isSameStart) { 61600 var day = $.trim(jsvc.attr('appt_dt')), tm = $.trim(jsvc.attr('time_vc')), dtEnd = jsvc.attr('end_dt'); 61601 61602 if (UTIL.isDate($.trim(day + ' ' + tm))) { 61603 var dtStart = new Date(day + ' ' + tm); 61604 61605 if (UTIL.isDate(dtEnd)) { 61606 dtEnd = new Date(dtEnd); 61607 } else { 61608 dtEnd = new Date(dtStart).addMinutes(totalServiceLen); 61609 } 61610 } else { 61611 if (isCheckout || (UTIL.isDate(_dtCheckout) && _dtCheckout > new Date())) { //dtEnd must be <= _dtCheckout 61612 dtEnd = new Date(UTIL.coalesceDate(_dtCheckout, new Date())).toGloDateTime(); 61613 var dtStart = new Date(dtEnd).addMinutes(-totalServiceLen); 61614 } else { 61615 var dtStart = _getNewServiceStartDate(arrUniqueStaff, staffId, isSameStart, isFA); 61616 dtEnd = new Date(dtStart).addMinutes(totalServiceLen); 61617 } 61618
61619 day = dtStart.toGloDate(); 61620 tm = dtStart.toGloTime(); 61621 } 61622 61623 _addToUniqueStaff(arrUniqueStaff, staffId, dtStart, dtEnd, isSameStart); 61624 return ' appt_dt="' + day + '" time_vc="' + tm + '" end_dt="' + dtEnd + '"'; 61625 } 61626 function _getNewServiceStartDate(arrUniqueStaff, staffId, isSameStart, isFA) { 61627 if (isSameStart && isFA) { 61628 return new Date(_lastServiceStart); 61629 } 61630 61631 var arrIndex = UTIL.isInObjectArray(arrUniqueStaff, 'staff_id', staffId); 61632 61633 if (arrIndex !== -1) { 61634 if (isSameStart && isFA) { 61635 return new Date(arrUniqueStaff[arrIndex].start_dt); 61636 } else { 61637 return new Date(arrUniqueStaff[arrIndex].end_dt); 61638 } 61639 } else if (isSameStart && UTIL.isDate(_lastServiceStart)) { 61640 return new Date(_lastServiceStart); 61641 } else if (UTIL.isDate(_lastServiceEnd)) { 61642 return new Date(_lastServiceEnd); 61643 } else { 61644 return _conTicket.getStartDate(); 61645 } 61646 } 61647 _conTicket.getStartDate = function() { 61648 var jdt = $('#pos-ticket-datetime'); //_conTicket.startDate 61649 var day = jdt.find('#Ticket_day').val(); 61650 var tm = UI.getTimeMaskValue(jdt.find('#Ticket_tm')); 61651 61652 if (UTIL.isDate(day) && UTIL.isValidTime(tm)) { 61653 return UTIL.joinDateAndTime(day, tm); 61654 } else if (UTIL.isValidTime(tm)) { 61655 return UTIL.joinDateAndTime(null, tm); 61656 } else { 61657 return new Date(new Date().toGloDateTime()); //round to minute 61658 } 61659 } 61660 _conTicket.resetDate = function() { 61661 var jdt = $('#pos-ticket-datetime'); 61662 jdt.find('#Ticket_tm').val(''); 61663 jdt.find('#Ticket_day').val(''); 61664 _time = null; 61665 } 61666 _conTicket.setStartDate = function(day, time) { 61667 var hasChange = false, jdt = $('#pos-ticket-datetime'); 61668 var jtime = jdt.find('#Ticket_tm'), jday = jdt.find('#Ticket_day'); 61669 61670 if (!UTIL.isDate(day)) { 61671 day = new Date(); 61672 } else { 61673 day = new Date(day); 61674 } 61675 61676 if (!UTIL.isValidTime(time)) { 61677 time = new Date().toGloTime(); 61678 } 61679 61680 if (time != UI.getTimeMaskValue(jtime)) { 61681 UI.setTimeMaskValue(jtime, time); 61682 hasChange = true; 61683 _time = time; 61684 } 61685 61686 if (day.toGloDate() != jday.val()) { 61687 jday.val(day.toGloDate()); 61688 hasChange = true; 61689 } 61690 61691 _conTicket.changeDayTime(); 61692 return hasChange; 61693 } 61694 _conTicket.changeDay = function(element) { 61695 _conTicket.changeDayTime(); 61696 _conTicket.ticketChanged(); 61697 } 61698 _conTicket.changeTime = function(element) { 61699 var jsvc = $('#pos-ticket').find('.pos-service-line-item'); 61700 _time = UI.getTimeMaskValue($('#pos-ticket-datetime #Ticket_tm')); 61701 61702 _conTicket.changeDayTime(); 61703 _conTicket.ticketChanged(); 61704 } 61705 _conTicket.changeDayTime = function() { 61706 var jsvc = $('#pos-ticket').find('.pos-service-line-item'); 61707 61708 for (var i=0; i < jsvc.length; i++) { 61709 jsvc.eq(i).removeAttr('appt_dt'); 61710 jsvc.eq(i).removeAttr('end_dt'); 61711 jsvc.eq(i).removeAttr('time_vc'); 61712 } 61713 } 61714 61715 function _addToUniqueStaff(arrUniqueStaff, staffId, dtStart, dtEnd, isSameStart) { 61716 var arrIndex = UTIL.isInObjectArray(arrUniqueStaff, 'staff_id', staffId); 61717 61718 if (arrIndex === -1) { 61719 arrUniqueStaff.push({ "staff_id": staffId, "start_dt": dtStart, "end_dt": dtEnd }); 61720 } else { 61721 arrUniqueStaff[arrIndex].start_dt = dtStart; 61722 arrUniqueStaff[arrIndex].end_dt = dtEnd; 61723 } 61724 61725 if (!UTIL.isDate(_lastServiceStart) || !isSameStart) { 61726 _lastServiceStart = new Date(dtStart); 61727 _lastServiceEnd = new Date(dtEnd); 61728 } 61729 } 61730 function _serviceTotalLen(svcLen, processingNR, processingFL, finishOutNR, finishOutFL) { 61731 var len = svcLen; 61732 61733 if ((processingFL && processingNR > 0) || (finishOutFL && finishOutNR)) { svcLen += processingNR; } 61734 if (finishOutFL && finishOutNR > 0) { svcLen += finishOutNR; } 61735 61736 return len; 61737 } 61738 function _clientLevelXml() { 61739 if (UTIL.isEmpty(_conTicket.clientId)) { return ''; } 61740 61741 var cname = UTIL.replaceQuotes(UTIL.cleanString(_conTicket.clientName)); 61742 var attributes = ' client_id="' + _conTicket.clientId + '" client_vc="' + cname + '" client_type_cd="' + _conTicket.clientType + '"'; 61743 61744 if (_ticketLoyalty > 0) { attributes += ' ticket_loyalty_nr="' + _ticketLoyalty + '"'; } 61745 //if (_availableLoyalty > 0) { attributes += ' available_loyalty_nr="' + _availableLoyalty + '"'; } 61746 if (_clientLoyalty > 0) { attributes += ' client_loyalty_nr="' + _clientLoyalty + '"'; } 61747 61748 if (_cftid > 0) { attributes += ' card_on_file_tid="' + _cftid + '"'; } 61749 if (_membershipId > 0) { attributes += ' membership_id="' + _membershipId + '"'; } 61750 if (_giftBalance > 0) { attributes += ' gift_balance_mn="' + _giftBalance + '"'; } 61751 if (_clientTagXml && _clientTagXml.length) { attributes += ' tag_count_sr="' + _clientTagXml.length + '"'; } 61752 if (_birthDays > 0) { attributes += ' birth_sr="' + _birthDays + '"'; } 61753 61754 return attributes; 61755 } 61756 function _bookingLevelXml(apptCount) { 61757 var smid = $.trim($('#pos-ticket').attr('schedule_multi_id')); 61758 var dtUpdate = $.trim(_conTicket.lastUpdateDate), dtCreate = _conTicket.createDate; 61759 var bkg = $.trim(_conTicket.bookingNumber); 61760 var mtid = _getMultiTicketId();
61761 61762 var attributes = ' schedule_multi_id="' + smid + '" booking_nr="' + bkg + '" create_dt="' + dtCreate + '" last_update_dt="' + dtUpdate + '" multi_appt_count_sr="' + apptCount + '"'; 61763 61764 if (_imageCount > 0) { attributes += ' image_count_sr="' + _imageCount + '"'; } 61765 if (!UTIL.isEmpty(_providerReferral)) { attributes += ' provider_referral_id="' + _providerReferral + '"'; } 61766 61767 if (apptCount > 0) { 61768 var apptStatus = _getApptStatus(smid, _apptStatus); 61769 attributes += ' appt_status_cd="' + apptStatus + '"'; 61770 61771 if (UTIL.isDate(_dtCheckin)) { 61772 attributes += ' checkin_dt="' + _dtCheckin + '"'; 61773 } 61774 61775 if (UTIL.isDate(_dtCheckout)) { 61776 attributes += ' checkout_dt="' + _dtCheckout + '"'; 61777 //} else if (apptStatus == 22) { 61778 // attributes += ' checkout_dt="' + new Date().toGloDateTime(); + '"'; 61779 } 61780 61781 if (UTIL.isDate(_dtSignin)) { 61782 attributes += ' signin_dt="' + new Date(_dtSignin).toGloDateTime() + '"'; 61783 } 61784 } else { 61785 var day = $('#pos #Ticket_day').val(); //_dtDue 61786 61787 if (UTIL.isDate(day)) { 61788 attributes += ' due_dt="' + new Date(day).toGloDate() + '"'; 61789 } 61790 } 61791 61792 if (!UTIL.isEmpty(mtid)) { 61793 attributes += ' multi_ticket_id="' + mtid + '"'; 61794 } 61795 61796 if (!UTIL.isEmpty(_clientNote)) { 61797 attributes += ' special_request_vcl="' + UTIL.htmlEncode2(UTIL.replaceQuotes(UTIL.cleanString(_clientNote))) + '"'; 61798 } 61799 61800 if (!UTIL.isEmpty(_staffNote)) { 61801 attributes += ' staff_only_note_vc="' + UTIL.htmlEncode2(UTIL.replaceQuotes(UTIL.cleanString(_staffNote))) + '"'; 61802 } 61803 61804 return attributes; 61805 } 61806 61807 function _getApptStatus(smid, apptStatus) { 61808 var status = UTIL.coalesceInt(apptStatus, _apptStatus); 61809 61810 if (UTIL.isEmpty(status)) { 61811 if (!UTIL.isEmpty(smid)) { 61812 return 11; 61813 } else { 61814 return 10; 61815 } 61816 } 61817 61818 return status; 61819 } 61820 61821 _conTicket.updateFromSave = function(editRow) { 61822 var smid = editRow.attr('schedule_multi_id'), bkg = editRow.attr('booking_nr'), dtUpdate = editRow.attr('last_update_dt'); //, dtEnd = editRow.attr('end_dt') 61823 $('#pos-ticket').attr('schedule_multi_id', smid); 61824 61825 if (!UTIL.isEmpty(bkg)) { 61826 _conTicket.bookingNumber = bkg; 61827 } 61828 61829 if (!UTIL.isDate(dtUpdate)) { 61830 _conTicket.lastUpdateDate = new Date().toGloDateTime(); 61831 } 61832 61833 _conTicket.createDate = UTIL.coalesceDate(_conTicket.createDate, jmain.attr('create_dt')); 61834 } 61835 61836 _conTicket.displayStaffScreen = function() { 61837 $('#pos-container').addClass('display-staff-screen'); 61838 61839 if (!GLO.Info.isMobile(true)) { 61840 $('#pos-staff-list-client').focus(); 61841 } 61842 } 61843 _conTicket.displayTicket = function() { 61844 $('#pos-container').removeClass('display-staff-screen'); 61845 SA.POS.resize(); 61846 } 61847 61848 _conTicket.openTicketEasy = function(smid, jsonPostOpen) { 61849 var json = jQuery.extend(true, { "check_ticket_fl": true, "processing_message_vc": "Loading Ticket..." }, jsonPostOpen); 61850 UserPortal.Edit.get(null, smid, true, false, true, json); 61851 } 61852 _conTicket.openExistingTicket = function(smid, jservices, payMeth, payAmt, payInfo, cardData, jsonPostOpen) { 61853 var json = jQuery.extend(true, { "check_ticket_fl": true }, jsonPostOpen); 61854 61855 if (!UTIL.isEmpty(cardData)) { 61856 json.cards = cardData; 61857 json.open_after_save_fl = true; 61858 } else if (!UTIL.isEmpty(payMeth)) { 61859 json.payment_method_cd = payMeth; 61860 json.payment_mn = payAmt; 61861 } 61862 61863 if (jservices.length > 0) { 61864 json.processing_message_vc = "Loading Appointment..."; 61865 UserPortal.Edit.get(null, smid, true, false, true, json); 61866 } else { 61867 json.processing_message_vc = "Loading Ticket..."; 61868 UserPortal.Price.get(smid, null, json); 61869 } 61870 } 61871 61872 _conTicket.openTicketAndShowDiscount = function(element) { 61873 var j = $('#pos-ticket-total-discount'); 61874 61875 if (!j.hasClass('processingColor')) { 61876 j.addClass('processingColor'); 61877 SA.Ticket.openTicket(null, 0, null, null, null, { "highlight": ".price-discount-name" }); 61878 61879 setTimeout(function() { 61880 j.removeClass('processingColor'); 61881 }, 1500); 61882 } 61883 } 61884 _conTicket.openTicket = function(btnViewTicket, payMeth, payAmt, payInfo, cardData, jsonPostOpen, isQuickCheckin) { //= when payMeth = 0 -> just means to open price-popup 61885 btnViewTicket = $(btnViewTicket); 61886 var isPrintTicket = jsonPostOpen && UTIL.parseBool(jsonPostOpen.isPrintTicket); 61887 61888 if (btnViewTicket.length === 0) { 61889 if (isQuickCheckin) { 61890 var btnViewTicket = $('#pos-ticket #btnCheckinTicket'); 61891 } else { 61892 var btnViewTicket = $('#pos-ticket #btnViewTicket'); 61893 } 61894 } 61895 61896 if (!btnViewTicket.hasClass('btnProcessing4')) { 61897 GLO.UI.Form.beginProcessing(btnViewTicket); 61898 UserPortal.Price.quit(); 61899 jsonPostOpen = jQuery.extend(true, { "open_from_pos_fl": true }, jsonPostOpen); 61900 61901 _conTicket.displayTicket(); 61902 61903 setTimeout(function() { //= made async so spin view ticket button + for check above to avoid duplicate opening. 61904 SA.Ticket.openTicket2(payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket, isQuickCheckin); 61905 61906 if (isPrintTicket) { 61907 if (jsonPostOpen && jsonPostOpen.isPrintReceipt) { 61908 UserPortal.Price.open(false); 61909 UserPortal.Price.Receipt.print(false); 61910 } else { //print button should always print traveler -> if (GLO.Data.provider.traveler_cd > 0 && GLO.Data.provider.traveler_cd < 100) 61911 UserPortal.Edit.goCheckinPrint(); 61912 } 61913 } 61914 }, 10); 61915 } 61916 } 61917 _conTicket.openTicket2 = function(payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket, isQuickCheckin) { 61918 var jtix = $('#pos-ticket'); 61919 var jproducts = jtix.find('.pos-ticket-line-item:not(.pos-service-line-item)'); //.pos-product-line-item 61920 var jservices = jtix.find('.pos-ticket-line-item.pos-service-line-item'); 61921 var smid = jtix.attr('schedule_multi_id'); 61922 var jd = _setTicketOpenXml(jproducts, jservices.length, payMeth, payAmt, payInfo, cardData); 61923 61924 if (jservices.length > 0) { 61925 _setApptStatus(payMeth, isQuickCheckin, jservices); 61926 var isCheckout = _isCheckout(payMeth);
61927 var serviceXml = _getServiceXml(jservices, isCheckout); 61928 61929 if (!_isValidServiceXml(serviceXml)) { 61930 GLO.UI.Form.resetProcessing(btnViewTicket); 61931 return; 61932 } 61933 61934 _openAppt(serviceXml, smid, payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket); 61935 var jedit = UserPortal.getEditAppt(); 61936 61937 if (UTIL.isEmpty(smid)) { 61938 _openNewTicketRows(jedit, serviceXml); 61939 } else if (jservices.length > 0) { 61940 UserPortal.Booking.loadOriginalFromPos(); 61941 } 61942 61943 var hasPayMethFee = (!UTIL.isEmpty(payMeth) && UserPortal.Price.Discount.hasPayMethRule()); 61944 UserPortal.Price.Discount.setMemberServiceXml(_conTicket.memberServiceXml); 61945 61946 UserPortal.Edit.reloadAppt1(serviceXml, jd, false); 61947 UserPortal.Edit.reloadAppt2(jedit, serviceXml, jd, true, jsonPostOpen, true, payMeth, isQuickCheckin); 61948 UserPortal.Price.Discount.checkIfCanMoveDiscountToThisTicket(); 61949 } else if (jproducts.length === 0) { 61950 _openSetEmptyTicket(jsonPostOpen, payAmt); 61951 } else { 61952 UserPortal.Price.getOpen(jd, null, false, jsonPostOpen); 61953 UserPortal.Price.open(false, true); 61954 } 61955 61956 GLO.UI.Form.resetProcessing(btnViewTicket); 61957 61958 if (isQuickCheckin) { 61959 if (jservices.length > 0) { 61960 jedit.find('.btnSave > a').click(); 61961 _conTicket.reset(); 61962 } 61963 } else { 61964 _conTicket.openFinishPricePopup(payMeth, payAmt, payInfo, cardData, jsonPostOpen); 61965 } 61966 } 61967 function _isCheckout(payMeth) { 61968 if (!UTIL.isEmpty(payMeth)) { 61969 var day = $('#pos-ticket-datetime #Ticket_day').val(); 61970 var isToday = new Date(day).toGloDate() == new Date().toGloDate(); 61971 61972 if (!UTIL.isEmpty(day) && isToday) { 61973 return true; 61974 } 61975 } 61976 61977 return false; 61978 } 61979 function _setApptStatus(payMeth, isQuickCheckin, jservices) { 61980 var dtAppt = jservices.eq(0).attr('appt_dt'); 61981 61982 if (!UTIL.isDate(dtAppt) || UTIL.isToday(dtAppt)) { 61983 if (_apptStatus != 13 || _apptStatus != 14 || _apptStatus != 22) { 61984 if (!UTIL.isEmpty(payMeth)) { 61985 _apptStatus = 22; 61986 } else if (isQuickCheckin) { //} else if (!UTIL.isDate(dtAppt)) { 61987 _apptStatus = 21; 61988 } else { 61989 var minuteDiff = (new Date(dtAppt) - new Date()) / (1000 * 60); 61990 61991 if (minuteDiff > -31 && minuteDiff < 61) { //= set to checked-in if appointment date is less than 30 minutes in future or less than 60 minutes in the past. 61992 _apptStatus = 21; 61993 } 61994 } 61995 } 61996 } 61997 } 61998 61999 _conTicket.deleteTicket = function(btn) { 62000 UserPortal.Edit.deleteSignin(); 62001 } 62002 _conTicket.printTicket = function(btn, isPrintReceipt) { 62003 var jsonPostOpen = { "isPrintTicket": true, "isPrintReceipt": isPrintReceipt }; 62004 _conTicket.openTicket(btn, null, null, null, null, jsonPostOpen); 62005 } 62006 _conTicket.checkinTicket = function(btnViewTicket) { 62007 if (GLO.Data.provider.resource_per_cd == 20 && SA.Data.resourceJson.length > 0) { 62008 _openSetTicketResource() 62009 } else { 62010 SA.Ticket.openTicket(btnViewTicket, null, null, null, null, null, true); 62011 } 62012 } 62013 _conTicket.checkinWithResource = function(resourceElement) { 62014 var resourceId = UTIL.coalesceString($(resourceElement).attr('resource_id')); 62015 var btnViewTicket = $('#pos-ticket-footer #btnCheckinTicket > a'); 62016 var jlines = $('#pos-ticket-order').find('.pos-service-line-item'); 62017 62018 for (var i=0; i < jlines.length; i++) { 62019 jlines.eq(i).attr('service_resource_id', resourceId); 62020 } 62021 62022 for (var s=0; s < _serviceXml.length; s++) { 62023 _serviceXml.eq(s).attr('service_resource_id', resourceId); 62024 } 62025 62026 GLO.Popup.closeIfExist($('#pop-set-ticket-resource').closest('.glopop')); 62027 SA.Ticket.openTicket(btnViewTicket, null, null, null, null, null, true); 62028 } 62029 function _openSetTicketResource() { 62030 var list = '', resourceId = null, rg = SA.Data.resourceJson; 62031 62032 if (_serviceXml.length) { 62033 resourceId = _serviceXml.eq(0).attr('service_resource_id'); 62034 } 62035 62036 for (var i=0; i < rg.length; i++) { 62037 if (rg.length > 1 && rg[i].resources.length > 0) { 62038 list += '<h3 class="ticket-resource-group" resource_group_id="' + rg[i].id + '">' + rg[i].name + '</h3>'; 62039 } 62040 62041 list += _getResourceHtm(rg[i].resources, resourceId); 62042 } 62043 62044 var msg = '<p>Select service location or press <b style="color: rgb(0, 140, 255);">Close</b> to skip</p>'; 62045 var htm = '<div id="pop-set-ticket-resource">
62045' + msg + list + '</div>'; 62046 var jpop = GLO.Popup.Custom.openSimple(htm, 'Set Ticket Resource'); 62047 GLO.Popup.Custom.singleButton(jpop, 'Close').click(SA.Ticket.checkinWithResource); 62048 } 62049 function _getResourceHtm(arrResource, resourceId) { 62050 var list = ''; 62051 62052 for (var i=0; i < arrResource.length; i++) { 62053 var cssClass = 'ticket-resource-box'; 62054 62055 if (resourceId == arrResource[i].id) { 62056 cssClass += ' is-selected'; 62057 } 62058 62059 list += '<span resource_id="' + arrResource[i].id + '" default_staff_id="' + arrResource[i].default_staff_id + '" class="' + cssClass 62060 + '" onclick="SA.Ticket.checkinWithResource(this)">' + arrResource[i].name + '</span>'; 62061 } 62062 62063 return list; 62064 } 62065 62066 function _isValidServiceXml(serviceXml) { 62067 for (var i=0; i < serviceXml.length; i++) { 62068 if (UTIL.isEmpty(serviceXml.eq(i).attr('staff_id'))) { 62069 var msg1 = '<p>Press Each Service in the Ticket to Add Staff to Each Service</p>'; 62070 var msg2 = '<p style="text-align: center;">Or press <span class="btnAdd"><a onclick="SA.POS.openSelectStaff()">Select Staff</a></span> </p>'; 62071 var htm = '<div id="pop-warnng-staff-required">' + msg1 + msg2 + '</div>'; 62072 62073 GLO.Popup.Warning.open(htm, 'Staff Required'); 62074 62075 /* SA.POS.filterBoxesHome(); 62076 62077 if (!GLO.POS.isDisplayServices()) { 62078 SA.POS.toggleList('services'); 62079 } */ 62080 62081 return false; 62082 } 62083 } 62084 62085 return true; 62086 } 62087 function _openNewTicketRows(jedit, serviceXml) { //= if is new appt, only 1st row included on load edit-appt. 62088 UserPortal.Edit.isNewAppt = true; 62089 return; 62090 62091 var trsXml = $(serviceXml); 62092 62093 for (var i=1; i < trsXml.length; i++) { 62094 UserPortal.Edit.addService(); 62095 var trsvc = jedit.find('.editServiceRow:last'), trXml = trsXml.eq(i); 62096 62097 UserPortal.Create.loadServiceRow(jedit, trsvc, trXml, i, i + 1); 62098 } 62099 } 62100 function _getMultiTicketId() { 62101 if (_multiTicketXml && _multiTicketXml.attr) { 62102 return _multiTicketXml.attr('multi_ticket_id'); 62103 } else { 62104 return ''; 62105 } 62106 } 62107 function _setTicketOpenXml(jproducts, apptCount, smid, payMeth, payAmt, payInfo, cardData) { 62108 var inventoryXml = _getTicketInventoryXml(jproducts, true, apptCount); //UserPortal.Price.inventoryXml 62109 var discountXml = _getDiscountXml(true); //UserPortal.Price.discountArray 62110 var tagXml = _conTicket.getTagXml(false, true); 62111 var pmt = UTIL.coalesceMoney(payAmt, _initialPayment); 62112 var multiTicketXml = '', mtid = _getMultiTicketId(); 62113 62114 var h2 = '<h2 product_tip_mn="' + $.trim(_productTip) + '"'; 62115 h2 += _bookingLevelXml(apptCount); 62116 h2 += _attributeSummaryXml(); 62117 h2 += _clientLevelXml(); 62118 62119 if (!UTIL.isEmpty(mtid)) { 62120 h2 += ' multi_ticket_id="' + mtid + '"'; 62121 multiTicketXml = _multiTicketXml.outerHTML(); 62122 } 62123 62124 h2 += '/>'; 62125 62126 if (!UTIL.isEmpty(_paymentXml)) { 62127 var paymentXml = '<ol>' + _paymentXml + '</ol>'; //UserPortal.Price.paymentXml 62128 } else { 62129 var paymentXml = ''; 62130 } 62131 62132 return $('<div>' + h2 + inventoryXml + paymentXml + discountXml + multiTicketXml + tagXml + '</div>'); 62133 } 62134 62135 function _loadTagXml(jxmlAppt) { 62136 _clientTagXml = jxmlAppt.find('tags tag'); 62137 _clientTagRelationshipXml = jxmlAppt.find('rl li'); 62138 } 62139 _conTicket.loadTagArray = function(tagArray) { 62140 var htm = '', tagXml = '<tags>'; 62141 var cid = _conTicket.clientId, cname = _conTicket.clientName; 62142 62143 for (var i=0; i < tagArray.length; i++) { 62144 tagXml += UTIL.jsonToXml(tagArray[i], 'tag'); 62145 htm += GLO.ClientProfile.Tag.getTagHtm(tagArray[i], cid, cname, true); 62146 } 62147 62148 _clientTagXml = $(tagXml + '</tags>').find('tag'); 62149 _conTicket.loadClientNote('client-tag', htm, tagArray.length); 62150 } 62151 _conTicket.getTagXml = function(isReturnAsJQuery, isGetTagRelatedAppts) { 62152 if (_clientTagXml && _clientTagXml.length) { 62153 var tagXml = $('<tags>'); 62154 62155 for (var t=0; t < _clientTagXml.length; t++) { 62156 tagXml.append(_clientTagXml.eq(t)); 62157 } 62158 62159 if (isReturnAsJQuery) { 62160 return tagXml.find('tag'); 62161 } else { 62162 var tagXml = tagXml.outerHTML(); 62163 62164 if (isGetTagRelatedAppts && _clientTagRelationshipXml && _clientTagRelationshipXml.length) { 62165 tagXml += '<rl>' + _clientTagRelationshipXml.outerHTML() + '</rl>'; 62166 } 62167 62168 return tagXml; 62169 } 62170 } 62171 62172 return ''; 62173 } 62174 _conTicket.editTagXml = function(tagObject) { 62175 if (_clientTagXml && _clientTagXml.length) { 62176 var jtags = _conTicket.getTagXml(true); 62177 var tagXml = '', isUpdate = false; 62178 62179 for (var t=0; t < tags.length; t++) { 62180 if (tagObject.tag_id == jtags.eq(i).attr('tag_id')) { 62181 jtags.eq(i).remove(); 62182 isUpdate = true; 62183 tagXml += UTIL.jsonToXml(tagObject, 'tag'); 62184 } else { 62185 tagXml += jtags.outerHTML(); 62186 } 62187 } 62188 62189 if (!isUpdate) { 62190 tagXml += UTIL.jsonToXml(tagObject, 'tag'); 62191 } 62192 62193 _clientTagXml = $(tagXml + '</tags>').find('tag'); 62194 } else { 62195 _conTicket.loadTagArray([tagObject]); 62196 } 62197 } 62198 62199 function _isPosQuickCheckout(jappt, payMeth) { 62200 if (!UTIL.isEmpty(payMeth)) { 62201 if (UTIL.isEmpty(UserPortal.Edit.scheduleMultiId)) { //= is new appointment so is a quick checkout 62202 return true; 62203 } 62204 62205 var apptDay = UserPortal.getApptDate(jappt.find('#Appt_dt, #Appointment_dt'));
62206 62207 if (UTIL.isToday(apptDay) && UserPortal.Booking.service.length) { 62208 var start = new Date(UserPortal.Booking.service[UserPortal.Booking.service.length - 1].start_dt); 62209 var end = new Date(UserPortal.Booking.service[UserPortal.Booking.service.length - 1].end_dt); 62210 62211 if (new Date().addMinutes(-5) > start) { //= appointment has already started or starts within the next 5 minutes) 62212 if (end > new Date().addMinutes(-60)) { //= appointment end time is in the future or less than 60 minutes in the past 62213 return true; 62214 } 62215 } 62216 } 62217 } 62218 62219 return false; 62220 } 62221 _conTicket.finishOpenAppt = function(jappt, payMeth, isQuickCheckin) { 62222 //var jappt = UserPortal.getAppt(); 62223 var isCreate = (jappt.attr('id') === 'ba-CreateAppointment'); 62224 var isQuickCheckout = _isPosQuickCheckout(jappt, payMeth); 62225 62226 UserPortal.Create.Checkout.loadEditAppt(jappt, isQuickCheckin, isQuickCheckout); 62227 UserPortal.Create.Checkout.calculateDateTime(jappt, isCreate, true); 62228 //UserPortal.Create.checkMoreButton(); 62229 62230 if (isQuickCheckout || !UTIL.isEmpty(payMeth)) { 62231 var jPricePop = UserPortal.getPricePop(); //if price-pop not open, this will try to open it. 62232 } else { 62233 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62234 } 62235 62236 /* if (_clientTagXml && _clientTagXml.length) { 62237 var tagXml = $('<tags>'); 62238 62239 for (var t=0; t < _clientTagXml.length; t++) { 62240 tagXml.append(_clientTagXml.eq(t)); 62241 } 62242 62243 UserPortal.setTagJsonFromXml(tagXml, jPricePop, _conTicket.clientId); 62244 UserPortal.setTagIcon(jappt, _conTicket.clientId); 62245 } */ 62246 62247 return jPricePop; 62248 } 62249 62250 function _openAppt(serviceXml, smid, payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket) { 62251 var note = ''; 62252 62253 if (true || !UTIL.isEmpty(smid)) { 62254 UserPortal.Price.resetOnOpen(); 62255 UserPortal.Edit.open(serviceXml, false, jsonPostOpen); 62256 UserPortal.Edit.schedule_Multi_Del_ids = _deleteScheduleIds; 62257 } else { 62258 UserPortal.Create.open(serviceXml, false, note, true); 62259 62260 if (serviceXml.length > 2) { 62261 //serviceXml = serviceXml.eq(0).remove(); 62262 //serviceXml = serviceXml.eq(0).remove(); 62263 62264 UserPortal.Create.convertCreateToEdit(serviceXml, payMeth, payAmt, payInfo, cardData, jsonPostOpen); 62265 //UserPortal.Create.Checkout.setEditQuickCheckout(); 62266 } 62267 } 62268 62269 if (!btnViewTicket.hasClass('btnProcessing4')) { 62270 GLO.UI.Form.beginProcessing(btnViewTicket); 62271 } 62272 } 62273 function _openSetEmptyTicket(jsonPostOpen, payAmt) { 62274 if (jsonPostOpen && UTIL.parseBool(jsonPostOpen.open_keypad_if_no_ticket)) { 62275 _conTicket.openKeypad(payAmt * 100); 62276 } else if ($('#pos-container.services').length) { 62277 GLO.Popup.Warning.open('Please add service before opening', 'Empty Ticket'); 62278 } else { 62279 GLO.Popup.Warning.open(SA.Resource.PleaseAddProductsBeforePayment, 'Empty Ticket'); 62280 } 62281 } 62282 function _openSetCashPayment(jPricePop) { 62283 var jchange = jPricePop.find('#appt-price-payment-table').find('.payment-good'); 62284 62285 if (jchange.length > 0) { 62286 jPricePop.find('.btnSave > a').click(); 62287 62288 if (jchange.hasClass('is-change')) { 62289 setTimeout(function() { 62290 $('#pos-ticket-change-due').addClass('display').html('Change Due<br/>' + jchange.text()); 62291 }, 900); 62292 } 62293 } 62294 } 62295 function _openSetSwipe(cardData, jsonPostOpen) { 62296 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62297 var jccPop = $('#process-card-container').closest('.glopop'); 62298 var jedit = UserPortal.getEditAppt(); 62299 62300 UserPortal.Price.Payment.MobileSwipe.processInvoice(cardData, jsonPostOpen, jccPop, jPricePop, jedit); 62301 } 62302 62303 function _getTaxForProduct(jline, taxRate, productPrice) { 62304 var tax = UTIL.coalesceMoney(jline.attr('tax_mn')); 62305 62306 if (tax > 0) { 62307 return tax; 62308 } else if (taxRate > 0 && tax === 0) { 62309 var jticket = $('#pos-ticket'); 62310 var totalPrice = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', '')); 62311 var payment = UTIL.coalesceMoney(_initialPayment); 62312 62313 if (totalPrice > payment) { 62314 var discount = UTIL.coalesceMoney(jline.attr('new_discount_mn'), jline.attr('discount_mn')); 62315 var addOnFee = UTIL.coalesceMoney(jline.attr('add_on_fee_mn')); 62316 var fullPrice = UTIL.coalesceMoney(productPrice - UTIL.coalesceMoney(discount) + UTIL.coalesceMoney(addOnFee)); 62317 62318 return UTIL.coalesceMoney(fullPrice * taxRate/100); 62319 } 62320 } 62321 62322 return ''; 62323 } 62324 function _openAddLineItem(jline, foundCount) { 62325 var taxRate = jline.attr('custom_tax_rate_pct'); 62326 if (UTIL.isEmpty(taxRate)) { taxRate = GLO.inventoryTax; } 62327 62328 var amt = jline.find('.line-item-amount').val() - UTIL.coalesceInt(foundCount, 0); 62329 var price = jline.find('.line-item-price').val(); 62330 var tax = _getTaxForProduct(jline, taxRate, price); 62331 62332 var ixml = '', inventoryId = parseInt(jline.attr('inventory_id')); 62333 var arrSIID = _getSIIDs(jline, amt); 62334 62335 if (SA.POS.inventory_json.manual_entry && SA.POS.inventory_json.manual_entry.id === inventoryId) { 62336 var product = SA.POS.inventory_json.manual_entry; 62337 } else { 62338 var product = SA.POS.getProductObject(inventoryId); 62339 } 62340 62341 if (product) { 62342 var name = product.label; 62343 var vendorId = UTIL.cleanString(product.vendor_id); 62344 var plineId = UTIL.cleanString(product.product_line_id); 62345 var cost = UTIL.cleanString(product.cost_mn); 62346 //eprice = product.employee_price_mn; 62347 } else { 62348 var name = jline.find('.line-item-name').text(); 62349 var vendorId = '', plineId = '', cost = 0; 62350 } 62351 62352 var more = _getProductDiscountAndFee(jline); 62353 var gc = _openAddLineItemGiftCard(jline); 62354 62355 if (!UTIL.isEmpty(vendorId)) {
62356 var vendor = SA.POS.getVendorObject(vendorId); 62357 62358 if (vendor) { 62359 vmid = vendor.vendor_merchant_id; 62360 62361 if (!UTIL.isEmpty(vmid)) { 62362 more += ' vendor_merchant_id="' + vmid + '"'; 62363 } 62364 } 62365 } 62366 62367 for (var s=0; s < arrSIID.length; s++) { 62368 ixml += '<li amount_nr="1" price_mn="' + price + '" tax_mn="' + tax + '" tax_rate_pct="' + taxRate // + '" employee_price_mn="' + eprice 62369 + '" schedule_inventory_id="' + arrSIID[s] + '" inventory_id="' + inventoryId + '" inventory_vc="' + name 62370 + '" cost_mn="' + cost + '" vendor_id="' + vendorId + '" product_line_id="' + plineId + '"' + gc + more + '/>'; 62371 } 62372 62373 return ixml; 62374 } 62375 62376 function _getProductDiscountAndFee(jline) { 62377 var discount = jline.attr('discount_mn'); 62378 var fee = jline.attr('add_on_fee_mn'); 62379 var attributes = ''; 62380 62381 if (discount > 0) { 62382 attributes += ' discount_mn="' + discount + '" new_discount_mn="' + discount + '"'; 62383 } 62384 62385 if (fee > 0) { 62386 attributes += ' add_on_fee_mn="' + fee + '"'; 62387 } 62388 62389 return attributes; 62390 } 62391 62392 function _openAddLineItemGiftCard(jline) { 62393 var output = ''; 62394 var isgc = jline.attr('is_gift_card_fl'); 62395 var gcid = jline.attr('gift_card_id'); 62396 var gcnr = jline.attr('gift_number_vc'); 62397 //var gcmn = jline.attr('gift_balance_mn'); 62398 62399 if (UTIL.parseBool(isgc) || !UTIL.isEmpty(gcid)) { 62400 var toCID = $.trim(jline.attr('to_client_id')), original = $.trim(jline.attr('gift_original_mn')), balance = $.trim(jline.attr('gift_balance_mn')); 62401 output += ' is_gift_card_fl="1"'; 62402 62403 if (!UTIL.isEmpty(gcid)) { output += ' gift_card_id="' + gcid + '"'; } 62404 if (!UTIL.isEmpty(gcnr)) { output += ' gift_number_vc="' + gcnr + '"'; } 62405 62406 output += ' to_client_id="' + toCID + '" gift_original_mn="' + original + '" gift_balance_mn="' + balance + '"'; 62407 } else { 62408 var inventoryId = jline.attr('inventory_id'); 62409 var product = SA.POS.getProductObject(inventoryId); 62410 62411 if (product && product.is_gift_card_fl) { 62412 output += ' is_gift_card_fl="1"'; 62413 } 62414 } 62415 62416 return output; 62417 } 62418 62419 function _getSIIDs(jline, amt) { 62420 var arrSIID = UTIL.cleanString(jline.attr('schedule_inventory_ids')).split(','); 62421 var cnt = arrSIID.length; 62422 62423 for (; cnt < amt; cnt++) { 62424 arrSIID.push(''); 62425 } 62426 62427 return arrSIID; 62428 } 62429 62430 _conTicket.openFinishPricePopup = function(payMeth, payAmt, payInfo, cardData, jsonPostOpen) { 62431 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62432 var jPriceSaveBtn = jPricePop.find('.btnSave').find('a').text('Complete'); 62433 var jappt = UserPortal.getAppt(); 62434 62435 var jticket = $('#pos-ticket').addClass('open-in-popup'); 62436 var smid = jticket.attr('schedule_multi_id'); 62437 var isSwipe = (!UTIL.isEmpty(smid) && !UTIL.isEmpty(cardData)); 62438 62439 UserPortal.Price.openFromPOS(_deleteInventoryXml); 62440 62441 if (jticket.find('#btnSaveTicket > a.unsaved-change').length) { 62442 jappt.find('.btnSave > a').css({ "border": "3px solid red" }); 62443 jPriceSaveBtn.css({ "border": "3px solid red" }); 62444 } 62445 62446 //if (UTIL.isEmptyObject(payInfo)) { jPricePop.find('#Is_Walkin_fl').prop('checked', true).change(); } 62447 62448 if (!UTIL.isEmpty(payMeth)) { 62449 if (!UTIL.isEmpty(payAmt)) { 62450 jPricePop.find('#Payment_mn:last').val(UTIL.displayMoney(payAmt, true, true, true)); 62451 } 62452 62453 if (true || GLO.Info.isMobile(true) || UI.Keypad.isButtonBased()) { 62454 if (isSwipe) { 62455 UI.setMobileSelect($('#Mobile_Payment_Method_cd'), payMeth); 62456 } else if (payMeth > 0) { 62457 jPricePop.find('#Mobile_Payment_Method_cd').find('li[value="' + payMeth + '"]').click(); 62458 } 62459 } else if (!isSwipe) { //swipe processed by _conPmt.MobileSwipe.processInvoice 62460 jPricePop.find('#Payment_Method_cd:last').val(payMeth).change(); 62461 //if (payMeth == 10 && !isSwipe) { setTimeout(UserPortal.Price.Payment.openCreditCard, 600); } 62462 } 62463 } 62464 62465 if (!UTIL.isEmpty(cardData)) { 62466 _openSetSwipe(cardData, jsonPostOpen); 62467 } else if ((payMeth == 1 || payMeth == 99) && UTIL.coalesceInt(payAmt, 0) === 0) { 62468 jPricePop.find('#appt-price-payment-table').find('.Payment_mn:last').focus(); 62469 } else if (payMeth == 1 && UTIL.coalesceInt(payAmt, 0) > 0) { 62470 _openSetCashPayment(jPricePop); 62471 } 62472
62473 /* if (!UTIL.isEmpty(smid)) { //merge ticket from POS + DB 62474 //jsonPostOpen = jQuery.extend(true, { "open_from_pos_fl": true }, jsonPostOpen); 62475 //UserPortal.Edit.checkIfUpdated(smid, null, true, null, jsonPostOpen); 62476 //_conTicket.openExistingTicket(smid, jservices, payMeth, payAmt, payInfo, cardData, jsonPostOpen); 62477 } */ 62478 62479 if (jsonPostOpen && jsonPostOpen.save_and_reset_fl) { 62480 if (jPriceSaveBtn.length) { 62481 jPriceSaveBtn.click(); 62482 } else { 62483 jappt.find('.btnSave > a').click(); 62484 } 62485 62486 _conTicket.reset(null, true); 62487 } else if (jsonPostOpen && jsonPostOpen.lookup_gift_card_fl) { 62488 var giftCardId = jsonPostOpen.gift_card_id; 62489 var jli = $('<li number_vc="' + jsonPostOpen.gift_number_vc + '" gift_card_id="' + jsonPostOpen.gift_card_id + '">' + jsonPostOpen.processing_mssage_vc + '</li>'); 62490 62491 UserPortal.Lookup.addGiftCardPayment(jPricePop, jli, giftCardId); 62492 } 62493 } 62494 62495 function _openTicketMatchesPOS(smid) { 62496 var posSMID = UTIL.cleanString($('#pos-ticket').attr('schedule_multi_id')); 62497 smid = UTIL.cleanString(smid); 62498 62499 if (posSMID == smid || (posSMID.indexOf('tmp') !== -1 && UTIL.isEmpty(smid))) { 62500 return true; 62501 } else { 62502 return false; 62503 } 62504 } 62505 62506 _conTicket.removeProduct = function(smid, inventoryId, siid) { 62507 var jticket = $('#pos-ticket'); 62508 62509 if (_openTicketMatchesPOS(smid)) { 62510 _removeProduct(jticket, inventoryId, siid); 62511 } 62512 } 62513 62514 function _removeProduct(jticket, inventoryId, siid) { 62515 var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]'); 62516 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62517 var amt = _getAmountOnOpenTicket(jPricePop, inventoryId); //var amt = jline.find('.line-item-amount').val(); 62518 62519 if (UTIL.coalesceInt(amt, 0) === 0) { 62520 jline.find('.ui-icon-circle-close').click(); 62521 } else { 62522 _changeProductAmount(jline, siid, amt, true); 62523 _conTicket.changeProductPriceFromOpenTicket(inventoryId); 62524 } 62525 62526 _finishAddProductOrService(); 62527 _conTicket.enableOrDisableTicketScroll(); 62528 } 62529 62530 function _changeProductAmount(jline, siid, amtNew, isRemove) { 62531 jline.find('.line-item-amount').val(amtNew); 62532 62533 if (!UTIL.isEmpty(siid)) { 62534 var arrSIID = UTIL.cleanString(jline.attr('schedule_inventory_ids')).split(','); 62535 62536 for (var i=0; i < arrSIID.length; i++) { 62537 if (arrSIID[i] == siid) { 62538 if (isRemove) { 62539 _deleteInventoryXml += '<li del_schedule_inventory_id="' + siid + '"/>'; 62540 62541 arrSIID.splice(i, 1); 62542 jline.attr('schedule_inventory_ids', arrSIID.join(',')); 62543 } 62544 62545 _conTicket.recalculate(); 62546 return; 62547 } 62548 } 62549 62550 if (!isRemove) { 62551 if (!UTIL.isEmpty(arrSIID[0])) { siid = arrSIID.join(',') + ',' + siid; } 62552 62553 jline.attr('schedule_inventory_ids', siid); 62554 } 62555 } 62556 62557 _conTicket.recalculate(); 62558 } 62559 62560 _conTicket.changeProductPriceFromOpenTicket = function(inventoryId) { 62561 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62562 var smid = UTIL.cleanString(jPricePop.find('#price-header').attr('schedule_multi_id')); 62563 var price = _getPriceOnOpenTicket(jPricePop, inventoryId); 62564 62565 if (!_openTicketMatchesPOS(smid)) { return; } 62566 62567 $('#pos-ticket').find('.pos-product-line-item[inventory_id="' + inventoryId + '"]').find('.line-item-price').val(price); 62568 _conTicket.recalculate(); 62569 } 62570 62571 _conTicket.inputOnFocus = function() { 62572 var me = this; 62573 62574 /* ?? throws error on Android ?? 62575 setTimeout(function() { 62576 me.selectionStart = me.selectionEnd = me.value.length; 62577 }, 100); 62578 */ 62579 } 62580 62581 _conTicket.changeProductAmountFromOpenTicket = function(inventoryId) { 62582 var jPricePop = $('#appt-price-popup').closest('.glopop'); 62583 var smid = UTIL.cleanString(jPricePop.find('#price-header').attr('schedule_multi_id')); 62584 var amt = _getAmountOnOpenTicket(jPricePop, inventoryId); 62585 62586 _conTicket.changeProductAmount(smid, inventoryId, null, amt); 62587 } 62588 62589 function _getPriceOnOpenTicket(jPricePop, inventoryId) { 62590 var tr = jPricePop.find('.appt-product-row'); 62591 var amt = 0, price = 0, rowPrice, rowAmt; 62592 62593 for (var i=0; i < tr.length; i++) { 62594 if (tr.eq(i).find('.booking-product').attr('inventory_id') == inventoryId) { 62595 rowAmt = UTIL.coalesceInt(tr.eq(i).find('.booking-product-count').val(), 0); 62596 rowPrice = UTIL.coalesceMoney(tr.eq(i).find('.booking-product-price').val(), 0); 62597 62598 price += rowPrice * rowAmt; 62599 amt += rowAmt; 62600 } 62601 } 62602 62603 return UTIL.coalesceMoney(UTIL.coalesceMoney(price)/UTIL.coalesceMoney(amt)); 62604 } 62605 62606 function _getAmountOnOpenTicket(jPricePop, inventoryId) { 62607 var tr = jPricePop.find('.appt-product-row'); 62608 var amt = 0; 62609 62610 for (var i=0; i < tr.length; i++) { 62611 if (tr.eq(i).find('.booking-product').attr('inventory_id') == inventoryId) { 62612 amt += UTIL.coalesceInt(tr.eq(i).find('.booking-product-count').val(), 0); 62613 } 62614 } 62615 62616 return amt; 62617 } 62618 62619 _conTicket.changeProductAmount = function(smid, inventoryId, siid, amt) { 62620 if (!_openTicketMatchesPOS(smid)) { return; } 62621 62622 var jticket = $('#pos-ticket'); 62623 var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]'); 62624 62625 if (jline.length === 0) { 62626 _conTicket.addProductLine(inventoryId, amt); 62627 _conTicket.recalculate(); 62628 62629 if (!UTIL.isEmpty(siid)) { 62630 var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]'); 62631 } else { 62632 return; 62633 } 62634 } 62635 62636 _changeProductAmount(jline, siid, amt); 62637 } 62638 62639 _conTicket.setClientAttributes = function(cid, cname, ctype, cftid, cpts, tpts, apts, membershipId, tagCount, giftBalance, birthDays) { 62640 //tagCount 62641 _cftid = cftid; 62642 _membershipId = membershipId; 62643 _giftBalance = giftBalance; 62644 _birthDays = birthDays; 62645 62646 _conTicket.clientId = UTIL.coalesceInt(_conTicket.clientId, cid); 62647 _conTicket.clientType = UTIL.coalesceInt(_conTicket.clientType, ctype); 62648 _conTicket.clientName = UTIL.coalesceString(_conTicket.clientName, cname); 62649 62650 _clientLoyalty = cpts; 62651 _ticketLoyalty = tpts; 62652 _availableLoyalty = apts; 62653 } 62654 _conTicket.updateTicket = function(jdata) { 62655 var jticket = $('#pos-ticket'); 62656 var smid = jdata.attr('schedule_multi_id'); 62657 62658 jticket.attr('schedule_multi_id', smid); 62659 //_initialPayment = 0, _originalTotal = 0, _productTip = 0; 62660 _bookingNumber = jticket.attr('booking_nr'); 62661 _lastUpdateDate = jdata.attr('last_update_dt'); 62662 62663 $('#pos-ticket #btnViewTicket > a').removeClass('unsaved-change'); 62664 } 62665 62666 function _resetClientAttributes(isFullReset) {
62667 $('#pos-ticket').removeClass('has-client'); 62668 $('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4'); 62669 62670 $('#pos-ticket-client-attributes').html('').addClass('hide'); //.find('.client-note-row').remove() 62671 $('#pos-ticket-client-header').find('.client-has-card-on-file, .client-membership-icon, .new-client-text-icon').remove(); 62672 62673 if (isFullReset) { 62674 $('#pos-add-client-button').removeAttr('title').find('input').val(''); 62675 } 62676 } 62677 _conTicket.reset = function(smid, isGoHome) { 62678 if (!UTIL.parseBool(GLO.isPOS)) { return; } 62679 if (!UTIL.isEmpty(smid) && !_openTicketMatchesPOS(smid)) { return; } 62680 62681 clearTimeout(_addLineToHeaderTimeout); 62682 62683 var jticket = $('#pos-ticket').removeClass('scroll-active').removeClass('open-in-popup').removeClass('has-client'); 62684 var jlns = jticket.find('.pos-ticket-line-item, .pos-staff-line-item'); //, .pos-ticket-discount-line, .pos-ticket-payment-line 62685 62686 for (var i=0; i < jlns.length; i++) { 62687 jlns.eq(i).remove(); 62688 } 62689 62690 jticket.removeAttr('schedule_multi_id'); //.removeAttr('last_update_dt').removeAttr('client_id').removeAttr('client_vc'); 62691 jticket.find('#pos-ticket-total-discount > b').text(''); 62692 jticket.find('#btnViewTicket').find('>a').text('Open Ticket'); 62693 jticket.find('#btnSaveTicket').find('>a').removeClass('unsaved-change'); 62694 62695 jticket.find('#pos-header-staff-ticket-label').text('Ticket').removeClass('ticket-booking-number').removeClass('ticket-resource-name'); 62696 jticket.find('#btnCheckinTicket, #btnPrintTicket').addClass('hide'); 62697 jticket.find('#pos-ticket-paid, #pos-ticket-due').addClass('hide'); 62698 jticket.find('#pos-ticket-header-paid-amount').text('0'); 62699 62700 $('#pos-product-header-enter #pos-enter-product-or-amount').val(''); 62701 $('#pos-product-header-enter .btnAction2').addClass('hide'); 62702 $('#pos #header-ticket-total').text(''); 62703 $('#pos-header-staff').removeClass('selected').find('#btnSelectedStaff > a').removeAttr('staff_id').removeAttr('is_first_available_fl').text(''); 62704 $('#pos-staff-list-client').val(''); 62705 62706 var jdt = $('#pos-ticket-datetime'); 62707 jdt.find('#Ticket_day').val(''); 62708 jdt.find('#Ticket_tm').val(''); 62709 jdt.find('.appt-icon').remove(); 62710 62711 _time = null; 62712 _resetClientAttributes(true); 62713 _resetVariables(); 62714 _setBookingNumber(); 62715 62716 _conTicket.ticketSaved(); 62717 _conTicket.recalculate(); 62718 SA.POS.filterBoxesHome(); 62719 62720 if (isGoHome) { 62721 _conTicket.displayStaffScreen(); 62722 } 62723 } 62724 function _resetVariables() { 62725 clearTimeout(_timeoutApplyDiscounts); 62726 62727 _addLineToHeaderTimeout = null; 62728 _isLoading = false; 62729 62730 _serviceXml = _productXml = _paymentXml = _discountXml = _multiTicketXml = ''; 62731 _clientTagXml = _clientTagRelationshipXml = null; 62732 _deleteInventoryXml = _deleteScheduleIds = ''; 62733 _conTicket.discountDelArray = []; 62734 62735 _conTicket.promoCode = _conTicket.bookingNumber = _conTicket.createDate = _conTicket.lastUpdateDate = _conTicket.waitId = null; 62736 _conTicket.clientId = _conTicket.clientName = _conTicket.clientType = null; 62737 _conTicket.isCustomDiscount = false; 62738 _conTicket.memberServiceXml = null; 62739 62740 _initialPayment = _originalTotal = _productTip = _giftBalance = _imageCount = 0; 62741 _clientLoyalty = _ticketLoyalty = _availableLoyalty = _discountCount = _referralDiscount = 0; 62742 _clientNote = _staffNote = ''; 62743 _lastServiceStart = _lastServiceEnd = null; 62744 62745 _cftid = _membershipId = _birthDays = null; 62746 _apptStatus = _dtCheckin = _dtCheckout = _dtSignin = _dtDue = _scheduleRecurId = _providerReferral = null; 62747 62748 SA.Ticket.resetDate(); 62749 } 62750 62751 _conTicket.getOriginalServiceXml = function() { 62752 return _serviceXml; 62753 } 62754 62755 function check_for_phone() { 62756 var message = document.getElementById("pos-staff-list-client").value; 62757 var Regex = /\b[\+]?[(]?[0-9]{2,6}[)]?[-\s\.]?[-\s\/\.0-9]{3,15}\b/m; 62758 62759 if (Regex.test(message)) { 62760 var matches = Regex.exec(message); 62761 var phone = matches[0]; // matches.index 62762 var name = message.replace(phone, ''); 62763 62764 62765 } 62766 62767 //alert(Regex.test(message)); // This will alert 'true' if the textarea contains a phonenumber 62768 } 62769 62770 _conTicket.openSelectStaff = function(delay, serviceId) {
62771 delay = UTIL.coalesceInt(delay, 500); 62772 62773 setTimeout(function() { 62774 SA.POS.openSelectStaff(null, serviceId); 62775 }, delay); 62776 } 62777 _conTicket.newTicket = function(staffId, staffName, isFA) { 62778 var clientInput = document.getElementById("pos-staff-list-client").value; 62779 var clientResult = UTIL.getNameAndPhone(clientInput); 62780 var isDefaultToProduct = false; 62781 62782 SA.Ticket.reset(); 62783 GLO.Popup.closeIfExist($('#pop-staff-preview').closest('.glopop')); 62784 62785 if (!UTIL.isEmpty(staffId)) { 62786 SA.POS.setStaff(staffId, staffName, isFA); 62787 } else { 62788 staffId = UserPortal.getFirstAvailableStaffId(); 62789 62790 if (!UTIL.isEmpty(staffId)) { 62791 staffName = UserPortal.getStaffName(staffId); 62792 SA.POS.setStaff(staffId, staffName, true); 62793 } else if (SA.POS.inventory_json.products.length < 30) { 62794 _conTicket.openSelectStaff(); 62795 } else { 62796 isDefaultToProduct = true; 62797 } 62798 } 62799 62800 SA.Ticket.displayTicket(); 62801 62802 if (isDefaultToProduct) { 62803 SA.POS.toggleList('products'); 62804 } else if (innerWidth > 970) { 62805 $('#pos-service-group-list:visible').find('.pos-type-list').eq(0).click(); 62806 } 62807 62808 _newTicketDateTime(); 62809 _newTicketAddClient(clientResult); 62810 } 62811 function _newTicketAddClient(clientResult) { 62812 if (clientResult && (clientResult.hasNameAndPhone || (clientResult.fname.length > 1 && clientResult.lname.length > 1))) { 62813 _conTicket.addClientNewOpen2(clientResult); 62814 } 62815 } 62816 function _newTicketDateTime() { 62817 var jday = $('#Ticket_day'); 62818 var jtime = $('#Ticket_tm'); 62819 62820 var day = new Date().toGloDate(); 62821 var tm = new Date().toGloTime(); 62822 62823 jday.val(day); 62824 UI.setTimeMaskValue(jtime, tm); 62825 _time = tm; 62826 } 62827 _conTicket.newTicket_Original = function() { 62828 if (_conTicket.hasUnsavedChange()) { 62829 var msg = '<div style="margin-left: 12px; margin-top: 12px; margin-bottom: 24px; letter-spacing: 1px; font-size: 116%;">' + SA.Resource.SaveTicketForLater + '?</div>'; 62830 var jpop = GLO.Popup.Confirm.open(msg, 'Un-Saved Changes', SA.Ticket.saveForLater, SA.Ticket.reset).getPopup(); 62831 var jbtns = jpop.find('.pop-buttons').css({ "margin-bottom": "12px" }); 62832 62833 var noCSS = { "padding": "8px 24px", "border": "none", "border-radius": "24px", "font-family": "arial", "font-size": "20px", "background-color": "black", "color": "white" }; 62834 62835 jbtns.find('.btnNo').css({ "margin": 0 }).find('> a').css(noCSS); 62836 jbtns.find('.btnYes').addClass('btnSave').find('> a').css({ "padding": "8px 24px", "font-family": "arial", "font-size": "20px" }); 62837 } else { 62838 _conTicket.clearTicket(); 62839 } 62840 } 62841 _conTicket.clearTicket = function() { 62842 GLO.UI.Form.resetProcessing(); 62843 62844 if ($('#pos-container').hasClass('edit-pos')) { 62845 SA.POS.Edit.changeMode(); 62846 } 62847 62848 _conTicket.hideChangeDue(); 62849 _conTicket.reset(null, true); 62850 //_conTicket.displayStaffScreen(); 62851 } 62852 _conTicket.saveForLater = function() { 62853 var jsonPostOpen = { "save_and_reset_fl": true }; 62854 var btnSaveTicket = $('#pos-ticket-footer #btnSaveTicket'); 62855 62856 _conTicket.openTicket(btnSaveTicket, null, null, null, null, jsonPostOpen); 62857 } 62858 62859 _conTicket.addClientToPosTicket = function(smid, cid, cnm, ctype, uiItem) { 62860 if (!GLO.isPOS) { return; } 62861 if (UTIL.isEmpty(cid)) { return; } 62862 62863 var jticket = $('#pos-ticket'); 62864 62865 if (smid != jticket.attr('schedule_multi_id')) { 62866 return; 62867 } 62868 62869 var firstCharacter = UTIL.cleanString(cid).substring(0,1); 62870 62871 if (firstCharacter === 'S') { 62872 return; 62873 } else if (firstCharacter === 'C') { 62874 cid = UTIL.cleanString(cid.substring(1)); 62875 } 62876 62877 if (uiItem && uiItem.id) { 62878 SA.Ticket.addClientCompleteFromAutoComplete(cid, cnm, ctype, uiItem); 62879 } else { 62880 ctype = $.trim(ctype); 62881 SA.Ticket.addClientComplete(cid, cnm, ctype); 62882 } 62883 62884 //_conTicket.clientId = cid; 62885 //_conTicket.clientName = cnm; //UTIL.htmlEncode2(cnm); 62886 //_conTicket.clientType = $.trim(ctype); 62887 62888 //jticket.find('input').val(cnm); 62889 } 62890 62891 _conTicket.ToggleInvoiceFields = function(clientId, clientName, clientType, uiItem) { 62892 var hasNote = uiItem.has_note_fl, cftid = uiItem.cftid, mid = uiItem.membership_id, giftBalance = uiItem.gift_balance_mn; 62893 var pts = uiItem.loyalty_points_nr, tagCount = uiItem.tag_count_sr, birth = uiItem.birth_sr, referId = uiItem.provider_referral_id; 62894 var ctype = UTIL.coalesceInt(clientType, uiItem.client_type_cd); 62895 62896 SA.Ticket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, mid, giftBalance, pts, tagCount, birth, referId); 62897 } 62898 62899 _conTicket.ToggleInvoiceFields = function() { 62900 var isInvoicePaymentRequired = $('#toggleInvoicePayment').is(':checked'); 62901 62902 if (isInvoicePaymentRequired) { 62903 if ($('#invoice-payment-fields').hasClass('hide')) { 62904 $('#invoice-payment-fields').removeClass('hide'); 62905 62906 if (!UI.Keypad.isButtonBased()) { 62907 $('#add-invoice-due-date').css({'text-align':'center','margin-bottom':'10px','float':'','width':'100%'});
62908 $('#add-invoice-client-note').css({'text-align':'center','float':'','width':'100%'}); 62909 } 62910 else { 62911 $('#add-invoice-due-date').css({'text-align':'center','width':'50%','float':'left','margin-bottom':''}); 62912 $('#add-invoice-client-note').css({'text-align':'center','width':'50%','float':'right'}); 62913 } 62914 } 62915 } else { 62916 $('#invoice-payment-fields').addClass('hide'); 62917 } 62918 } 62919 62920 _conTicket.VoidInvoice = function(smid, btn) { 62921 var uri = GLO.Link.Object.AppointmentAjax + 'voidinvoice'; 62922 var invoiceData = { "smid": UTIL.coalesceInt(smid, UserPortal.Edit.scheduleMultiId) }; 62923 var jsonInvoiceData = JSON.stringify(invoiceData); 62924 62925 GLO.UI.Form.beginProcessing($(btn)); 62926 62927 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonInvoiceData, contentType: "application/json" }) 62928 .success(function(data, textStatus, jqXHR) { 62929 window.onbeforeunload = null; 62930 62931 new GLO.Popup.Success('Invoice Voided.', 1000); 62932 62933 GLO.Popup.closeIfExist($('#enter-email-invoice-payment-container').closest('.glopop')); 62934 GLO.Popup.closeIfExist($('#enter-text-invoice-payment-container').closest('.glopop')); 62935 }) 62936 .error(function(jqXHR, textStatus, errorThrown) { 62937 GLO.UI.Form.resetProcessing(); 62938 new GLO.Popup.Error('Unable to Void Invoice'); 62939 }); 62940 } 62941 62942 _conTicket.SendInvoiceToClient = function(pid,smid,amount,message,cid,duedate) { 62943 62944 // var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice'; 62945 var uri = GLO.Link.Object.AppointmentAjax + 'sendinvoice'; 62946 62947 // var jpop = $('#pax-wifi-setup').closest('.glopop'); 62948 // var ipAddress = jpop.find('#pax-wifi-ip').val(); 62949 // //remove leading zeros from ip 62950 // var cleanIPAddress = ipAddress.replace(/(^|\.)0+(?=[^.])/g, '.'); 62951 // var jPricePop = $('#appt-price-popup').closest('.glopop'); 62952 var invoiceTicket = { 62953 "ProviderId":GLO.Data.provider.id, 62954 "ScheduleMultiId":UserPortal.Edit.scheduleMultiId, 62955 "InvoiceAmount":$('#Invoice_Amount_vc').val(), 62956 "InvoiceNote": UTIL.htmlEncode4($('#Invoice_Client_note_vc').val()), 62957 "ClientId":UserPortal.Price.getClientId(), 62958 "InvoiceDueDate":$('#Invoice_due_dt').val() 62959 }; 62960 62961 var jsonInvoiceTicket = JSON.stringify(invoiceTicket); 62962 62963 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonInvoiceTicket, contentType: "application/json" }) 62964 .success(function(data, textStatus, jqXHR) { 62965 window.onbeforeunload = null; 62966 //update the device list table 62967 // _pax.ShowSelectedWifiDeviceInDeviceList(data); 62968 //_pax.setvar(data.DeviceId); 62969 new GLO.Popup.Success('Invoice Sent.', 1000); 62970 GLO.Popup.close($('#pop-invoice-header').closest('.glopop')); 62971 }) 62972 .error(function(jqXHR, textStatus, errorThrown) { 62973 GLO.UI.Form.resetProcessing(); 62974 new GLO.Popup.Error('Unable to Send Invoice'); 62975 }); 62976 } 62977 62978 return _conTicket; 62979})(); 62980 62981SA.TicketCard = (function() { 62982 function _cTicketCard() { } 62983 var _cards = [], _smids = [], _staffSummary = []; 62984 62985 _cTicketCard.openTicket = function(tr) { 62986 var jtr = $(tr); 62987 var jclient = _getSigninClient(jtr); 62988 var isStaffPreview = jtr.closest('#pop-staff-preview').length; 62989 62990 jclient = _addBookingAttributes(jtr, jclient, isStaffPreview); 62991 62992 if (isStaffPreview) { 62993 var bkgData = _getSigninServicesFromStaffPreview(jtr, jclient); 62994 } else { 62995 var bkgData = _getSigninServicesFromPosTicketCard(jtr, jclient); 62996 } 62997 62998 SA.Ticket.loadTicket(bkgData); 62999 63000 if (UTIL.isNumber(jtr.attr('wait_id'))) { 63001 UserPortal.waitListId = parseInt(jtr.attr('wait_id')); 63002 SA.Ticket.waitId = UserPortal.waitListId; 63003 } 63004 63005 if (isStaffPreview) { 63006 GLO.Popup.closeIfExist($('#pop-staff-preview').closest('.glopop')); 63007 } 63008 } 63009 _cTicketCard.openSignin = function(waitId) { 63010 var jpanel = $('#pos-panel-client-list'); 63011 jpanel.find('tr.pos-ticket-card[wait_id="' + waitId + '"]').click(); 63012 } 63013 63014 function _getSigninServicesFromStaffPreview(jtr, jclient) { 63015 var faId = UserPortal.getFirstAvailableStaffId(); 63016 var staffId = null, staffName = '', arrSvc = [], bkgData = '';
63017 var jservices = jtr.find('.staff-preview-service .staff-preview-line-amount'); 63018 var jservices2 = jtr.find('.staff-preview-service .staff-preview-line-amount-other'); 63019 63020 for (var i=0; i < jservices.length; i++) { 63021 var svcid = jservices.eq(i).attr('service_id'); 63022 var sid = jservices.eq(i).attr('staff_id'); 63023 var price = UTIL.coalesceMoney(jservices.eq(i).find('.line-total').text()); 63024 63025 arrSvc.push({ "service_id": svcid, "staff_id": sid, "price_mn": price }); 63026 } 63027 63028 for (var i=0; i < jservices2.length; i++) { 63029 var svcid = jservices2.eq(i).attr('service_id'); 63030 var sid = jservices2.eq(i).attr('staff_id'); 63031 var price = UTIL.coaleceMoney(jservices2.eq(i).attr('price_mn')); 63032 63033 arrSvc.push({ "service_id": svcid, "staff_id": sid, "price_mn": price }); 63034 } 63035 63036 for (var a=0; a < arrSvc.length; a++) { 63037 if (a == 0) { 63038 jclient.attr('multi_appt_count_sr', arrSvc.length); 63039 } else { 63040 bkgData += jclient.outerHTML(); 63041 } 63042 63043 var sid = UTIL.coalesceString(arrSvc[a].staff_id, faId); 63044 //if (!UTIL.isEmpty(sid) && UTIL.isEmpty(staffId) && !UTIL.parseBool(jservices.eq(i).attr('is_first_available_fl'))) { staffId = sid; } 63045 63046 if (sid > 0) { 63047 jclient.attr('staff_id', sid); 63048 } 63049 63050 if (arrSvc[a].service_id > 0) { 63051 var osvc = UserPortal.Booking.lookupDefault(arrSvc[a].service_id, sid); 63052 var price = UTIL.coalesceMoney(arrSvc[a].price_mn, osvc.price); 63053 63054 jclient.attr('service_id', arrSvc[a].service_id); 63055 jclient.attr('service_group_id', osvc.service_group_id); 63056 jclient.attr('price_mn', price); 63057 } 63058 63059 if (!UTIL.isEmpty(sid) && sid != faId) { 63060 jclient.attr('client_request_fl', '1'); 63061 } else { 63062 jclient.attr('client_request_fl', '0'); 63063 } 63064 } 63065 63066 bkgData += jclient.outerHTML(); 63067 return bkgData; 63068 } 63069 function _getSigninServicesFromPosTicketCard(jtr, jclient) { 63070 var faId = UserPortal.getFirstAvailableStaffId(); 63071 var staffId = null, staffName = '', arrSvc = [], bkgData = ''; 63072 var jspecialRequest = jtr.find('.pos-card-note'); 63073 var specialRequest = UTIL.coalesceString(jspecialRequest.attr('title'), jspecialRequest.text()); 63074 63075 if (!UTIL.isEmpty(specialRequest)) { 63076 jclient.attr('special_request_vcl', specialRequest); 63077 } 63078 63079 var jstaff = jtr.find('.pos-card-staff-name'); 63080 var jservices = jtr.find('.pos-card-service-name'); 63081 63082 for (var i=0; i < jservices.length; i++) { 63083 var svcid = jservices.eq(i).attr('service_id'); 63084 var sid = jservices.eq(i).attr('staff_id'); 63085 63086 if (!UTIL.isEmpty(svcid)) { 63087 arrSvc.push({ "service_id": svcid, "staff_id": sid }); 63088 } 63089 63090 if (!UTIL.isEmpty(sid) && UTIL.isEmpty(staffId) && !UTIL.parseBool(jservices.eq(i).attr('is_first_available_fl'))) { 63091 staffId = sid; 63092 } 63093 } 63094 63095 if (arrSvc.length == 0) { 63096 for (var i=0; i < jstaff.length; i++) { 63097 var sname = jstaff.eq(i).text(); 63098 var sid = jstaff.eq(i).attr('staff_id'); 63099 63100 if (!UTIL.isEmpty(sname) && faId != sid) { 63101 staffId = sid; 63102 staffName = sname; 63103 63104 jclient.attr('client_request_fl', '1').attr('staff_id', sid); 63105 break; 63106 } 63107 } 63108 } else { 63109 jclient.attr('multi_appt_count_sr', arrSvc.length); 63110 63111 for (var i=0; i < arrSvc.length; i++) { 63112 if (i > 0) { 63113 bkgData += jclient.outerHTML(); 63114 } 63115 63116 var sid = UTIL.coalesceString(arrSvc[i].staff_id, faId); 63117 var osvc = UserPortal.Booking.lookupDefault(arrSvc[i].service_id, sid); 63118 var price = UTIL.coalesceMoney(osvc.price); 63119 63120 jclient.attr('price_mn', price); 63121 jclient.attr('staff_id', sid); 63122 jclient.attr('service_id', arrSvc[i].service_id); 63123 jclient.attr('service_group_id', osvc.service_group_id); 63124 63125 if (!UTIL.isEmpty(sid) && sid != faId) { 63126 jclient.attr('client_request_fl', '1'); 63127 } else { 63128 jclient.attr('client_request_fl', '0'); 63129 } 63130 } 63131 } 63132 63133 bkgData += jclient.outerHTML(); 63134 return bkgData; 63135 } 63136 63137 function _addBookingAttributes(jtr, jclient, isStaffPreview) { 63138 var waitId = jtr.attr('wait_id'); 63139 var note = UTIL.cleanString(UTIL.coalesceString(jtr.find('.pos-card-note').text(), jtr.find('.special-request-icon').attr('title'))); 63140
63141 var day = new Date().toGloDate(); 63142 var time = new Date().toGloTime(); 63143 63144 if (isStaffPreview) { 63145 var signinDate = jtr.find('.staff-preview-signin-icon').attr('signin_dt'); 63146 } else { 63147 var signinTime = UTIL.directTagOnly(jtr.find('.pos-card-start')); 63148 63149 if (UTIL.isValidTime(signinTime)) { 63150 var signinDate = day + ' ' + signinTime; 63151 time = signinTime; 63152 } else { 63153 var signinDate = day + ' ' + new Date().toGloTime(); 63154 } 63155 } 63156 63157 jclient.attr('wait_id', waitId).attr('provider_id', GLO.Data.provider.id); 63158 jclient.attr('special_request_vcl', note); 63159 63160 jclient.attr('appt_dt', day); 63161 jclient.attr('time_vc', time); 63162 63163 if (UTIL.isDate(signinDate)) { 63164 jclient.attr('signin_dt', signinDate); 63165 } 63166 63167 return jclient; 63168 } 63169 function _getSigninClient(jtr) { 63170 var jclient = jtr.find('.pos-card-client'); 63171 63172 if (jclient.length) { 63173 var cid = jclient.attr('client_id'), ctype = UTIL.coalesceInt(jclient.attr('client_type_cd'), 1); 63174 var cname = UTIL.replaceQuotes(jclient.text()); 63175 } else { 63176 var jclient = jtr.find('.staff-preview-client'); 63177 var jcname = jclient.find('.staff-preview-client-name'); 63178 63179 var cid = jclient.attr('client_id'), ctype = UTIL.coalesceInt(jclient.attr('client_type_cd'), 1); 63180 var cname = UTIL.replaceQuotes(UTIL.coalesceString(jcname.attr('title'), jcname.text())); 63181 } 63182 63183 var birth = jclient.attr('birth_sr'); 63184 var gift = jclient.attr('gift_balance_mn'), membershipId = jclient.attr('membership_id'), tagCount = jclient.attr('tag_count_sr'); 63185 var pts = jclient.attr('loyalty_points_nr'), cftid = jclient.attr('cftid'); 63186 var importantNote = jclient.attr('important_note_vc'), otherNote = jclient.attr('other_note_vc'); 63187 63188 var tr = $('<tr client_id="' + cid + '" client_vc="' + cname + '" client_type_cd="' + ctype + '"/>'); 63189 63190 if (birth > 0) { 63191 tr.attr('birth_sr', birth); 63192 } 63193 63194 if (gift > 0) { 63195 tr.attr('gift_balance_mn', gift); 63196 } 63197 63198 if (membershipId > 0) { 63199 tr.attr('membership_id', membershipId); 63200 } 63201 63202 if (tagCount > 0) { 63203 tr.attr('tag_count_sr', tagCount); 63204 } 63205 63206 if (pts > 0) { 63207 tr.attr('client_loyalty_nr', pts); 63208 } 63209 63210 if (cftid > 0) { 63211 tr.attr('cftid', cftid); 63212 } 63213 63214 if (!UTIL.isEmpty(importantNote)) { 63215 tr.attr('staff_note_vcl', importantNote); 63216 } 63217 63218 return tr; 63219 } 63220 63221 _cTicketCard.displayCards = function() { 63222 var htm = ''; 63223 var firstAvailableId = UserPortal.getFirstAvailableStaffId(); 63224 63225 for (var i=0; i < _cards.length; i++) { 63226 if (_cards[i].status != 270) { //= do NOT display no-show or late-cancel 63227 htm += _getCardHtm(_cards[i], firstAvailableId); 63228 } 63229 } 63230 63231 var jpanel = $('#pos-panel-client #pos-panel-client-list'); 63232 var trSignin = jpanel.find('tr.pos-ticket-walkin'); 63233 var htmSignin = _getCardSigninRows(trSignin); 63234 var trhead = _getHeaderRow(trSignin.length); 63235 63236 htm = '<table class="tablesorter">' + trhead + '<tbody>' + htmSignin + htm + '</tbody></table>'; 63237 63238 jpanel.html(htm); 63239 var jtbl = jpanel.find('> table'); 63240 UI.initTableSorter(jtbl); 63241 63242 if (_cards.length > 0) { 63243 $('#pos-staff-list-header1 #pos-staff-list-header1-clientpanel').removeClass('hide'); 63244 } else { 63245 $('#pos-staff-list-header1 #pos-staff-list-header1-clientpanel').addClass('hide'); 63246 } 63247 63248 SA.POS.resetPanelHeight(); 63249 } 63250 function _getHeaderRow(waitRowCount) { 63251 if (waitRowCount == 0 && _cards.length === 0) { 63252 return ''; 63253 } else { 63254 return '<thead><tr>' 63255 + '<th class="pos-card-staff">Staff</th>' 63256 + '<th class="pos-card-start">Start</th>' 63257 + '<th class="pos-card-client">Client</th>' 63258 63259 + '<th class="pos-card-service">Service</th>' 63260 + '<th class="pos-card-update">Last Update</th>' 63261 + '<th class="pos-card-price">Price</th>' 63262 + '</tr></thead>'; 63263 } 63264 } 63265 function _getCardSigninRows(trSignin) { 63266 var htm = ''; 63267 63268 for (var w=0; w < trSignin.length; w++) { 63269 htm += trSignin.eq(w).outerHTML(); 63270 } 63271 63272 return htm; 63273 } 63274 function _getCardHtm(card, firstAvailableId) { 63275 var css = _getStatusCss(card.status); 63276 var onclick = ' onclick="UserPortal.getTicket(' + card.schedule_multi_id + ', ' + card.booking_nr + ', null, false, true)"'; 63277 var htm = '<tr class="pos-ticket-appt pos-ticket-card ' + css + '" schedule_multi_id="' + card.schedule_multi_id + '"' + onclick + '>'; 63278 63279 htm += _getCardStaffHtm(card, firstAvailableId); 63280 htm += _getCardStartHtm(card); 63281 htm += _getCardClientHtm(card); 63282 63283 htm += _getCardServiceHtm(card); 63284 htm += _getCardLastUpdateHtm(card) + '</span>'; 63285 htm += _getCardPriceHtm(card); 63286 63287 return htm + '</tr>'; 63288 } 63289 function _getCardStartHtm(card) { 63290 var htmDiff = '', htmIcon = ''; 63291 var htmStart = '<span class="pos-card-start-time">' + card.start_tm + '</span>'; 63292 63293 if (card.status == 5 || card.status == 29) { 63294 var diffMinutes = UTIL.coalesceInt((new Date(card.start_dt).getTime() - new Date().getTime()) / 60 / 1000, 0); 63295 63296 if (diffMinutes > 0) { 63297 var label = 'early'; 63298 } else { 63299 var label = 'late'; 63300 } 63301 63302 css = 'pos-start-diff pos-card-' + label; 63303 htmDiff = '<span class="' + css + '"><b>' + Math.abs(diffMinutes) + ' min ' + label + '</b></span>'; 63304 } 63305 63306 if (card.schedule_multi_id > 0) { 63307 if ( (card.start_dt - card.create_dt) / (60*60*1000) > 1 ) { //appt created > 1 hr before start 63308 var title = 'Appointment Created on ' + card.create_dt.toGloDateString(); 63309 htmIcon = '<b class="pre-booked-appointment-icon" title="' + title + '"><span></span></b>'; 63310 } else { 63311 //htmIcon = '<span class="walkin-icon"><b>walk-in</b></span>'; 63312 //htmIcon = '<span class="walkin-icon" title="Walk-In"><b style="top: inherit; left: inherit; bottom: -14px; right: -90px;">W</b></span>'; 63313 } 63314 } 63315 63316 return '<td class="pos-card-start">' + htmIcon + htmDiff + htmStart + '</td>'; 63317 } 63318 function _getCardClientHtm(card) { 63319 var icons = '', clientTitle = '', clientName = UTIL.cleanString(card.services[0].client_vc); 63320 63321 if (clientName.length > 2 && card.services[0].client_type_cd == 1) { 63322 icons += '<span class="new-client-text-icon" title="New Client"><b>new</b></span>'; 63323 63324 if (UTIL.startsWith(clientName, '* ')) { 63325 clientName = clientName.substring(2); 63326 } 63327 } 63328 63329 if (clientName.length > 20) { 63330 clientTitle = ' title="' + UTIL.replaceQuotes(clientName) + '"'; 63331 } 63332
63333 return '<td class="pos-card-client"' + clientTitle + '>' + UTIL.maxString(clientName, 20, true) + icons + '</td>'; 63334 } 63335 function _getCardStaffHtm(card, firstAvailableId) { 63336 var arrStaff = [], htm = ''; 63337 var start = new Date(card.start_dt).toGloDateTime(); 63338 63339 for (var i=0; i < card.services.length; i++) { 63340 var staffId = card.services[i].staff_id; 63341 63342 if (staffId && !arrStaff.has(staffId) && firstAvailableId != staffId) { //&& start == new Date(card.services[i].start).toGloDateTime() 63343 var staffTitle = '', htmRequested = '', staffName = card.services[i].staff_vc; 63344 63345 if (UTIL.parseBool(card.client_request_fl)) { 63346 htmRequested = '<b class="checkmark-icon"></b>'; 63347 } 63348 63349 if (UTIL.isEmpty(staffName)) { 63350 staffName = UserPortal.getStaffName(staffId); 63351 } 63352 63353 if (staffName.length > 10) { 63354 staffTitle = ' title="' + UTIL.replaceQuotes(staffName) + '"'; 63355 } 63356 63357 arrStaff.push(staffId); 63358 htm += '<span class="pos-card-staff-name pos-card-staff' + arrStaff.length + '"' + staffTitle + '>' + UTIL.maxString(staffName, 10, true) + '</span>'; 63359 } 63360 } 63361 63362 return '<td class="pos-card-staff">' + htm + '</td>'; 63363 } 63364 function _getCardServiceHtm(card) { 63365 var arrService = [], htm = ''; 63366 var start = new Date(card.start_dt).toGloDateTime(); 63367 63368 for (var i=0; i < card.services.length; i++) { 63369 if (start == new Date(card.services[i].start).toGloDateTime() && !arrService.has(card.services[i].service_id)) { 63370 var title = '', name = card.services[i].service_name_vc; 63371 63372 if (name.length > 15) { 63373 title = ' title="' + UTIL.replaceQuotes(name) + '"'; 63374 } 63375 63376 arrService.push(card.services[i].service_id); 63377 htm += '<span class="pos-card-service-name pos-card-service' + arrService.length + '"' + title + '>' + UTIL.maxString(name, 15, true) + '</span>'; 63378 } 63379 } 63380 63381 return '<td class="pos-card-service">' + htm + '</td>'; 63382 } 63383 function _getCardLastUpdateHtm(card) { 63384 var htm = '', htmDue = ''; 63385 var lastUpdateDate = new Date(card.services[0].last_update_dt); 63386 var lastUpdateBy = card.services[0].update_by_vc; 63387 63388 for (var i=1; i < card.services.length; i++) { 63389 if (new Date(card.services[i].last_update_dt) > lastUpdateDate) { 63390 lastUpdateDate = new Date(card.services[i].last_update_dt); 63391 lastUpdateBy = card.services[i].update_by_vc; 63392 } 63393 } 63394 63395 var lastUpdateTitle = 'Last Update by ' + lastUpdateBy + ' at ' + lastUpdateDate.toGloTime() + ' on ' + lastUpdateDate.toGloDateString(true, true); 63396 var hourDiff = UTIL.coalesceInt( (new Date() - lastUpdateDate) / (60*60*1000), 0); 63397 63398 if (hourDiff < 2) { 63399 var minuteDiff = UTIL.coalesceInt( (new Date() - lastUpdateDate) / (1000 * 60), 0); 63400 updateLabel = UTIL.pluralLabel(minuteDiff, 'min') + ' ago'; 63401 } else if (hourDiff < 25) { 63402 updateLabel = UTIL.pluralLabel(hourDiff, 'hour') + ' ago'; 63403 } else if (new Date().addDays(-1).toGloDate() == lastUpdateDate.toGloDate()) { 63404 updateLabel = 'yesterday'; 63405 } else { 63406 var dayDiff = UTIL.dayDiff(lastUpdateDate, new Date()) + 1; 63407 updateLabel = UTIL.pluralLabel(dayDiff, 'day') + ' ago'; 63408 } 63409 63410 if (card.price_mn > 0 && card.payment_mn > 0) { 63411 var due = UTIL.coalesceMoney(card.price_mn - card.payment_mn); 63412 var cssDue = 'pos-ticket-update-due'; 63413 var title = 'Price = ' + UTIL.displayMoney(card.price_mn); 63414 63415 if (card.payment_mn > 0) { 63416 title = 'Payment = ' + UTIL.displayMoney(card.payment_mn) + ' | ' + title; 63417 } 63418 63419 if (due > 0) { 63420 due = '<small>Due</small> <span class="dollar-sign">$</span><span>' + UTIL.displayMoney(due, true) + '</span>'; 63421 } else { 63422 due = 'PAID'; 63423 cssDue += ' pos-ticket-update-paid'; 63424 } 63425 63426 htmDue = '<b class="' + cssDue + '" title="' + title + '">' + due + '</b>'; 63427 } 63428 63429 var htmUpdate = '<i class="pos-ticket-update-label" title="' + lastUpdateTitle + '">' + updateLabel + '</i>'; 63430 return '<td class="pos-card-update"><span class="pos-card-update2">' + htmUpdate + htmDue + '</span></td>'; 63431 } 63432 function _getCardPriceHtm(card) { 63433 var price = UTIL.coalesceMoney(card.price_mn); 63434 var tip = UTIL.coalesceMoney(card.tip_mn); 63435 var payment = UTIL.coalesceMoney(card.payment_mn); 63436 var css = '', htmPrice = '', htmTip = ''; 63437 63438 if (price > 0) { 63439 if (payment >= price) { 63440 css = ' appt-paid'; 63441 } 63442
63443 htmPrice = '<b class="pos-card-client-price">' + UTIL.displayMoney(price) + '</b>'; 63444 } 63445 63446 if (tip > 0) { 63447 htmTip = '<i class="plus-sign">+</i><span class="dollar-sign">$</span><i>' + UTIL.displayMoney(tip, true) + '</i>'; 63448 htmTip = '<b class="pos-card-client-tip" title="Tip = $' + tip + '">' + htmTip + '</b>'; 63449 } 63450 63451 return '<td class="pos-card-price' + css + '">' + htmPrice + htmTip + '</td>'; 63452 } 63453 63454 function _createStaffSummary() { 63455 var arr = []; 63456 63457 for (var i=0; i < GLO.staffResources.length; i++) { 63458 if (!GLO.staffResources.is_first_available_fl) { 63459 var ss = structuredClone(GLO.staffResources[i]); 63460 63461 ss.price_mn = 0; 63462 ss.service_sr = 0; 63463 ss.turn_sr = 0; 63464 ss.ticket_sr = 0; 63465 ss.smids = []; 63466 63467 arr.push(ss); 63468 } 63469 } 63470 63471 return arr; 63472 } 63473 function _updateStaffSummary(staffSummary, calEvent) { 63474 if (calEvent.appt_status_cd == 21 || calEvent.appt_status_cd == 22 || calEvent.appt_status_cd == 25) { 63475 for (var i=0; i < staffSummary.length; i++) { 63476 if (staffSummary[i].id == calEvent.staff_id) { 63477 staffSummary[i].price_mn = UTIL.coalesceMoney(staffSummary[i].price_mn, 0) + UTIL.coalesceMoney(calEvent.price_mn); 63478 63479 staffSummary[i].service_sr = UTIL.coalesceInt(staffSummary[i].service_sr, 0) + 1; 63480 staffSummary[i].turn_sr = UTIL.coalesceInt(staffSummary[i].turn_sr, 0) + 1; 63481 63482 if (!staffSummary[i].smids.has(calEvent.schedule_multi_id)) { 63483 staffSummary[i].smids.push(calEvent.schedule_multi_id); 63484 staffSummary[i].ticket_sr = UTIL.coalesceInt(staffSummary[i].ticket_sr, 0) + 1; 63485 } 63486 63487 return; 63488 } 63489 } 63490 } 63491 } 63492 _cTicketCard.getStaffSummary = function() { //returns copy of staffSummary (so doesn't reload array during processing) 63493 return _staffSummary.slice(); 63494 } 63495 63496 _cTicketCard.loadAppointments = function(calEvents) { 63497 var offHourSGID = UserPortal.getOffTimeServiceGroupId(); 63498 var internalSGID = UserPortal.getInternalServiceGroupId(); 63499 var staffSummary = _createStaffSummary(); 63500 _cards = []; 63501 _smids = []; 63502 63503 if (calEvents) { 63504 for (var i=0; i < calEvents.length; i++) { 63505 var ev = calEvents[i]; 63506 63507 if (ev.service_group_id != offHourSGID && ev.service_group_id != internalSGID && !UTIL.parseBool(ev.is_finish_out_fl)) { 63508 if (_smids.has(ev.schedule_multi_id)) { 63509 _updateCard(ev); 63510 } else { 63511 _addCard(ev); 63512 } 63513 63514 _updateStaffSummary(staffSummary, ev); 63515 } 63516 } 63517 63518 _cards.sort(_sortCards); 63519 } 63520 63521 staffSummary.sort(_sortStaffSummary); 63522 _staffSummary = staffSummary; 63523 _cTicketCard.displayCards(); 63524 } 63525 63526 function _addCard(ev) { 63527 var status = _getStatus(ev); 63528 var dt = new Date(ev.start); 63529 var tm = dt.toGloTime(); 63530 63531 var pmt = UTIL.coalesceMoney(ev.total_payment_mn), tip = UTIL.coalesceMoney(ev.tip_mn); 63532 var price = UTIL.coalesceMoney(ev.price_mn) + UTIL.coalesceMoney(ev.tax_mn) + tip; // - UTIL.coalesceMoney(ev.discount_mn) + UTIL.coalesceMoney(ev.add_on_fee_mn) 63533 price = UTIL.coalesceMoney(price + UTIL.coalesceMoney(ev.inventory_price_mn) - UTIL.coalesceMoney(ev.total_discount_mn) + UTIL.coalesceMoney(ev.total_AddOnFee_mn)); 63534 63535 var card = { 63536 "schedule_multi_id": ev.schedule_multi_id, "booking_nr": ev.booking_nr, "price_mn": price, "tip_mn": tip, "payment_mn": pmt, "status": status 63537 , "client_request_fl": ev.client_request_fl, "start_dt": dt, "start_tm": tm, "start_sr": UTIL.timeToInt(tm), "create_dt": new Date(ev.create_dt), "services": [] 63538 }; 63539 63540 card.services.push(ev); 63541 _cards.push(card); 63542 _smids.push(ev.schedule_multi_id); 63543 } 63544 function _updateCard(ev) { 63545 var card = _findCard(ev.schedule_multi_id); 63546 var tip = UTIL.coalesceMoney(ev.tip_mn); 63547 var price = UTIL.coalesceMoney(ev.price_mn) + UTIL.coalesceMoney(ev.tax_mn) + tip; // - UTIL.coalesceMoney(ev.discount_mn) + UTIL.coalesceMoney(ev.add_on_fee_mn) 63548 63549 if (card.create_dt > new Date(ev.create_dt)) { 63550 card.create_dt = new Date(ev.create_dt); 63551 } 63552 63553 if (UTIL.parseBool(ev.client_request_fl)) { 63554 card.client_request_fl = 1; 63555 } 63556 63557 card.tip_mn = UTIL.coalesceMoney(card.tip_mn + tip); 63558 card.price_mn = UTIL.coalesceMoney(card.price_mn + price); 63559 card.services.push(ev); 63560 } 63561 function _findCard(smid) { 63562 for (var i=0; i < _cards.length; i++) { 63563 if (smid == _cards[i].schedule_multi_id) { 63564 return _cards[i]; 63565 } 63566 } 63567 63568 return null; 63569 } 63570 63571 function _sortStaffSummary(staff1, staff2) { 63572 if (staff1.turn_sr < staff2.turn_sr) { 63573 return -1; 63574 } else if (staff1.turn_sr > staff2.turn_sr) { 63575 return 1; 63576 63577 } else if (staff1.price_mn < staff2.price_mn) { 63578 return -1; 63579 } else if (staff1.price_mn > staff2.price_mn) { 63580 return 1; 63581 63582 } else { 63583 return 0; 63584 } 63585 } 63586 63587 function _sortCards(card1, card2) { 63588 if (card1.status < card2.status) { 63589 return -1; 63590 } else if (card1.status > card2.status) { 63591 return 1; 63592 63593 } else if (card1.start_sr < card2.start_sr) { 63594 return -1; 63595 } else if (card1.start_sr > card2.start_sr) { 63596 return 1; 63597 63598 } else { 63599 return 0; 63600 } 63601 } 63602 63603 function _getStatus(ev) { 63604 var dtStart = new Date(ev.start); 63605 63606 if (ev.appt_status_cd == 22) { //= checked-out || UTIL.isDate(ev.checkout_dt) 63607 return 120; 63608 } else if (ev.appt_status_cd == 21) { //= checked-in || UTIL.isDate(ev.checkin_dt) 63609 return 21; 63610 } else if (ev.appt_status_cd == 13) { //= no-show or late-cancel 63611 return 130; 63612 } else if (ev.appt_status_cd == 14) { //= no-show or late-cancel 63613 return 140; 63614 } else if (ev.appt_status_cd == 25) { //= ready to pay 63615 return 25; 63616 } else if (UTIL.isDate(ev.signin_dt) && new Date(ev.signin_dt).toGloDate(
63616) == new Date().toGloDate()) { //= client sign-in 63617 return 2; 63618 } else { 63619 var diffMinutes = (new Date().getTime() - dtStart.getTime()) / 60 / 1000; 63620 63621 if (Math.abs(diffMinutes) < 16) { //= now 63622 return 5; 63623 } else if (diffMinutes > 0 && diffMinutes < 60) { //= late (appt start time < 60 minutes in the past) 63624 return 29; 63625 } else if (dtStart > new Date()) { //= upcoming 63626 return 41; 63627 } else if (dtStart < new Date()) { //= past 63628 return 60; 63629 } 63630 } 63631 63632 return 40; 63633 } 63634 function _getStatusCss(status) { 63635 var css = 'cardstatus' + status + ' '; 63636 63637 if (status == 2) { //= client sign-in 63638 css += 'card-signin'; 63639 } else if (status == 5) { //= now 63640 css += 'card-now'; 63641 63642 } else if (status == 21) { //= checked-in 63643 css += 'card-checkin'; 63644 } else if (status == 25) { //= ready to pay 63645 css += 'card-ready'; 63646 } else if (status == 29) { //= late 63647 css += 'card-late'; 63648 63649 } else if (status >= 40 && status <= 49) { //= upcoming 63650 css += 'card-upcoming'; 63651 } else if (status >= 90 && status <= 99) { //= past 63652 css += 'card-past'; 63653 63654 } else if (status == 120) { //= checked-out 63655 css += 'card-checkout'; 63656 } else if (status == 130) { //= no-show 63657 css += 'card-noshow'; 63658 } else if (status == 140) { //= late-cancel 63659 css += 'card-late-cancel'; 63660 } 63661 63662 return css; 63663 } 63664 63665 function _loadSigninData(data) { 63666 var jpanel = $('#pos-panel-client #pos-panel-client-list > table'); 63667 jpanel.find('tr.pos-ticket-walkin').remove(); 63668 jpanel.prepend($(data).html()); 63669 63670 _cTicketCard.displayCards(); 63671 _updateSigninCount(data); 63672 } 63673 63674 function _updateSigninCount(data) { 63675 var jstaff = $('#pos-staff-screen').find('.pos-staff-cell'); 63676 var trSignin = $(data).find('tr'); 63677 var faid = UserPortal.getFirstAvailableStaffId(); 63678 63679 for (var a=0; a < trSignin.length; a++) { 63680 var jss = trSignin.eq(a).find('.pos-card-staff-name'); 63681 63682 if (jss.length == 0 && faid > 0) { 63683 for (var r=0; r < GLO.resourceHours.length; r++) { 63684 if (GLO.resourceHours[r].id == faid) { 63685 GLO.resourceHours[r].walkin_signin_sr = UTIL.coalesceInt(GLO.resourceHours[r].walkin_signin_sr, 0) + 1; 63686 } 63687 } 63688 } else { 63689 for (var b=0; b < jss.length; b++) { 63690 var staffId = jss.eq(b).attr('staff_id'); 63691 63692 for (var r=0; r < GLO.resourceHours.length; r++) { 63693 if (GLO.resourceHours[r].id == staffId) { 63694 GLO.resourceHours[r].walkin_signin_sr = UTIL.coalesceInt(GLO.resourceHours[r].walkin_signin_sr, 0) + 1; 63695 } 63696 } 63697 } 63698 } 63699 } 63700 63701 for (var i=0; i < GLO.resourceHours.length; i++) { 63702 if (GLO.resourceHours[i].walkin_signin_sr > 0) { 63703 var jstaff = $('#pos-staff-screen').find('.pos-staff-cell[staff_id="' + GLO.resourceHours[i].id + '"]'); 63704 var jicon = jstaff.find('.staff-appt-signin'); 63705 63706 if (jicon.length) { 63707 var jcnt = jicon.find('.staff-appt-signin-count'); 63708 var count = parseInt(jcnt.text()); 63709 var title = jcnt.attr('title') + ' with appointment | ' + GLO.resourceHours[i].walkin_signin_sr + ' sign-in without appointment'; 63710 63711 jcnt.text(parseInt(count + GLO.resourceHours[i].walkin_signin_sr)).attr('title', title); 63712 } else { 63713 var htmIcon = SA.POS.getSigninIcon(GLO.resourceHours[i].walkin_signin_sr); 63714 jstaff.prepend(htmIcon); 63715 } 63716 63717 var jlabel = jstaff.find('.staff-box-label'); 63718 var priority = UTIL.coalesceInt(jlabel.attr('priority_sr'), 99); 63719 63720 if (priority > 9) { 63721 var css = 'label-status-2', title = '', label = 'SIGN-In <i>WALK-In</i>'; 63722 var htmLabel = SA.POS.getLabelHtm(css, title, 2, 2, label); 63723 jlabel.replaceWith(htmLabel); 63724 } 63725 } 63726 } 63727 } 63728 63729 function _loadExtraClockOutsOnStaffPreview(jpop, staffId) { 63730 var jStaffCard = $('#pos-staff-list .pos-staff-cell[staff_id="' + staffId + '"]'); 63731 var jul = jStaffCard.find('#staff-prev-clock-out-list'); 63732 var jStaffPreviewHeader = jpop.find('#staff-preview-header'); 63733 63734 jStaffPreviewHeader.find('#staff-prev-clock-out-list').remove(); 63735 63736 if (jul.length) { 63737 jStaffPreviewHeader.prepend(jul.outerHTML()); 63738 } 63739 } 63740 _cTicketCard.loadExtraClockOutsOnStaffPreview = function() { 63741 var jpop = $('#pop-staff-preview').closest('.glopop'); 63742 63743 if (jpop.length) { 63744 var staffId = jpop.find('#pop-staff-preview').attr('staff_id'); 63745 63746 _loadExtraClockOutsOnStaffPreview(jpop, staffId); 63747 } 63748 } 63749 _cTicketCard.checkIfNeedReload = function(jpop, staffId, ticketCount) { 63750 if (_checkIfNeedReload2(jpop, staffId, ticketCount)) { 63751 SA.POS.refreshEvents(true); 63752 } else { 63753 _loadExtraClockOutsOnStaffPreview(jpop, staffId); 63754 } 63755 } 63756 function _checkIfNeedReload2(jpop, staffId, ticketCount) { 63757 var jStaffCard = $('#pos-staff-list .pos-staff-cell[staff_id="' + staffId + '"]'); 63758 var jcnt = jStaffCard.find('.staff-appt-count > b'); 63759 var total = 0, diff = 0; 63760 63761 for (var i=0; i < jcnt.length; i++) { 63762 total += parseInt(jcnt.eq(i).text()); 63763 } 63764 63765 if (total != ticketCount) { 63766 return true; 63767 } else { 63768 if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-signin')) { 63769 return true; 63770 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-checkin')) { 63771 return true; 63772 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-checkout')) { 63773 return true; 63774 63775 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-now')) { 63776 return true; 63777 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-late')) { 63778 return true; 63779 63780 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-upcoming')) { 63781 return true; 63782 } else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-past')) { 63783 return true; 63784 } 63785 } 63786 } 63787 function _hasTicketDiff(jpop, jStaffCard, cssClass) { 63788 var popCnt = UTIL.coalesceInt(jpop.find('.' + cssClass + ' .staff-appt-count > b').text()); 63789 var cardCnt = UTIL.coalesceInt(jStaffCard.find('.' + cssClass + ' > b').text()); 63790 } 63791 63792 _cTicketCard.refreshSigninList = function() { 63793 var url = GLO.Link.WebsiteDomain + 'pos/GetSignin?cdn=' + GLO.Data.cdnVersion; 63794
63795 $.ajax({ type: "GET", url: url, "cache": false }) 63796 .success(function(data, textStatus, jqXHR) { 63797 if ($(data).hasClass('warning')) { 63798 if (UTIL.parseBool($(data).attr('must_refresh'))) { 63799 setTimeout(function() { 63800 location.reload(); 63801 }, 450); 63802 } 63803 63804 new GLO.Popup.Warning(data); 63805 return true; 63806 } else { 63807 _loadSigninData(data); 63808 SA.TicketCard.refreshFilterPanel(); 63809 } 63810 }).error(function(jqXHR, textStatus, errorThrown) { 63811 if (textStatus == 'abort' && event && event.currentTarget && event.currentTarget.id == 'btnNewTicketQuick') { 63812 if (oj && oj.close) { 63813 oj.close(); 63814 } 63815 63816 SA.Ticket.newTicket(sid, sname, isFA); 63817 } 63818 }); 63819 } 63820 63821 _cTicketCard.refreshFilterPanel = function() { 63822 var panelFilter = GLO.Uri.hash('panel'); 63823 63824 if (!UTIL.isEmpty(panelFilter)) { 63825 SA.TicketCard.filterPanel(panelFilter, null, true); 63826 } 63827 } 63828 63829 _cTicketCard.filterPanel = function(status, btn, isRefresh) { 63830 GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop')); 63831 63832 var jpanel = $('#pos-panel-client:visible'); 63833 isRefresh = UTIL.parseBool(isRefresh); 63834 63835 if (jpanel.length == 0 && !isRefresh) { 63836 if (status == 11) { //= all appointments 63837 SA.Menu.openReportUpcomingAppointments(null, btn); 63838 } else if (status == 21 || status == 110 || status == 210) { //= checked-in 63839 SA.Menu.openReportCheckedIn(null, btn); 63840 } else if (status == 22 || status == 120 || status == 220) { //= checked-out 63841 SA.Menu.openReportCheckedOut(null, btn); 63842 } else if (status == 2) { //= client sign-in 63843 GLO.WaitList.open(); 63844 } else { //= recent 63845 SA.Menu.openReportRecent(20, btn); 63846 } 63847 63848 return; 63849 } 63850 63851 jpanel.removeClass('narrow-filter').find('.pos-ticket-card').addClass('hide'); 63852 $('#pos-card-filter-header').find('.btnAdd.selected').removeClass('selected'); 63853 63854 if (status == 1) { //= all 63855 jpanel.find('.pos-ticket-card').removeClass('hide'); 63856 } else if (status == 2) { //= sign-ins 63857 jpanel.find('.card-signin').removeClass('hide'); 63858 } else if (status == 11) { //= all appointments: now, late, upcoming / other, past 63859 jpanel.find('.cardstatus5,.cardstatus29, .cardstatus40,.cardstatus41,.cardstatus42, .cardstatus90,.cardstatus91,.cardstatus92').removeClass('hide'); 63860 } else if (status == 110) { //= checked-in | ready to pay | late 63861 jpanel.find('.cardstatus21, .cardstatus25, .cardstatus29').removeClass('hide'); 63862 } else if (status == 220) { //= completed 63863 jpanel.find('.cardstatus22, .cardstatus130, .cardstatus140').removeClass('hide'); 63864 } else { // is either: sign-in, now, or checked-out 63865 jpanel.addClass('narrow-filter').find('.cardstatus' + status).removeClass('hide'); 63866 } 63867 63868 if (!isRefresh) { 63869 document.location.hash = 'panel=' + status; 63870 63871 if (btn) { 63872 $(btn).addClass('selected'); 63873 } 63874 } 63875 } 63876 63877 _cTicketCard.openScanQRCode = function() { 63878 var msg = '<p><label for="Ticket_QR_or_Number_vc" style="margin: 0; padding: 8px;">Scan Ticket\'s QR Code or Enter Ticket Number</label></p>'; 63879 var input = '<input type="text" id="Ticket_QR_or_Number_vc" maxlength="20" onkeyup="SA.TicketCard.enterTicketNumber(this)" autocomplete="off"/>'; 63880 var htmCards = _getCardInProgress(); 63881 63882 var htm = '<div id="pop-scan-qr">' + msg + input + htmCards + '</div>'; 63883 var jpop = GLO.Popup.Custom.openSimple(htm, 'Scan QR Code'); 63884 63885 GLO.Popup.Custom.singleButton(jpop, 'Close'); 63886 SA.POS.refreshEvents(true); 63887 } 63888 _cTicketCard.enterTicketNumber = function(element) { 63889 var test = $.trim(element.value); 63890 var testOriginal = test, isFullQRTicketNumber = false; 63891 63892 if (!UTIL.isEmpty(test)) { 63893 if (test.length > 1 && test.substring(0,2) == '#p' || test.substring(0,2) == '#P') { 63894 test = test.substring(2); 63895 } else if (test.substring(0,1) == 'p' || test.substring(0,1) == 'P') { 63896 test = test.substring(1); 63897 } 63898 63899 if (test.length > 2 && test.endsWith('-qr') || test.endsWith('-QR')) { 63900 test = test.substring(0, test.length - 3); 63901 isFullQRTicketNumber = true; 63902 } else if (test.length > 1 && test.endsWith('qr') || test.endsWith('QR')) { 63903 test = test.substring(0, test.length - 2); 63904 isFullQRTicketNumber = true; 63905 } 63906 } 63907 63908 if (!UTIL.isEmpty(test)) { 63909 for (var i=0; i < _cards.length; i++) { 63910 if (_cards[i].booking_nr == test) { 63911 UserPortal.getTicket(_cards[i].schedule_multi_id, _cards[i].booking_nr, null, false, true); 63912 GLO.Popup.closeIfExist($('#pop-scan-qr').closest('.glopop')); 63913 63914 return; 63915 } 63916 } 63917 } 63918 63919 if (isFullQRTicketNumber) { 63920 var jelement = $(element); 63921 var jdiv = jelement.closest('div'); 63922 var msg = 'Ticket P' + test + ' Not Found'; 63923 63924 if (jelement.closest('#pop-scan-qr')) { 63925 var btn = '<span class="btnAdd" style="margin-left: 8px;">
63925<a onclick="UserPortal.Lookup.scanTicketLookup(' + test + ')">Lookup P' + test + ' on any date</a></span>'; 63926 msg += ' as a Ticket Today ' + btn; 63927 } 63928 63929 jdiv.find('.ticket-not-found').remove(); 63930 jelement.before('<p class="ticket-not-found">' + msg + '</p>'); 63931 element.value = ''; 63932 } 63933 63934 //console.log('SA.TicketCard.enterTicketNumber: ' + testOriginal + ' -> ' + test); 63935 } 63936 63937 function _getCardInProgress() { 63938 var htmCards = '', styleUL = '', signinCount = 0, checkinCount = 0; 63939 var trSignin = $('#pos-panel-client-list').find('tr.pos-ticket-walkin'); 63940 63941 for (var i=0; i < _cards.length; i++) { 63942 if (_cards[i].status == 2 || _cards[i].status == 21) { 63943 if (_cards[i].status == 2) { 63944 var css = 'card-signin'; 63945 ++signinCount; 63946 } else { 63947 var css = 'card-checkin'; 63948 ++checkinCount; 63949 } 63950 63951 var smid = _cards[i].schedule_multi_id, bkg = _cards[i].booking_nr; 63952 var clientName = UTIL.cleanString(_cards[i].services[0].client_vc); 63953 63954 if (UTIL.startsWith(clientName, '* ')) { 63955 clientName = clientName.substring(2); 63956 } 63957 63958 var htmBookingAndName = '<b>P' + bkg + '</b> <span>' + UTIL.maxString(clientName, 20, true) + '</span>'; 63959 var onClick = ' onclick="UserPortal.getTicket(' + smid + ', ' + bkg + ', null, false, true)"'; 63960 63961 htmCards += '<li class="' + css + '" smid="' + smid + '"' + onClick + '>' + htmBookingAndName + '</li>'; 63962 } 63963 } 63964 63965 for (var w=0; w < trSignin.length; w++) { 63966 var waitId = trSignin.eq(w).attr('wait_id'); 63967 var clientName = trSignin.eq(w).find('.pos-card-client').text(); 63968 var htmBookingAndName = '<b></b> <span>' + UTIL.maxString(clientName, 20, true) + '</span>'; 63969 var onClick = ' onclick="SA.TicketCard.openSignin(' + waitId + ')"'; 63970 63971 htmCards += '<li class="signin-only card-signin" waitid="' + waitId + '"' + onClick + '>' + htmBookingAndName + '</li>'; 63972 } 63973 63974 var msgHelp = _getCardInProgressSummary(signinCount, checkinCount); 63975 var endDiv = '<div style="clear: both; min-height: 32px;"></div>'; 63976 63977 if (signinCount + checkinCount < 12) { 63978 styleUL = 'max-width: 640px;'; 63979 } 63980 63981 return msgHelp + '<ul id="simple-client-cards" style="' + styleUL + '">' + htmCards + '</ul>' + endDiv; 63982 } 63983 function _getCardInProgressSummary(signinCount, checkinCount) { 63984 var msgHelp = '<p class="card-progress-summary">'; 63985 var bSignin = '<b class="card-signin">', bCheckin = '<b class="card-checkin">'; 63986 63987 if (signinCount > 0 && checkinCount > 0) { 63988 msgHelp += bSignin + UTIL.pluralLabel(signinCount, 'Sign-In') + '</b> + ' + bCheckin + UTIL.pluralLabel(checkinCount, 'Check-In') + '</b>'; 63989 } else if (signinCount > 0) { 63990 msgHelp += bSignin + UTIL.pluralLabel(signinCount, 'Sign-In') + '</b>'; 63991 } else if (checkinCount > 0) { 63992 msgHelp += bCheckin + UTIL.pluralLabel(checkinCount, 'Check-In') + '</b>'; 63993 } 63994 63995 return msgHelp + '</p>'; 63996 } 63997 _cTicketCard.getCardSummary = function() { 63998 var signinCount = 0, checkinCount = 0, checkoutCount = 0, readyToPayCount = 0; 63999 var noShowCount = 0, lateCancelCount = 0; 64000 var nowCount = 0, lateCount = 0, upcomingCount = 0, pastCount = 0; 64001 var htm = '', header = '<h3>Today\'s Summary</h3>'; 64002 64003 for (var i=0; i < _cards.length; i++) { 64004 if (_cards[i].status == 2) { 64005 ++signinCount; 64006 } else if (_cards[i].status == 21) { 64007 ++checkinCount; 64008 } else if (_cards[i].status == 22 || _cards[i].status == 120) { 64009 ++checkoutCount; 64010 } else if (_cards[i].status == 25) { 64011 ++readyToPayCount; 64012 64013 } else if (_cards[i].status == 13 || _cards[i].status == 130) { 64014 ++noShowCount; 64015 } else if (_cards[i].status == 14 || _cards[i].status == 140) { 64016 ++lateCancelCount; 64017 64018 } else if (_cards[i].status == 5) { 64019 ++nowCount; 64020 } else if (_cards[i].status == 29) { 64021 ++lateCount; 64022 } else if (_cards[i].status == 41) { 64023 ++upcomingCount; 64024 } else if (_cards[i].status == 90) { 64025 ++pastCount; 64026 } 64027 } 64028 64029 htm += _getCardSummary('Sign-In', signinCount, 'card-signin'); 64030 htm += _getCardSummary('Check-In', checkinCount, 'card-checkin'); 64031 htm += _getCardSummary('Check-Out', checkoutCount, 'card-checkout'); 64032 htm += _getCardSummary('Ready To Pay', readyToPayCount, 'card-ready'); 64033
64034 htm += _getCardSummary('No Show', noShowCount, 'card-noshow'); 64035 htm += _getCardSummary('Late Cancel', lateCancelCount, 'card-late-cancel'); 64036 64037 htm += _getCardSummary('Now Appointment', nowCount, 'card-now', 'within 20 minutes of now'); 64038 htm += _getCardSummary('Late Appointment', lateCount, 'card-late'); 64039 htm += _getCardSummary('Upcoming Appointment', upcomingCount, 'card-upcoming'); 64040 htm += _getCardSummary('Past Appointment', pastCount, 'card-past'); 64041 64042 var endDiv = '<div style="clear: both; min-height: 12px;"></div>'; 64043 return '<div id="pop-report-pos-summary" class="pop-report-box">' + header + '<ul>' + htm + '</ul>' + endDiv + '</div>'; 64044 } 64045 function _getCardSummary(label, count, cssClass, title) { 64046 var onclick = ' onclick="'; 64047 64048 if (cssClass == 'card-checkin') { 64049 onclick += 'SA.Menu.openReportCheckedIn(null, this)"'; 64050 } else if (cssClass == 'card-checkout') { 64051 onclick += 'SA.Menu.openReportCheckedOut(null, this)"'; 64052 } else if (cssClass == 'card-signin') { 64053 onclick += 'GLO.WaitList.open()"'; 64054 } else if (cssClass == 'card-ready') { 64055 onclick += '"'; 64056 64057 } else if (cssClass == 'card-noshow') { 64058 onclick += 'SA.TicketCard.filterPanel(130, this)"'; 64059 } else if (cssClass == 'card-late-cancel') { 64060 onclick += 'SA.TicketCard.filterPanel(140, this)"'; 64061 64062 } else if (cssClass == 'card-now') { 64063 onclick += 'SA.TicketCard.filterPanel(5, this)"'; 64064 } else if (cssClass == 'card-late') { 64065 onclick += 'SA.TicketCard.filterPanel(29, this)"'; 64066 } else if (cssClass == 'card-upcoming') { 64067 onclick += 'SA.Menu.openReportUpcomingAppointments(null, this)"'; 64068 } else if (cssClass == 'card-past') { 64069 onclick += 'SA.TicketCard.filterPanel(90, this)"'; 64070 } 64071 64072 if (count > 0) { 64073 return '<li class="' + cssClass + '" title="' + UTIL.cleanString(title) + '"' + onclick + '><b>' + UTIL.pluralLabel(count, label) + '</b></li>'; 64074 } else { 64075 return ''; 64076 } 64077 } 64078 64079 return _cTicketCard; 64080})(); 64081 64082 64083SA.Kiosk = (function() { 64084 function _conKiosk() { } 64085 64086 _conKiosk.init = function() { 64087 if (innerWidth < 600 || !UTIL.parseBool($.cookies.get('kioskmode'))) { return; } 64088 64089 GLO.Mobile.initKiosk(); 64090 64091 var dot = '<a class="nohover" style="display: inline-block; margin-top: -2px; border:none; font-size: 108%; font-family: Verdana;">●</a>'; 64092 var ft = $('#ft'); 64093 var ft_help = ft.find('li:first'); 64094 var ft_sa = ft.find('#footer-powered-by'); 64095 var css = '', color = ft.find('ul li a:last').css('color'); 64096 64097 if (!UTIL.isEmpty(color)) { 64098 css = 'color: ' + color + ';'; 64099 } 64100 64101 var aExit = '<a onclick="SA.Kiosk.exit()" tabindex="-1" title="' + SA.Resource.CloseWindow.toLowerCase() + '" style="' + css + '">' + SA.Resource.Exit + '</a>'; 64102 var li = '<li style="' + css + '">' + aExit + ' • </li>'; 64103 64104 //GLO.Popup.Info.open('I Am here at Kiosk Init', 'Where are you?'); 64105 64106 if (ft.length == 0) { 64107 $('#pos-footer').addClass('iskiosk').find('#btnExitFooter').removeClass('hideX'); 64108 return; 64109 } 64110 64111 ft.find('ul').prepend(li); 64112 64113 if (ft_sa.length) { 64114 var ft_sa_htm = ft_sa.html().replace('Powered by ', ''); //.replace('|', dot); 64115 ft_sa.remove(); 64116 ft_help.prepend(ft_sa_htm); 64117 } 64118
64119 if (ft.width() < 300) { 64120 ft.width(320); 64121 } 64122 } 64123 64124 _conKiosk.exit_DOES_NOT_WORK = function() { 64125 var e = jQuery.Event("keydown"); 64126 e.keyCode = e.which = 115; //= F4. 64127 e.altKey = true; 64128 $(window).trigger(e); 64129 64130 /* 64131 var e = jQuery.Event("keypress"); 64132 var e2 = $.extend({}, e, { which: 115, altKey: true }); 64133 $(window).trigger(e2); 64134 */ 64135 64136 //setTimeout(SA.Kiosk.exit2, 900); 64137 } 64138 64139 _conKiosk.exit = function() { 64140 if (window.history.length === 1) { 64141 window.close(); 64142 } else { 64143 var msg1 = '<p>' + SA.Resource.Press + ' <b>ALT + F4</b> ' + SA.Resource.ExitConfirm + '</p>'; 64144 var msg2 = '<p style="margin: auto; margin-top: 12px; text-align: center;">(hold the <b>ALT</b> key + press the <b>F4</b> key)</p>'; 64145 var msg3 = '<p style="margin: auto; text-align: center; font-size: smaller;">(or hold the <b>ALT</b> + <b>FN</b> keys + press the <b>F4</b> key)</p>'; 64146 64147 var htm = '<div id="pop-info-kiosk-close">' + msg1 + msg2 + msg3 + '</div>'; 64148 var header = 'Instructions to Close ' + GLO.Info.getScheduleAnyoneHtm(true); 64149 64150 GLO.Popup.Info.open(htm, header); 64151 } 64152 } 64153 64154 return _conKiosk; 64155})(); 64156 64157 64158SA.Menu = (function() { 64159 function _conMenu() { } 64160 64161 _conMenu.init = function() { 64162 $('#easySearch_text').focus(SA.Menu.activateSearch); 64163 _initMenuUrlActions(); 64164 } 64165 64166 function _initMenuUrlActions() { 64167 var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(); 64168 64169 if (!UTIL.isEmpty(open)) { 64170 if (open === 'main-menu-help') { 64171 var step = GLO.Uri.url('step'); 64172 var icon = $('#header-sa-logo')[0]; 64173 64174 SA.Menu.openNewestFeatureHelp(icon, step); //$('#hd .circle-spacer .morph-icon').click(); 64175 } 64176 } 64177 } 64178 64179 _conMenu.clickHeader = function(event, element, functionOrLink) { 64180 if (true || GLO.Info.isIPad) { 64181 var li = $(element).closest('li'); 64182 64183 if (li.hasClass('menu-is-open')) { 64184 li.removeClass('menu-is-open'); 64185 $(window).off('click.closeHeaderMenu', SA.Menu.closeHeaderMenu); 64186 } else { 64187 $('#header-navigation-links li.menu-is-open').removeClass('menu-is-open'); 64188 64189 window.setTimeout(function() { 64190 li.addClass('menu-is-open'); 64191 64192 if ($('li.menu-is-open').length > 0) { 64193 $(window).on('click.closeHeaderMenu', SA.Menu.closeHeaderMenu); 64194 } 64195 }, 50); 64196 } 64197 } else { 64198 setTimeout(function() { 64199 document.location = functionOrLink; 64200 }, 200); 64201 } 64202 } 64203 64204 _conMenu.closeHeaderMenu = function(event, li) { 64205 if (event) { 64206 var target = (event.target || event.srcElement || event.originalTarget); 64207 64208 if ($(target).closest('.header-drop-menu').length > 0) { 64209 return; 64210 } 64211 } 64212 64213 $('li.menu-is-open').removeClass('menu-is-open'); 64214 $(window).off('click.closeHeaderMenu', SA.Menu.closeHeaderMenu); 64215 } 64216 64217 _conMenu.createClient = function() { 64218 //var fn = function(clientId, clientName, email, phone, isNewUser) { if (isNewUser) { new GLO.Popup.Success('Client Created'); } } 64219 GLO.Popup.Profile(); 64220 } 64221 64222 _conMenu.closeSearchOverlay = function() { 64223 $('#search-overlay:visible').remove(); 64224 } 64225 64226 _conMenu.activateSearch = function() { 64227 if ($('#search-overlay').length > 0) { return; } 64228 if ($('.pop-black_overlay:visible').length > 0) { return; } //glopop is open. 64229 if ($('#pop-sa-keypad').closest('.glopop').length > 0) { return; } 64230 64231 _displaySearchTipOverlay(); 64232 UI.Keypad.openKeypadSearch('Search', GLO.Link.Object.Provider.UserSearch + '?include-inventory=1', 'sa-main-search'); 64233 } 64234 function _displaySearchTipOverlay() { 64235 if (UTIL.parseBool($.cookies.get('search-overlay-hide'))) { return false; } 64236 64237 var css = ''; 64238 if (GLO.Info.isMobile()) { css += ' width: ' + $(document).width() + ', height: ' + $(document).height() + ';'; } 64239 64240 var overlay = '<div id="search-overlay" class="pop-black_overlay" style="' + css + '">' + _activateSearchHtm() + '</div>'; 64241 $('body').append(overlay); 64242 64243 var joverlay = $('#search-overlay').css('display', 'block'); 64244 64245 if ($('#staffFilter').length > 0) { 64246 joverlay.css({ "top": "64px" }); 64247 } 64248 64249 setTimeout(function() { 64250 $(window).bind('click.activateSearch, touchstart.activateSearch', function() { 64251 $('#search-overlay').remove(); 64252 $(window).unbind('click.activateSearch, touchstart.activateSearch'); 64253 64254 if (event.target.id == 'search-overlay-hide' || event.target.id == 'Hide_Search_Overlay_fl') {
64255 SA.Menu.hideSearchOverlay(); 64256 } 64257 }); 64258 }, 500); 64259 64260 return true; 64261 } 64262 _conMenu.hideSearchOverlay = function() { 64263 var dtExpire = new Date().addDays(180); 64264 64265 UTIL.setCookieWithExpire('search-overlay-hide', '1', dtExpire); 64266 } 64267 function _getHideOverlayCheckbox() { 64268 //if (GLO.Data && GLO.Data.provider && UTIL.isDate(GLO.Data.provider.last_payment_dt)) { 64269 var box = '<input type="checkbox" id="Hide_Search_Overlay_fl" onclick="SA.Menu.hideSearchOverlay(this)" onchange="SA.Menu.hideSearchOverlay(this)"/>'; 64270 var label = '<label for="Hide_Search_Overlay_fl">Hide These Search Tips</label>'; 64271 64272 return '<div id="search-overlay-hide">' + box + label + '</div>'; 64273 } 64274 function _activateSearchHtm() { 64275 var closeIcon = '<a class="x-close-img sa-sprite" onclick="SA.Menu.closeSearchOverlay()" style="float: right; border-bottom: none;"></a>'; 64276 var msgStreet = '', msg = '<div>'; 64277 64278 if (GLO.Data && GLO.Data.provider && (GLO.Data.provider.new_client_address_cd > 14)) { // || UTIL.isEmpty(GLO.Data.provider.relationship 64279 msgStreet = '<li>' + SA.Resource.StreetAddress + '</li>'; 64280 } 64281 64282 if (GLO.Info.providerPackage > 1 && GLO.Provider.isPaidAccount(true)) { 64283 msg += SA.Resource.SearchHelp1; 64284 64285 if (GLO.Info.providerPackage == 2) { msg += ' ' + SA.Resource.SearchHelp2; } 64286 } else { 64287 msg += SA.Resource.SearchHelp3; 64288 } 64289 64290 msg += '</div>'; 64291 msg += '<div id="search-overlay-message-line2">' + SA.Resource.SearchHelpBelow + '</div>'; 64292 64293 var forExample = '<small style="letter-spacing: 0;">' + SA.Resource.for_example_enter + '</small>'; 64294 var htm = '<div>' 64295 + '<div id="search-overlay-header">' + SA.Resource.Search + closeIcon + '...</div>' 64296 + _getHideOverlayCheckbox() 64297 + '<div id="search-overlay-text">' 64298 + '<div id="search-overlay-message">' + msg + '</div>' 64299 + '<h5>' + SA.Resource.Client + '</h5>' 64300 + '<ul>' 64301 + '<li style="margin-bottom: 0;">' + SA.Resource.PhoneNumber + '</li>' 64302 + '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneWithAreaCode + '</li>' 64303 + '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneWithoutAreaCode + '</li>' 64304 + '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneLast4Digits + '</li>' 64305 + msgStreet 64306 + '<li>' + SA.Resource.FirstName + '</li>' 64307 + '<li>' + SA.Resource.FullName + '</li>' 64308 + '<li>' + SA.Resource.First2CharactersHelp + '</li>' 64309 + '<li>' + SA.Resource.EmailAddress + '</li>' 64310 + '</ul>' 64311 + '<h5>' + SA.Resource.Ticket + '</h5>' 64312 + '<ul> <li class="search-overlay-text">' + forExample + ' "<b>P1</b>"</li> </ul>'; 64313 64314 if (GLO.Info.providerPackage > 1 && GLO.Provider.isPaidAccount(true)) { 64315 htm += '<h5>Gift Card</h5> <ul id="gift-card-help"> <li>' + forExample + ' "<b>#</b>GC1" <i style="font-size: 12px;">( "#" + gift card number )</i></li> </ul>'; 64316 64317 if (GLO.Info.providerPackage == 2) { 64318 htm += '<h5>' + SA.Resource.Order + '</h5> <ul> <li class="search-overlay-text">' + forExample + ' "<b>O1</b>"<i style="font-size: 12px;">( "O" + order number )</i></li> </ul>'; 64319 } 64320 64321 htm += '<h5>' + SA.Resource.Product + '</h5> <ul>' 64322 + '<li>' + SA.Resource.ProductName + '</li>' 64323 + '<li>' + SA.Resource.Product + ' ' + SA.Resource.Brand + '</li>' 64324 + '<li>' + SA.Resource.ProductType + '</li>' 64325 + '<li>' + SA.Resource.ProductSku + '</li>' 64326 + '<li>' + SA.Resource.ProductUPC + '</li>' 64327 + '</ul>'; 64328 } 64329 64330 return htm + '</div> </div>'; 64331 } 64332 64333 _conMenu.gotoContact = function(event, element) { 64334 if (GLO.Info.isMobile(true)) { 64335 if (GLO.Info.isMobile()) { 64336 GLO.Mobile.Header.closeMenu(); 64337 } 64338 64339 //GLO.UI.animate(2); 64340 } else if (element) { 64341 //$(element).addClass('is-loading'); 64342 } 64343 64344 setTimeout(function() { 64345 SA.App.openContactSAPopup(); 64346 64347 /* 64348 var url = GLO.Link.WebsiteDomain + 'log/contact'; 64349 64350 if (typeof event != 'undefined' && event.ctrlKey) { 64351 UI.openChildWindow(url, '', true); 64352 64353 if (element) { setTimeout(function() { $(element).removeClass('is-loading'); }, 2500); } 64354 } else { 64355 document.location = url; 64356 } 64357 */ 64358 }, 200); 64359 } 64360 64361 _conMenu.gotoInventory = function(event, element, url) { 64362 var j = $('#manage-inventory'); 64363 64364 if (j.length > 0) { 64365 if (GLO.Info.isMobile() && !GLO.Mobile.isTablet) { 64366 GLO.Mobile.Header.closeMenu(); 64367 } else { 64368 var test = url.toLowerCase(); 64369 64370 if (test.indexOf('order-create') !== -1) { 64371 GLO.Inventory.gotoHash('order'); 64372 } else if (test.indexOf('order-list') !== -1) { 64373 GLO.Inventory.gotoHash('order-list'); 64374 } else { 64375 if (j.find('#inventory-table').find('tr').length > 20) { 64376 GLO.Inventory.updateHash('product-list-intro'); 64377 } else { 64378 GLO.Inventory.updateHash('product-list'); 64379 } 64380 } 64381 } 64382 64383 $(element).addClass('is-loading'); 64384 64385 setTimeout(function() { 64386 $(element).removeClass('is-loading');
64387 SA.Menu.hideMenuTemporarily(); 64388 }, 600); 64389 } else { 64390 return _conMenu.gotoReport(event, element, url, true); 64391 } 64392 } 64393 64394 _conMenu.gotoInventoryReports = function(event, element, url) { 64395 var jTabContainer = $('#inventory-report-portal'); 64396 64397 if (jTabContainer.length > 0) { 64398 if (GLO.Info.isMobile()) { 64399 GLO.Mobile.Header.closeMenu(); 64400 } else { 64401 $('#header-navigation-links .menu-is-open').removeClass('menu-is-open'); 64402 //document.location = url; // document.location = document.location.protocol + '//' + document.location.host + url; 64403 var test = url.toLowerCase(); 64404 64405 if (test.indexOf('product-history') !== -1) { 64406 jTabContainer.find('#report-tab-product-history').click(); 64407 } else if (test.indexOf('order-and-restock') !== -1) { 64408 jTabContainer.find('#report-tab-shipment-history').click(); 64409 } else if (test.indexOf('audit-history') !== -1) { 64410 jTabContainer.find('#report-tab-audit-history').click(); 64411 } else { 64412 jTabContainer.find('#report-tab-returns-exchanges').click(); 64413 } 64414 } 64415 64416 $(element).addClass('is-loading'); 64417 64418 setTimeout(function() { 64419 $(element).removeClass('is-loading'); 64420 SA.Menu.hideMenuTemporarily(); 64421 }, 600); 64422 } else { 64423 return _conMenu.gotoReport(event, element, url, true); 64424 } 64425 } 64426 64427 _conMenu.gotoPopularReport = function(event, element, url) { 64428 var jTabContainer = $('#popular-report-portal'); 64429 64430 if (jTabContainer.length > 0) { 64431 if (GLO.Info.isMobile()) { 64432 GLO.Mobile.Header.closeMenu(); 64433 } else { 64434 $('#header-navigation-links .menu-is-open').removeClass('menu-is-open'); 64435 //document.location = '/' + url; // document.location = document.location.protocol + '//' + document.location.host + url; 64436 var test = url.toLowerCase(); 64437 64438 if (test.indexOf('popular-services') !== -1) { 64439 jTabContainer.find('#report-tab-popular-service').click(); 64440 } else { 64441 jTabContainer.find('#report-tab-popular-product').click(); 64442 } 64443 64444 $(element).addClass('is-loading'); 64445 64446 setTimeout(function() { 64447 $(element).removeClass('is-loading'); 64448 SA.Menu.hideMenuTemporarily(); 64449 }, 600); 64450 } 64451 } else { 64452 return _conMenu.gotoReport(event, element, url, true); 64453 } 64454 } 64455 64456 _conMenu.gotoReportSimple = function(element, url) { 64457 return _conMenu.gotoReport(event, element, url, true); 64458 } 64459 _conMenu.gotoReport2 = function(event, element, url) { 64460 return _conMenu.gotoReport(event, element, url, true); 64461 } 64462 64463 _conMenu.gotoReportConfirmed = function(url, isOpenChildWindow, element) { 64464 var fnFinishLoad = function() {}; 64465 64466 if (GLO.Info.isMobile(true)) { 64467 if (GLO.Info.isMobile()) { 64468 GLO.Mobile.Header.closeMenu(); 64469 } 64470 64471 GLO.UI.animate(2); 64472 } else if (element) { 64473 $(element).addClass('is-loading'); 64474 64475 if (_isSamePage(url)) { 64476 fnFinishLoad = function() { setTimeout(function() { 64477 $(element).removeClass('is-loading'); 64478 SA.Menu.hideMenuTemporarily(); 64479 }, 900); }; 64480 } else { 64481 fnFinishLoad = function() { setTimeout(function() { $(element).removeClass('is-loading'); }, 2500); }; 64482 } 64483 } 64484 64485 if (GLO.isPOS) { 64486 url = GLO.Uri.addQueryKeyAndValue(url, 'helloback=pos'); //GLO.Uri.query('helloback', 'pos'); 64487 } 64488 64489 setTimeout(function() { 64490 url = GLO.Link.WebsiteDomain + url; 64491 64492 if (isOpenChildWindow) { 64493 UI.openChildWindow(url, '', true); 64494 fnFinishLoad(); 64495 } else { 64496 document.location = url; 64497 } 64498 }, 200); 64499 } 64500 function _getReportQueryString(url, ignoreQueryString) { 64501 if (!ignoreQueryString) { 64502 var sfilter = GLO.Uri.query('sfilter'); 64503 64504 if ((UTIL.isEmpty(sfilter) && GLO.Info.isMobile() && GLO.Info.roleType < 219) || GLO.Info.roleType < 210) { 64505 sfilter = GLO.Info.StaffId;
64506 } 64507 64508 if (!UTIL.isEmpty(sfilter)) { 64509 if (url.indexOf("?") !== -1) { url += '&'; } else { url += '?'; } 64510 url += 'sfilter=' + sfilter; 64511 } 64512 } 64513 64514 return url; 64515 } 64516 64517 64518 _conMenu.gotoReport = function(event, element, url, ignoreQueryString) { 64519 url = _getReportQueryString(url, ignoreQueryString); 64520 var isOpenChildWindow = (typeof event != 'undefined' && event.ctrlKey); 64521 64522 if (!isOpenChildWindow) { 64523 var jpop = $(element).closest('.glopop'); 64524 64525 if (jpop.find('#pop-manager-report').length) { 64526 GLO.Popup.close(jpop); 64527 } 64528 } 64529 64530 if (_isRequirePIN()) { 64531 _conMenu.openRequirePIN(url, isOpenChildWindow, element); 64532 } else { 64533 _conMenu.gotoReportConfirmed(url, isOpenChildWindow, element); 64534 } 64535 } 64536 _conMenu.isRequirePIN = function(url, element, event, isPopup, header) { 64537 if (_isRequirePIN()) { 64538 if (GLO.Report.isReport(url)) { 64539 if (UTIL.isEmpty($.cookies.get('pinsession'))) { 64540 var isOpenChildWindow = (typeof event != 'undefined' && event.ctrlKey); 64541 64542 _conMenu.openRequirePIN(url, isOpenChildWindow, element, isPopup, header); 64543 return true; 64544 } 64545 } 64546 } 64547 64548 return false; 64549 } 64550 function _getUrl(uri) { 64551 if (uri && uri.length > 3) { 64552 var test4 = uri.toLowerCase().substring(0,4); 64553 64554 if (test4 !== 'http' && test4 !== 'www.') { 64555 if (uri.indexOf('/') !== 0) { 64556 uri = '/' + uri; 64557 } 64558 64559 uri = GLO.Info.http + document.location.host + uri; 64560 } 64561 } 64562 64563 return uri; 64564 } 64565 function _isRequirePIN() { 64566 return (UTIL.coalesceInt(GLO.Info.roleTypeOriginal, GLO.Info.roleType) == 200 || (GLO.Data.Staff.role_report_cd > 199 && GLO.Data.Staff.role_report_cd < 249)); 64567 } 64568 _conMenu.openRequirePIN = function(url, isOpenChildWindow, element, isOpenInPopup, message) { 64569 var msg = '<p>Please Enter Password or PIN to View Report</p>'; 64570 64571 if (!UTIL.isEmpty(message)) { 64572 msg += '<div class="pop-enter-pin-custom-message">' + message + '</div>'; 64573 } 64574 64575 var input = '<div><input type="password" id="Pasword_Or_Pin_vc"/></div>'; 64576 var htm = '<div id="pop-require-pin" report_page_vc="' + url + '">' + msg + input + '</div>'; 64577 64578 var fnSave = function() { 64579 SA.Menu.verifyPIN(url, isOpenChildWindow, element, isOpenInPopup); 64580 }; 64581 64582 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Enter Password or PIN', fnSave, null, true); 64583 var jpop = ojpop.getPopup() 64584 var cssYes = { "position": "absolute", "right": "8px", "width": "140px", "font-size": "16px" }; 64585 64586 jpop.find('.btnSave').attr('id', 'btnOpenReport').addClass('btnYes').addClass('btnAdd').removeClass('btnSave').css(cssYes).find('>a').text('Open Report'); 64587 jpop.find('.btnCancel').css({ "font-size": "16px" }); 64588 64589 ojpop.saveOnEnter(); 64590 SA.Menu.hideMenuTemporarily(true); 64591 } 64592 _conMenu.verifyPIN = function(url, isOpenChildWindow, element, isOpenInPopup) { 64593 var jpop = $('#pop-require-pin').closest('.glopop'); 64594 var verifyUrl = GLO.Link.WebsiteDomain + 'provider/ajax/VerifyPasswordForReport'; 64595 64596 if (jpop.length) { 64597 var page = jpop.find('#pop-require-pin').attr('report_page_vc'); 64598 var jpass = jpop.find('#Pasword_Or_Pin_vc'); 64599 var pass = jpass.val(); 64600 64601 GLO.UI.Form.beginProcessing(jpop.find('#btnOpenReport')); 64602 } else { 64603 var jcontainer = $('#report-password-container'); 64604 var page = document.location.pathname.substring(1); 64605 var jpass = jcontainer.find('#Report_Password_vc'); 64606 var pass = jpass.val(); 64607 64608 GLO.UI.Form.beginProcessing(jcontainer.find('.btnSearchWithReportPassword')); 64609 } 64610 64611 var jqxhr = $.ajax({ "type": "POST", "url": verifyUrl, "cache": false, "data": { "password": pass, "page": page } }) 64612 .success(function(data, textStatus, jqXHR) { 64613 var jdata = $(data); 64614 var fnOk = function() { 64615 jpass.focus(); 64616 }; 64617 64618 if (!UTIL.isEmpty(jdata.attr('warning_cd')) || !UTIL.isEmpty(jdata.attr('error_cd'))) { 64619 if (jpop.css('z-index') == 251001) { // hideMenuTemporarily increases z-index 64620 jpop.css('z-index', 5002); 64621 } 64622 64623 var htmWarn = '<div id="pop-warn-pin-not-accepted">' + jdata.html() + '</div>'; 64624 64625 GLO.Popup.closeIfExist($('#pop-warn-pin-not-accepted').closest('.glopop')); 64626 GLO.UI.Form.resetProcessing(); 64627 64628 var jwarn = GLO.Popup.Warning.open(htmWarn, 'PIN Not Accepted', fnOk); 64629 var jPopEnterPin = $('#pop-require-pin').closest('.glopop'); 64630 var zindex = jPopEnterPin.css('z-index'); 64631 64632 //if (jPopEnterPin.length && zindex > 0) { jwarn.getPopup().css('z-index', zindex); } 64633 } else if (!UTIL.isEmpty(jdata.attr('success_cd'))) { 64634 url = _getUrl(url); //var reportUrl = document.location.origin + page; 64635 _completeLoadReport(url, isOpenChildWindow, isOpenInPopup, element, jdata, jpop); 64636 } else { 64637 GLO.UI.Form.resetProcessing(); 64638 GLO.Popup.Warning.open('Unable to find this PIN or Password', 'Unable to Process PIN', fnOk); 64639 } 64640 }) 64641 .error(function(jqXHR, textStatus, errorThrown) { 64642 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 64643 }); 64644 } 64645 function _completeLoadReport(url, isOpenChildWindow, isOpenInPopup, element, jdata, jpop) {
64646 var pinGuid = jdata.attr('pinsession'); 64647 var dtExpire = new Date().addMinutes(5); 64648 64649 //sessionStorage.setItem('pinsession', pinGuid); //= think sessionStorage is a better solution, but to make it easier to implement to work with existing code for now use cookie mainly to check pinsession 64650 UTIL.setCookieWithExpire('pinsession', pinGuid, dtExpire); 64651 64652 GLO.Popup.Success.open(jdata.html(), 'PIN / Password Accepted'); 64653 64654 setTimeout(function() { 64655 if (isOpenChildWindow) { 64656 GLO.Popup.closeIfExist(jpop); 64657 UI.openChildWindow(url, 'Report', true); 64658 } else if (isOpenInPopup) { 64659 GLO.Popup.closeIfExist(jpop); 64660 var pinGuid = $.cookies.get('pinsession'); //if staff just entered PIN in popup, then won't be in request cookie sent to server 64661 64662 //if (pinGuid && UTIL.isEmpty(GLO.Uri.getQueryStringValueFromUrl('pinguid', url))) { url += '&pinguid=' + pinGuid; } 64663 64664 if (url.toLowerCase().indexOf('report/payrolldays?') !== -1) { 64665 var h1 = 'Payroll Today', popupId = 'report-payroll-days-full-page', msg = null, fnOnload = SA.POS.printTodayCommissionDisplay; 64666 } else { 64667 //must implement for other reports 64668 } 64669 64670 _openPopupReport(null, element, url, h1, popupId, msg, fnOnload); 64671 } else if (document.location.href.toLowerCase() == url.toLowerCase()) { 64672 location.reload(); 64673 } else { 64674 document.location = url; 64675 } 64676 }, 100); 64677 } 64678 64679 function _isSamePage(url) { 64680 if (url.indexOf('#') !== -1) { 64681 url = url.substring(0, url.indexOf('#')); 64682 } 64683 64684 var newUrl = url.toLowerCase(); 64685 var currentUrl = document.location.href.replace(document.location.hash, '').toLowerCase(); 64686 64687 if (newUrl == currentUrl) { 64688 return true; 64689 } else { 64690 return false; 64691 } 64692 } 64693 64694 _conMenu.hideMenuTemporarily = function(isPopup) { 64695 var jmenu = $('#hd-reports-menu'); 64696 64697 if (isPopup && GLO.isPOS) { 64698 GLO.Popup.closeIfExist(jmenu.closest('.glopop')); 64699 } else if (isPopup) { 64700 $('.msg').closest('.glopop').css({ "z-index": 251001 }); 64701 return; 64702 } else { 64703 if (jmenu.find('li.menu-is-open').length > 0) { 64704 jmenu.find('li.menu-is-open').removeClass('menu-is-open'); 64705 } else { 64706 jmenu.css({ "visibility": "hidden" }); 64707 64708 setTimeout(function() { 64709 $('#hd-reports-menu').css({ "visibility": "" }); 64710 }, 1500); 64711 } 64712 } 64713 } 64714 64715 _conMenu.clearPinSession = function() { 64716 UTIL.setCookieWithExpire('pinsession', null); 64717 document.cookie = "pinsession=a1;expires=Thu, 01 Jan 1970 00:00:00 GMT"; //for some reason occasionally get duplicate cookie records, this line removes the duplicate! 64718 } 64719 64720 _conMenu.openPopupReport = function(btn, url, h1, popupId, msg, fnOnload) { 64721 _openPopupReport(null, btn, url, h1, popupId, msg, fnOnload); 64722 } 64723 function _openPopupReport(rowCount, btn, url, h1, popupId, msg, fnOnload) { 64724 GLO.Popup.closeIfExist($('.popup-report').closest('.glopop')); 64725 64726 if (UTIL.coalesceInt(rowCount, 0) > 0) { 64727 url += '&rows=' + rowCount; 64728 } 64729 64730 url += '&search=1'; 64731 var throbber = UI.getBlueThrobber('margin: 32px auto;'); 64732 var htm = '<div id="' + popupId + '" class="popup-report"><div class="friendly-msg2" style="min-width: 280px; padding: 0 12px;">' + $.trim(msg) + throbber + '</div> </div>'; 64733 64734 var ojpop = GLO.Popup.Custom.openSimple(htm, h1, null, null, true); 64735 var jpop = ojpop.getPopup().css({ "padding-bottom": "0" }); 64736 var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" }); //.addClass('pop-buttons2'); 64737 //jbtns.find('.btnSave').remove(); 64738 64739 GLO.Popup.Custom.singleButton(jpop, 'Close'); 64740 _conMenu.hideMenuTemporarily(true); 64741 GLO.UI.Form.beginProcessing($(btn)); 64742
64743 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 64744 .success(function(data, textStatus, jqXHR) { 64745 var htm = data; //var htm = $.trim(msg) + data; 64746 jpop.addClass('quick-report').find('#' + popupId).html(htm); 64747 64748 if (jpop.find('#enter-report-password').length) { 64749 ojpop.close(); 64750 64751 if (!UTIL.isEmpty($.cookies.get('pinsession'))) { 64752 GLO.Popup.Processing.open('Re-loading for Report Access...', h1); 64753 GLO.Log.insertSimple('PIN Session in Browser but NOT Server', msg, 'warning'); //GLO.Log.processWarning(msg) 64754 64755 setTimeout(function() { 64756 location.reload(); 64757 }, 100); 64758 64759 _conMenu.clearPinSession(); 64760 return; 64761 } 64762 64763 url = url.replace('&search=1', ''); 64764 _conMenu.openRequirePIN(url, false, btn, true, msg); 64765 return; 64766 } 64767 64768 jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close).focus(); 64769 jpop.find('#report-header-help-text').css({ "padding": "0 8px", "font-size": "" }); 64770 64771 if ($('.glopop').length === 1) { 64772 jpop.css({ "z-index": "501" }); 64773 $('#pop-overlay1').css({ "z-index": "501" }); 64774 } 64775 64776 if (fnOnload) { 64777 fnOnload(url); 64778 } else { 64779 var jtbl = jpop.find('table.tablesorter:visible'); 64780 UI.initTableSorter(jtbl); 64781 64782 GLO.Report.CellSummary.initReport(jtbl, true, true); 64783 GLO.Report.initIcons(jtbl); 64784 GLO.Report.TicketHistory.loadColumns(jtbl); 64785 } 64786 64787 ojpop.realign(); 64788 GLO.UI.Form.resetProcessing(); 64789 64790 setTimeout(ojpop.realign, 100); 64791 }) 64792 .error(function(jqXHR, textStatus, errorThrown) { 64793 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 64794 }); 64795 } 64796 _conMenu.openReportTicketHistory = function(rowCount, btn, apptStatus, payMethod) { 64797 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?'; 64798 var h1 = '', msg = '', msgSmall = '', popupId = 'pop-appt-ticket-history'; 64799 64800 if (!UTIL.isEmpty(apptStatus)) { 64801 url = GLO.Uri.addQueryKeyAndValue(url, 'appt-status=' + apptStatus); 64802 64803 if (apptStatus == 13) { 64804 h1 = SA.Resource.NoShow; 64805 msg = 'No Show'; 64806 msgSmall = 'client missed their appointment'; 64807 } else if (apptStatus == 14) { 64808 h1 = 'Late Cancellation'; 64809 msg = 'Late Cancel'; 64810 msgSmall = 'Client cancelled appointment at the last minute'; 64811 } else if (apptStatus == 21) { 64812 h1 = SA.Resource.CheckIn_dash; 64813 popupId = 'pop-appt-checkedin'; 64814 msg = 'Tickets where the client is currently On-Site'; 64815 msgSmall = '(ticket is checked-in but not yet checked-out)'; 64816 } else if (apptStatus == 22) { 64817 h1 = SA.Resource.CheckOut_dash; 64818 popupId = 'pop-appt-checkedout'; 64819 msg = 'Completed Ticket'; 64820 msgSmall = '(ticket is checked-out)'; 64821 } 64822 } 64823 64824 if (!UTIL.isEmpty(payMethod)) { 64825 url = GLO.Uri.addQueryKeyAndValue(url, 'pay-method=' + payMethod); 64826 var msgPay = UserPortal.Price.paymentMethodLabel(payMethod); 64827 64828 if (!UTIL.isEmpty(h1)) { 64829 msg += ' | and ' + msgPay; 64830 } else { 64831 h1 = UserPortal.Price.paymentMethodLabel(payMethod); 64832 msg = msgPay; 64833 } 64834 } 64835 64836 var msgClick = '<p> <small>click date to open ticket</small> </p>'; 64837 var htm = '<p>' + msg + '<small style="white-space: nowrap; letter-spacing: 0;">' + msgSmall + '</small></p>' + msgClick; 64838 64839 _openPopupReport(rowCount, btn, url, h1, popupId, htm); 64840 } 64841 _conMenu.openReportCheckedIn = function(rowCount, btn) { 64842 GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop')); 64843 64844 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=21'; 64845 var popupId = 'pop-appt-checkedin'; 64846 64847 var headerLeft = '<a class="quietest quietest-left" onclick="SA.Me
64847nu.openReportCheckedOut(' + rowCount + ', this)" style="margin: 0; font-stretch: condensed;">Checked-Out</a>'; 64848 var h1 = headerLeft + '<b>Checked-In</b>'; //SA.Resource.CheckIn_dash; 64849 64850 var msg1 = '<p>Tickets where the client is currently On-Site <small style="white-space: nowrap; letter-spacing: 0;">( ticket is checked-in but not yet checked-out )</small> </p>'; 64851 var msg2 = '<div> <small>click date to open ticket</small> </div>'; 64852 var msg = msg1 + msg2; 64853 64854 _openPopupReport(rowCount, btn, url, h1, popupId, msg); 64855 } 64856 _conMenu.openReportCheckedOut = function(rowCount, btn) { 64857 GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop')); 64858 64859 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=22'; 64860 var popupId = 'pop-appt-checkedin'; 64861 64862 var headerLeft = '<a class="quietest quietest-left" onclick="SA.Menu.openReportCheckedIn(' + rowCount + ', this)" style="margin: 0; font-stretch: condensed;">Checked-In</a>'; 64863 var h1 = headerLeft + '<b>Checked-Out</b>'; 64864 64865 var msg1 = '<p>Tickets where the client is currently On-Site <small style="white-space: nowrap; letter-spacing: 0;">( ticket is checked-in but not yet checked-out )</small> </p>'; 64866 var msg2 = '<div> <small>click date to open ticket</small> </div>'; 64867 var msg = msg1 + msg2; 64868 64869 _openPopupReport(rowCount, btn, url, h1, popupId, msg); 64870 } 64871 _conMenu.openReportUpcomingAppointments = function(rowCount, btn, eventCode, htmHeader) { 64872 GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop')); 64873 64874 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=11'; 64875 var popupId = 'pop-appt-upcoming'; 64876 64877 var headerLeft = '<a class="quietest quietest-left" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/calendar\', this, event, true)" style="margin: 0;">Calendar</a>'; 64878 var h1 = headerLeft + '<b>Upcoming Appointments Today</b>'; 64879 64880 var msg1 = '<p>Upcoming Appointments Scheduled Today <small style="white-space: nowrap; letter-spacing: 0;">(and not checked-in, checked-out, or marked as a no-show)</small></p>'; 64881 var msg2 = '<div> <small>click date to open ticket</small> </div>'; 64882 var msg = msg1 + msg2; 64883 64884 _openPopupReport(rowCount, btn, url, h1, popupId, msg); 64885 } 64886 _conMenu.openReportRecent = function(rowCount, btn) { 64887 var jpos = $('#pos-container'); 64888 64889 if (jpos.hasClass('services')) { 64890 SA.Menu.recentApptEdits(rowCount, btn); 64891 } else { 64892 SA.Menu.recentSales(rowCount, null, null, btn); 64893 } 64894 64895 //GLO.UI.Form.beginProcessing($(btn)); 64896 } 64897 64898 _conMenu.printTodaySales = function(event, element) { 64899 GLO.Report.Sales.printByReceptionistFromMenu(); 64900 } 64901 64902 _conMenu.recentSales = function(rowCount, eventCode, htmHeader, btn) { 64903 GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop')); 64904 64905 var url = 'reports/saleshistory?isfullpage=1&paymethod=0&start=' + new Date().toGloDate(); 64906 64907 if (GLO.isPOS) { 64908 url += '&helloback=pos'; 64909 } 64910 64911 var rptLinkRight = 'GLO.Report.CellSummary.gotoReport(\'' + url + '\', this, event)'; 64912 64913 if (eventCode > 0) { 64914 var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?isrecentsale=1&search=1&eventcode=' + eventCode + '&rows=' + UTIL.coalesceInt(rowCount, 10); 64915 var rptLinkLeft = 'SA.Menu.recentSales(' + rowCount + ', null, null, this)'; 64916 var rptLabel = 'Sales'; 64917 } else { 64918 var url = GLO.Link.WebsiteDomain + 'report/RecentSales?rows=' + UTIL.coalesceInt(rowCount, 10); 64919 var rptLinkLeft = 'SA.Menu.recentApptEdits(' + rowCount + ', this)'; 64920 var rptLabel = 'Appointments'; 64921 } 64922 64923 if (innerWidth > 979) { 64924 rptLinkLeft = '<a class="quietest quietest-left" onclick="' + rptLinkLeft + '"><span>Recent </span>' + rptLabel + '</a>'; 64925 64926 if (GLO.Info.roleType == 200) { 64927 rptLinkRight = ''; 64928 } else { 64929 rptLinkRight = '<a class="quietest quietest-right" onclick="' + rptLinkRight + '"><span>Payments </span>Today</a>'; 64930 } 64931 } else { 64932 rptLinkLeft = rptLinkRight = ''; 64933 } 64934 64935 var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + UI.getBlueThrobber('margin: 120px auto;') + '</div>'; 64936 var h1Label = '<b id="report-recent-popup-header-inner">' + SA.Resource.RecentSales + '</b>'; 64937 var h1 = '<h1 id="report-recent-popup-header" class="friendly-msg2">' + rptLinkLeft + h1Label + rptLinkRight + '</h1>'; 64938 var htm = $('<div id="pop-recent-sales" class="popup-report">' + h1 + '<div>' + throbber + '</div></div>'); 64939 64940 var ojpop = new GLO.Popup.Custom(htm); 64941 var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": "0" }); 64942 var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" }); //.addClass('pop-buttons2'); 64943 GLO.Popup.Custom.singleButton(jpop, 'Close'); 64944 64945 jbtns.find('.btnSave').remove(); 64946 _conMenu.hideMenuTemporarily(true); 64947 GLO.UI.Form.beginProcessing($(btn)); 64948
64949 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 64950 .success(function(data, textStatus, jqXHR) { 64951 jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close).focus(); 64952 64953 var htm = $.trim(htmHeader) + data; 64954 64955 jpop.addClass('quick-report').find('#pop-recent-sales').html(htm); 64956 64957 if (true || !GLO.isPOS) { 64958 jpop.css({ "z-index": "501" }); 64959 $('.pop-black_overlay').css({ "z-index": "501" }); 64960 } 64961 64962 var jtbl = jpop.find('table.tablesorter:visible'); 64963 UI.initTableSorter(jtbl); 64964 64965 GLO.Report.CellSummary.initReport(jtbl, true, true); 64966 GLO.Report.initIcons(jtbl); 64967 GLO.Report.TicketHistory.loadColumns(jtbl); 64968 ojpop.realign(); 64969 GLO.UI.Form.resetProcessing(); 64970 }) 64971 .error(function(jqXHR, textStatus, errorThrown) { 64972 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 64973 }); 64974 } 64975 64976 _conMenu.recentApptEdits = function(rowCount, btn) { 64977 GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop')); 64978 64979 var url = GLO.Link.Page.Provider.Home + 'report/RecentApptEdit?rows=' + UTIL.coalesceInt(rowCount, 10); 64980 var urlActivity = 'provider/apptportal'; 64981 64982 if (GLO.isPOS) { 64983 urlActivity += '?helloback=pos'; 64984 } 64985 64986 var rptLinkLeft = 'SA.Menu.recentSales(' + rowCount + ', null, null, this)'; 64987 var rptLinkRight = 'GLO.Uri.gotoUriWithSpinner(\'' + urlActivity + '\', this, event, true)'; 64988 64989 if (innerWidth > 979) { 64990 rptLinkLeft = '<a class="quietest quietest-left" onclick="' + rptLinkLeft + '"><span>Recent </span>Sales</a>'; 64991 64992 if (GLO.Data.Staff.defaultScreenOnly) { 64993 rptLinkRight = ''; 64994 } else { 64995 rptLinkRight = '<a class="quietest quietest-right" onclick="' + rptLinkRight + '">All Activity</a>'; 64996 } 64997 } else { 64998 rptLinkLeft = rptLinkRight = ''; 64999 } 65000 65001 var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + UI.getBlueThrobber('margin: 120px auto;') + '</div>'; 65002 //var throbber = $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML(); 65003 var h1Label = '<b id="report-recent-popup-header-inner">' + SA.Resource.RecentAppointmentUpdates + '</b>'; 65004 var h1 = '<h1 id="report-recent-popup-header" class="friendly-msg2">' + rptLinkLeft + h1Label + rptLinkRight + '</h1>'; 65005 var htm = $('<div class="friendly-msg2" style="min-width: 300px;">' + h1 + '<div>' + UI.getBlueThrobber('margin: 120px auto;') + '</div></div>'); 65006 65007 var ojpop = new GLO.Popup.Custom(htm); 65008 var jpop = ojpop.getPopup().addClass('no-persist'); 65009 var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" }); //.addClass('pop-buttons2'); 65010 jbtns.find('.btnSave').remove(); 65011 GLO.Popup.Custom.singleButton(jpop, 'Close'); 65012 65013 _conMenu.hideMenuTemporarily(true); 65014 GLO.UI.Form.beginProcessing($(btn)); 65015 65016 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 65017 .success(function(data, textStatus, jqXHR) { 65018 jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close); 65019 jpop.addClass('quick-report').find('.msg').html(data); 65020 jpop.find('.appt-list-search, .appt-list-line').remove(); 65021 65022 if (!GLO.isPOS) { 65023 jpop.css({ "z-index": "501" }); 65024 $('#pop-overlay1').css({ "z-index": "501" }); 65025 } 65026 65027 UI.initTableSorter( jpop.find('table.tablesorter:visible') ); 65028 ojpop.realign(); 65029 GLO.UI.Form.resetProcessing(); 65030 }) 65031 .error(function(jqXHR, textStatus, errorThrown) { 65032 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65033 }); 65034 } 65035 65036 _conMenu.print = function() { 65037 if (GLO.Calendar !== undefined) { 65038 UserPortal.Calendar.beforePrint(); 65039 } else if ($('#report-sales-history').length > 0) { 65040 GLO.Report.Sales.printScreen(); 65041 } else { 65042 UI.Print.printOnDevice(); 65043 } 65044 } 65045 65046 function _openLoadingReportHelpPopup() { 65047 var htmGreen = '<span style="font-weight: bold; letter-spacing: 0;
65047 font-family: Verdana, Tahoma, Helvetica; color: rgb(20,240,80) !important;">Green</span>'; 65048 var msg1 = '<p style="color: #444;">Start with the reports highlighted in ' + htmGreen + ' on the <a onclick="SA.Menu.openReportMenu()">Reports</a> menu</p>'; 65049 var msg2 = '<p style="margin-top: 28px; margin-bottom: 0;">All reports in <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span> are interactive</p>' 65050 var ul = '<ul style="margin: 0; margin-left: 16px; margin-bottom: 8px;">' 65051 + '<li>Press any value in the report for more information</li>' 65052 + '<li>Press any report header to sort by that column</li>' 65053 + '<li>' 65054 + '<span class="help-icon-text">For help, press a blue question mark on the report<b>➔</b></span>' 65055 + '<span class="help-icon-parent"> <span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Advanced.Help.openAboutQuestionMark()"></span> </span>' 65056 + '</li>' 65057 + '</ul>'; 65058 var blueThrobber = '<div class="blue-throbber"><img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="height: 64px; margin: 32px;"/></div>'; 65059 var htm = '<div>' + msg1 + msg2 + ul + blueThrobber + '</div>'; 65060 var ojpop = GLO.Popup.Processing.open(htm, 'Loading Report Help'); 65061 65062 ojpop.getPopup().attr('id', 'pop-processing-loading-report-help'); 65063 return ojpop; 65064 } 65065 65066 _conMenu.openReportHelp = function(step) { 65067 var jhelp = $('#help-report-overview'); 65068 step = UTIL.coalesceInt(step, 0); 65069 65070 if (jhelp.length) { 65071 _conMenu.openReportHelp2(step); 65072 return; 65073 } 65074 65075 var url = GLO.Link.WebsiteDomain + 'info/ReportHelp'; 65076 var ojLoading = _openLoadingReportHelpPopup(); 65077 65078 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 65079 .success(function(data, textStatus, jqXHR) { 65080 ojLoading.close(); 65081 var jcontainer = $('#staff-popups'); 65082 65083 if (jcontainer.length) { 65084 jcontainer.append(data); 65085 } else { 65086 $('body').append('<div class="hideX">' + data + '</div>'); 65087 } 65088 65089 _conMenu.openReportHelp2(step); 65090 }) 65091 .error(function(jqXHR, textStatus, errorThrown) { 65092 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65093 }); 65094 } 65095 65096 _conMenu.openReportHelp2 = function(stepNumber, popid) { 65097 var ojpop = SA.Help.openReportHelp('#help-report-overview', stepNumber, 'info/ReportHelp'); 65098 65099 _conMenu.hideMenuTemporarily(true); 65100 } 65101 65102 _conMenu.toggleReportMenu = function() { 65103 $('#hd-reports-menu-text').click(); 65104 } 65105 _conMenu.openReportMenu = function() { 65106 $('#hd #hd-reports-menu.header-drop-menu-trigger > li').addClass('menu-is-open'); 65107 GLO.Popup.close($('#sa-message').closest('.glopop')); 65108 } 65109 65110 function _openLoading(subject) { 65111 var throbber = $('.loadingDiv').clone().find('img').css({"margin": "40px auto"}).outerHTML(); 65112 65113 var h1 = '<h1>' + UTIL.coalesce(subject, 'New Features') + '</h1>'; 65114 var msg = '<div style="padding: 4px 20px;">Loading New Feature Overview...</div>'; 65115 var htm = $('<div>' + h1 + '<div class="friendly-msg2" style="min-width: 240px;">' + msg + throbber + '</div> </div>'); 65116 65117 var ojpop = new GLO.Popup.Custom(htm); 65118 var jpop = ojpop.getPopup().addClass('no-persist'); 65119 var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" }); //.addClass('pop-buttons2'); 65120 jbtns.find('.btnSave').remove(); 65121 return ojpop; 65122 } 65123 65124 _conMenu.openNewestFeatureHelp = function(icon, stepNumber) { //SA.Help.openMtoHelp('report-version3-1', 'New Feature: Interactive Reports'); 65125 var jicon = $(icon).parent().find('.morph-icon'); //.parent() because may have clicked on '.help-indicator' 65126 jicon.parent().find('.help-indicator').remove(); //do NOT need indicator displayed after open (indicator there so user opens) 65127 jicon.parent().find('#main-header-help').remove(); //ensures not loaded multiple times 65128 65129 var ojThrob = _openLoading(); //GLO.Popup.Processing.open('<div style="padding: 4px 20px;">Loading New Feature Overview...</div>', 'New Features'); 65130 var url = GLO.Link.WebsiteDomain + 'log/NewFeatures'; 65131 65132 if (GLO.Info.isMobile()) { GLO.Mobile.Header.closeMenu(); } 65133
65134 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 65135 .success(function(data, textStatus, jqXHR) { 65136 ojThrob.close(); 65137 stepNumber = UTIL.coalesceInt(stepNumber, $(data).find('.wizard-step').length - 1); 65138 data = _addSaHeader(data); 65139 65140 if (GLO.Info.isMobile()) { 65141 SA.Help.openReportHelpAsMorph('#main-header-help', stepNumber, data); 65142 } else { 65143 jicon.removeAttr('onclick'); //using same icon to load help + open morph popup (this is NOT required by morph popup - just doing in this instance) 65144 jicon.parent().append(data); //must load help data in same parent as icon (so have effect where popup morphs in/out of icon) 65145 65146 var mp = new UI.MorphPopup('#main-header-help', null, null, { "visibleIcon": true, "stepNumber": stepNumber }); 65147 jicon.click(); 65148 } 65149 }) 65150 .error(function(jqXHR, textStatus, errorThrown) { 65151 //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65152 }); 65153 } 65154 function _addSaHeader(data) { 65155 var logoPrefix = UTIL.coalesceString(GLO.Data.VAR.prefix_vc, ''); 65156 var sa = '<img class="sa-logo" src="' + GLO.Data.cdnDirectory + 'image/marketing/logo/' + logoPrefix + 'logo.png"/>'; 65157 65158 if (!GLO.Info.isMobile()) { 65159 sa += ' ' + GLO.Info.getScheduleAnyoneHtm(true); 65160 } 65161 65162 var htmSaHeader = '<span id="main-help-last-step-top"> <b class="sa-brand-header">' + sa + '</b> <b class="help-new-features">New Features</b></span>'; 65163 var jd = $(data); 65164 var jsteps = jd.find('.wizard-step'); 65165 65166 for (var i=0; i < jsteps.length; i++) { 65167 var h1 = jsteps.eq(i).find('> h1'); 65168 var height = UTIL.coalesceInt(jsteps.eq(i).attr('height')) + 34; 65169 65170 jsteps.eq(i).attr('height', height); 65171 h1.css({ "padding": 0 }).html(htmSaHeader + '<span id="main-help-last-step-header-text">' + h1.html() + '</span>'); 65172 } 65173 65174 return jd.outerHTML(); 65175 } 65176 65177 return _conMenu; 65178})(); 65179 65180 65181GLO.RequestApptSetting = (function() { 65182 function _cRequestApptSetting() { } 65183 65184 _cRequestApptSetting.init = function() { 65185 var j = $('#request-appt-setting'); 65186 var jBtnSave = $('#wizBody').find('.btnSave > a'); 65187 GLO.UI.initSaveButton(j, jBtnSave); 65188 65189 var jCustomPopup = $("#request-appt-setting .sa-text-editor"); 65190 SA.TextEditor.init(jCustomPopup, 'Custom Popup'); 65191 /* 65192 jCustomPopup.focusout(function() { 65193 var element = $(this); 65194 65195 if (!element.text().trim().length) { 65196 element.empty(); 65197 } 65198 }); 65199 */ 65200 _initRequestApptUrl(); 65201 } 65202 function _initRequestApptUrl() { 65203 var highlight = UTIL.cleanString(GLO.Uri.url('highlight')); 65204 65205 if (!UTIL.isEmpty(highlight)) { 65206 var jhigh = $('#' + highlight); 65207 65208 if (jhigh.length) { 65209 UI.highlight(jhigh, 100, 9500, true); 65210 return true; 65211 } 65212 } 65213 } 65214 65215 _cRequestApptSetting.save = function() { 65216 var url = GLO.Link.Page.Provider.WebTemplate + 'RequestApptSetting'; 65217 var j = $('#request-appt-setting'); 65218 var jsave = $('#wizBody').find('.btnSave > a'); 65219 65220 var requireDT = j.find('#Require_DateTime_fl').prop('checked'); 65221 var requireNote = j.find('#Require_Note_fl').prop('checked'); 65222 var requireService = j.find('#Require_Service_fl').prop('checked'); 65223 var allowOffDay = j.find('#Allow_OffDay_fl').prop('checked'); 65224 var isAllowImageUpload = j.find('#Allow_Image_Upload_fl').prop('checked'); 65225 65226 var isDisplayPrice = j.find('#Display_Price_fl').prop('checked'); 65227 var isRequireCardOnFile = j.find('#Require_CardOnFile_fl').prop('checked'); 65228 var requireCardOnFileMin = j.find('#Require_CardOnFile_mn').val(); 65229 65230 var noteLabel = UTIL.htmlEncode2(j.find('#Note_Label_vc').val()); 65231 var popupHtm = j.find('#request-appt-popup-note .sa-text-editor')[0].innerHTML; 65232 var popupWhen = j.find('#Request_Appt_Popup_cd').val(); 65233 var jbookEvery = j.find('#Book_Every_cd'); 65234 var currentBookEvery = jbookEvery.attr('current_book_every_cd'), newBookEvery = jbookEvery.val(); 65235 65236 if (!UTIL.isEmpty(popupHtm)) { 65237 popupHtm = UTIL.htmlEncode(DOMPurify.sanitize(popupHtm)); 65238 } 65239 65240 var jd = { "require_datetime_fl": requireDT, "require_note_fl": requireNote, "require_service_fl": requireService, "allow_offday_fl": allowOffDay 65241 , "require_cof_fl": isRequireCardOnFile, "display_price_fl": isDisplayPrice, "allow_image_upload_fl": isAllowImageUpload 65242 , "note_label_vc": noteLabel, "popup_vcm": popupHtm, "popup_when_cd": popupWhen 65243 , "current_book_every_cd": currentBookEvery, "new_book_every_cd": newBookEvery }; 65244 65245 if (isRequireCardOnFile) { 65246 jd.require_cof_mn = UTIL.coalesceMoney(requireCardOnFileMin, 0); 65247 } 65248 65249 GLO.UI.Form.beginProcessing(jsave); 65250
65251 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd }) 65252 .success(function(data, textStatus, jqXHR) { 65253 GLO.UI.Form.resetProcessing(); 65254 65255 jsave.removeClass('unsaved'); 65256 jbookEvery.attr('current_book_every_cd', newBookEvery); 65257 65258 new GLO.Popup.Success(SA.Resource.ChangesSaved); 65259 }) 65260 .error(function(jqXHR, textStatus, errorThrown) { 65261 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65262 }); 65263 } 65264 65265 return _cRequestApptSetting; 65266})(); 65267 65268SA.TimecardManager = (function() { 65269 function _cTimecardManager() { } 65270 var _lastRowId = 0; 65271 65272 _cTimecardManager.init = function() { 65273 var jmanager = $('#timecard-manager'); 65274 var jstart = jmanager.find('.Begin_dt'), jend = jmanager.find('.End_dt'); 65275 65276 _loadStaffList(jmanager); 65277 65278 jstart.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 65279 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 65280 jend.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 65281 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 65282 65283 _initFromUrl(jmanager); 65284 _initBreaktimeSetting(jmanager); 65285 jmanager.find('.btnSearch > a').click(); 65286 } 65287 function _initBreaktimeSetting(jmanager) { 65288 var jClockHr = jmanager.find('#Timecard_Require_Break_After_Hour_sr'); 65289 var jBreakMin = jmanager.find('#Timecard_Require_Break_Minute_sr'); 65290 65291 _initSetting(jClockHr); 65292 _initSetting(jBreakMin); 65293 } 65294 function _initSetting(jfield) { 65295 var uriSave = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedFields'; 65296 var fnAfterSave = function() { GLO.Provider.Advanced.afterSaveFieldText(jfield); }; 65297 new UI.AutoSave(jfield, uriSave, fnAfterSave, 2800); 65298 } 65299 function _initFromUrl(jmanager) { 65300 var staff = GLO.Uri.url('staff'), service = GLO.Uri.url('service'), start = GLO.Uri.url('start'), end = GLO.Uri.url('end'); 65301 var jstaff = jmanager.find('#Timecard_Staff_id'); 65302 var jstart = jmanager.find('.Begin_dt'); 65303 var jend = jmanager.find('.End_dt'); 65304 65305 if (!UTIL.isEmpty(staff)) { 65306 jstaff.val(staff).change(); 65307 } else { 65308 jstaff.find('option:first').prop('selected', true).change(); 65309 } 65310 65311 if (!UTIL.isEmpty(service)) { 65312 jmanager.find('#Timecard_Service_id').val(service); 65313 } 65314 65315 if (UTIL.isEmpty(start)) { 65316 if (!UTIL.isEmpty(jstaff.val())) { 65317 start = new Date( (new Date().getMonth() + 1) + '/1/' + new Date().getFullYear()).toGloDate(); 65318 } else { 65319 start = new Date().addDays(-7).toGloDate(); 65320 } 65321 } 65322 65323 if (UTIL.isEmpty(end)) { 65324 end = new Date().toGloDate(); 65325 } 65326 65327 jstart.val(start); 65328 jend.val(end); 65329 } 65330 function _loadStaffList(jmanager, staffId) { 65331 var sids = UserPortal.getStaffWhoDoInternalService(); 65332 var optionList = ''; 65333 65334 if (sids.length > 0) { 65335 for (var i=0; i < sids.length; i++) { 65336 optionList += '<option value="' + sids[i] + '">' + UserPortal.getStaffName(sids[i]) + '</option>'; 65337 } 65338 65339 jmanager.find('#Timecard_Staff_id').replaceWith('<select id="Timecard_Staff_id" class="timecard-staff-dd" onchange="SA.TimecardManager.changeStaff(this)">' + optionList + '</select>'); 65340 65341 jmanager.find('#Timecard_Staff_id').html(jmanager.find('#Timecard_Staff_id').find('option').sort(function (a, b) { 65342 return a.text == b.text ? 0 : a.text < b.text ? -1 : 1 65343 })); 65344 65345 jmanager.find('#Timecard_Staff_id').prepend('<option value="">Select Person</option>'); 65346 } else { 65347 var aReportCommission = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/CommissionByStaffService\', this, event, true)">Payroll Setup</a>'; 65348 var msg1 = '<p>No Staff assigned to an <b class="narrow-text">Employee Service</b> to <b class="narrow-text">Clock-In/Out</b></p>'; 65349 var msg2 = '<p>To create timecards please go to the ' + aReportCommission + ' to assign each staff a wage and to which service(s) each staff can clock-in</p>'; 65350 65351 jmanager.find('#timecard-manager-search').after('<div id="timecard-manager-no-staff">' + msg1 + msg2 + '</div>'); 65352 jmanager.find('#Timecard_Staff_id').remove(); 65353 } 65354 } 65355 65356 _cTimecardManager.checkAll = function(element) { 65357 GLO.Message.Bulk.checkAll2(element, '#timecard-list > tbody'); 65358 } 65359 65360 _cTimecardManager.changeDay = function(element) { 65361 var jin = $(element).closest('tr').find('.clockin-time'); 65362 65363 if (UTIL.isEmpty(jin.val())) { 65364 jin.focus(); 65365 } 65366 } 65367 _cTimecardManager.changeTime = function(element, isClockIn) { 65368 var tr = $(element).closest('tr'); 65369 var tmIn = tr.find('.clockin-time').val(); 65370 var tmOut = tr.find('.clockout-time').val(); 65371 65372 if (UTIL.isValidTime(tmIn) && UTIL.isValidTime(tmOut)) { 65373 var srIn = UTIL.timeToInt(tmIn), srOut = UTIL.timeToInt(tmOut); 65374 var diffMin = srOut - srIn; 65375 65376 if (diffMin > 0) { 65377 var breakTimeMin = UTIL.coalesceInt($('#Timecard_Require_Break_Minute_sr').val(), 0); 65378 var hrForBreak = UTIL.coalesceInt($('#Timecard_Require_Break_After_Hour_sr').val(), 0); 65379 65380 if (breakTimeMin > 0 && hrForBreak > 0 && diffMin >= hrForBreak * 60) { 65381 tr.find('.tc-column-break-time').text(breakTimeMin + ' minutes'); 65382 } else { 65383 breakTimeMin = 0; 65384 tr.find('.tc-column-break-time').text(''); 65385 } 65386 65387 diffMin -= breakTimeMin; 65388 var diffMinNice = UTIL.pluralLabel(UTIL.coalesceMoney(diffMin/60), 'hr'); 65389 var diffMinTitle = UTIL.pluralLabel(parseInt(diffMin/60), 'hour') + ' ' + UTIL.pluralLabel(diffMin % 60, 'minute'); 65390 tr.find('.tc-column-time-length').text(diffMinNice).attr('title', diffMinTitle); 65391 } 65392 } 65393 } 65394 _cTimecardManager.clickStaffName = function(element) { 65395 $(element).closest('tr').find('.timecard-copy-checkbox').click(); 65396 } 65397 _cTimecardManager.changeStaff = function(ddStaff) { 65398 var jstaff = $(ddStaff); 65399 var staffId = jstaff.val(); 65400 var jServiceListContainer = jstaff.closest('.timecard-filter').find('.timecard-manager-service-list'); 65401 65402 jServiceListContainer.find('.timecard-service-dd').remove(); 65403 65404 if (staffId > 0) { 65405 if (jstaff.attr('id') == 'Timecard_Staff_id') { 65406 var dropDownId = 'Timecard_Service_id'; 65407 } else { 65408 var dropDownId = 'New_Timecard_Service_id'; 65409 } 65410 65411 var htmServiceList = _getEmployeeServiceDropDown(staffId, dropDownId); 65412 jServiceListContainer.append(htmServiceList); 65413 } 65414 } 65415 function _getEmployeeServiceDropDown(staffId, dropDownId) { 65416 var sgs = $('#ServiceGroupOptionsClone').find('option[default_service_group_id="1009"]'); 65417 var foundCount = 0, newOptionList = ''; 65418 65419 for (var a=0; a < sgs.length; a++) { 65420 var sgid = sgs.eq(a).attr('value'); 65421 var optionList = UserPortal.getOriginalServiceDropDown(sgid); 65422 var joptions = $('<select>' + optionList + '</select>').find('option'); 65423 var xmlOptions = ''; 65424 65425 for (var i=0; i < joptions.length; i++) { 65426 var sids = joptions.eq(i).attr('staff_ids'); 65427
65428 if (sids.split(',').has(staffId)) { 65429 ++foundCount; 65430 xmlOptions += '<option value="' + joptions.eq(i).attr('value') + '">' + joptions.eq(i).text() + '</option>'; 65431 } 65432 } 65433 65434 if (sgs.length > 1) { 65435 xmlOptions = '<optgroup id="sgid"' + sgid + '>' + xmlOptions + '</optgroup>'; 65436 } 65437 65438 newOptionList += xmlOptions; 65439 } 65440 65441 if (foundCount > 0) { 65442 return '<select id="' + dropDownId + '" class="timecard-service-dd">' + newOptionList + '</select>'; 65443 } else { 65444 return ''; 65445 } 65446 } 65447 function _getStaffDropDown(staffId) { 65448 var jstaff = $('<select id="Timecard_Staff_id' + _lastRowId + '" class="timecard-staff">' + $('#timecard-manager #Timecard_Staff_id').html() + '</select>'); 65449 65450 if (staffId > 0) { 65451 jstaff.find('option[value="' + staffId + '"]').attr('selected', 'selected'); 65452 } 65453 65454 return jstaff.outerHTML(); 65455 } 65456 function _getTimecardRowHtm(staffId, serviceId, staffName, serviceName, scheduleMultiId, scheduleId, dtDay) { 65457 ++_lastRowId; 65458 var datepickerAttribute = '', trAttributes = '', rowCSS = 'timecard-is-new'; 65459 65460 if (GLO.Info.isMobile()) { 65461 datepickerAttribute = ' readonly="mobile"'; 65462 } 65463 65464 var removeRow = '<span class="ticket-row-remove" onclick="SA.TimecardManager.removeTimecard(this)"> <span class="ui-icon ui-icon-circle-close"></span> </span>'; 65465 //var ddStaff = _getStaffDropDown(staffId); 65466 var datepicker = '<input type="text" id="dayTimecard' + _lastRowId + '" class="timecard-day" placeholder="Day" style="z-index: 10;" pattern="[0-9]*"' 65467 + datepickerAttribute + ' onchange="SA.TimecardManager.changeDay(this)"/>'; 65468 65469 var clockInTime = '<input type="text" id="tmClockin' + _lastRowId + '" class="clock-time clockin-time" placeholder="In" pattern="[0-9]*" onchange="SA.TimecardManager.changeTime(this, true)">'; 65470 var clockOutTime = '<input type="text" id="tmClockout' + _lastRowId + '" class="clock-time clockout-time" placeholder="Out" pattern="[0-9]*" onchange="SA.TimecardManager.changeTime(this)">'; 65471 65472 if (!UTIL.isEmpty(scheduleId)) { 65473 var displayDay = dtDay.getWeekDayString(true) + ', ' + dtDay.getMonthString(true) + ' ' + dtDay.getDate(); 65474 65475 rowCSS = 'timecard-is-edit timecard-is-loading'; 65476 trAttributes = ' schedule_multi_id="' + scheduleMultiId + '" schedule_id="' + scheduleId + '" day_d="' + dtDay.toGloDate() + '"'; 65477 datepicker = '<a onclick="UserPortal.Edit.get(' + scheduleMultiId + ')">' + displayDay + '</a>'; 65478 } 65479 65480 return '<tr class="' + rowCSS + '" service_id="' + $.trim(serviceId) + '" staff_id="' + $.trim(staffId) + '"' + trAttributes + '>' 65481 + '<td class="tc-column-checkbox">' + removeRow + '</td>' //<input class="timecard-copy-checkbox" type="checkbox"/> 65482 + '<td class="tc-column-staff-name">' + staffName + '</td>' 65483 + '<td class="tc-column-service-name">' + serviceName + '</td>' 65484 + '<td class="tc-column-day" order_by="0">' + datepicker + '</td>' 65485 65486 + '<td class="tc-column-clockin">' + clockInTime + '</td>' 65487 + '<td class="tc-column-clockout">' + clockOutTime + '</td>' 65488 65489 + '<td class="tc-column-time-length"></td>' 65490 + '<td class="tc-column-break-time"></td>' 65491 + '<td class="tc-column-edit"></td>'
65492 + '</tr>'; 65493 } 65494 65495 function _getStaffAndServiceFilterHtm() { 65496 var jsearch = $('#timecard-manager-search'); 65497 var jstaff = jsearch.find('#Timecard_Staff_id'); 65498 var jservice = jsearch.find('#Timecard_Service_id'); 65499 65500 var staffId = jstaff.val(), serviceId = jservice.val(); 65501 var ddStaff = '<span class="timecard-manager-staff-list">' + jstaff.clone().attr('id', 'New_Timecard_Staff_id').outerHTML() + '</span>'; 65502 var ddService = '<span class="timecard-manager-service-list"></span>'; //' + $.trim(jservice.clone().attr('id', 'New_Timecard_Service_id').outerHTML()) + ' 65503 65504 return '<div id="pop-new-timecard-staff-service">' + ddStaff + ddService + '</div>'; 65505 } 65506 function _initStaffAndServiceFilterPopup(jpop) { 65507 var jsearch = $('#timecard-manager-search'); 65508 var staffId = jsearch.find('#Timecard_Staff_id').val(); 65509 var serviceId = jsearch.find('#Timecard_Service_id').val(); 65510 65511 if (staffId > 0) { 65512 jpop.find('#New_Timecard_Staff_id').val(staffId).change(); 65513 65514 if (serviceId > 0) { 65515 jpop.find('#New_Timecard_Service_id').val(serviceId); 65516 } 65517 } 65518 } 65519 _cTimecardManager.removeTimecard = function(element) { 65520 $(element).closest('tr').remove(); 65521 } 65522 _cTimecardManager.openNew = function() { 65523 var filter1 = _getStaffAndServiceFilterHtm(); 65524 var datepickerAttribute = ''; 65525 65526 if (GLO.Info.isMobile()) { 65527 datepickerAttribute = ' readonly="mobile"'; 65528 } 65529 65530 var label1 = '<label for="Timecard_Count_nr">Add</label>'; 65531 var label2 = '<label for="Timecard_Count_nr">Timecards to Edit</label>'; 65532 var inputCount = '<input id="Timecard_Count_nr" type="text" maxlength="3" pattern="[0-9]*" value="1" onkeypress="UI.numberOnly()" style="width: 40px;"/>'; 65533 var msg = '<p>' + label1 + inputCount + label2 + '</p>'; 65534 65535 var labelDates = '<p><label for="New_Start_Timecard_dt">Or create timecards over this date range</label></p>'; 65536 var inputStart = '<input type="text" id="New_Start_Timecard_dt" class="Begin_dt timecard-date-filter" placeholder="Begin Day" style="z-index: 10;"' + datepickerAttribute + '/>'; 65537 var inputEnd = '<input type="text" id="New_End_Timecard_dt" class="End_dt timecard-date-filter" placeholder="End Day" style="z-index: 10;"' + datepickerAttribute + '/>'; 65538 var filter2 = '<div id="pop-new-timecard-dates">' + labelDates + inputStart + '<b> - </b>' + inputEnd + '</div>'; 65539 65540 var styleDatepicker = '<style> .ui-datepicker { z-index: 9999 !important; } </style>'; 65541 var htmFilter = '<div class="timecard-filter">' + filter1 + '<fieldset>' + msg + filter2 + '</fieldset></div>'; 65542 var htm = '<div id="pop-new-timecard-rows">' + styleDatepicker + htmFilter + '</div>'; 65543 65544 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Add Timecard Rows for Staff', SA.TimecardManager.addNewRows, null, true); 65545 var jpop = ojpop.getPopup(); 65546 65547 jpop.find('.btnSave').css({ "margin": "0", "width": "200px" }).find('> a').text('Create Timecard Rows'); 65548 65549 jpop.find('#New_Start_Timecard_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 65550 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 65551 jpop.find('#New_End_Timecard_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 65552 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 65553 65554 _initStaffAndServiceFilterPopup(jpop); 65555 ojpop.saveOnEnter(); 65556 } 65557 _cTimecardManager.addNewRows = function() { 65558 var jpop = $('#pop-new-timecard-rows').closest('.glopop'); 65559 var staffId = jpop.find('#New_Timecard_Staff_id').val(); 65560 65561 if (!_isValidNewTimecardFilter(staffId)) { return; } 65562 65563 GLO.UI.Form.beginProcessing(jpop.find('.btnSave')); 65564 65565 setTimeout(function() { 65566 SA.TimecardManager.addNewRows2(jpop, staffId); 65567 }, 100); 65568 } 65569 _cTimecardManager.addNewRows2 = function(jpop, staffId) { 65570 var serviceId = jpop.find('#New_Timecard_Service_id').val(); 65571 var staffName = jpop.find('#New_Timecard_Staff_id option:selected').text(); 65572 var serviceName = jpop.find('#New_Timecard_Service_id option:selected').text(); 65573 65574 var dtStart = null, start = jpop.find('#New_Start_Timecard_dt').val(); 65575 var end = jpop.find('#New_End_Timecard_dt').val(); 65576 var count = UTIL.coalesceInt(jpop.find('#Timecard_Count_nr').val(), 1); 65577 var trnew1, tbody = $('#timecard-list > tbody'); 65578 65579 if (UTIL.isDate(start)) { 65580 dtStart = new Date(start); 65581 65582 if (UTIL.isDate(end)) { 65583 count = UTIL.dayDiff(dtStart, new Date(end)) + 1; 65584 } 65585 } 65586 65587 for (var i=0; i < count; i++) { 65588 var trhtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName); 65589 var trnew = _loadNewRow(tbody, trhtm, dtStart); 65590 65591 if (i == 0) { trnew1 = trnew; } 65592 } 65593 65594 GLO.Popup.close(jpop); 65595 trnew1.find('.timecard-day').focus(); 65596 } 65597 function _loadNewRow(tbody, trhtm, dtStart) { 65598 var trLastNew = _getLastEditRow(tbody); 65599 65600 if (trLastNew.length) { 65601 trLastNew.after(trhtm); 65602 } else { 65603 tbody.prepend(trhtm); 65604 } 65605 65606 var tr = _getLastEditRow(tbody); 65607 return _setRowDateAndTime(tr, dtStart); 65608 } 65609 function _getLastEditRow(tbody) { 65610 var tr = tbody.find('tr.timecard-is-new:last, tr.timecard-is-edit:last'); 65611 65612 if (tr.length > 1) { 65613 return tr.eq(tr.length - 1); 65614 } else { 65615 return tr; 65616 } 65617 } 65618 function _setRowDateAndTime(tr, dtStart) { 65619 var inId = tr.find('.clockin-time').attr('id'); 65620 var outId = tr.find('.clockout-time').attr('id'); 65621 65622 var jday = tr.find('.timecard-day').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek 65623 , numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
65623atepicker }); //, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1 65624 65625 UI.timeMask('#' + inId); 65626 UI.timeMask('#' + outId, '11:59 am'); 65627 UI.highlight(tr, null, null, true); 65628 65629 if (UTIL.isDate(dtStart)) { 65630 jday.val(dtStart.toGloDate()); 65631 dtStart.addDays(1); 65632 } 65633 65634 return tr; 65635 } 65636 function _isValidNewTimecardFilter(staffId) { 65637 if (UTIL.isEmpty(staffId)) { 65638 var msgWarn = '<div id="pop-warn-new-timecard">Please choose person you want to create timecards for</div>'; 65639 var fnWarn = function() { 65640 $('#pop-new-timecard-rows').closest('.glopop').find('#New_Timecard_Staff_id').focus(); 65641 }; 65642 65643 GLO.Popup.Warning.open(msgWarn, 'Please Select Person', fnWarn); 65644 return false; 65645 } 65646 65647 return true; 65648 } 65649 65650 _cTimecardManager.openCopy = function() { 65651 if ($('#timecard-list').hasClass('timecard-list-copy')) { 65652 var msg1 = '<p>Please Save Copied Timecards on Screen</p>'; 65653 var msg2 = '<p>Or Press Search to Clear these copied timecards and load existing timecards</p>'; 65654 var htm = '<div id="pop-warn-copy-timecard-in-progress">' + msg1 + msg2 + '</div>'; 65655 65656 GLO.Popup.Warning.open(htm, 'Copy Already in Progress'); 65657 return; 65658 } 65659 65660 var htmFilter = _getStaffAndServiceFilterHtm(); 65661 var jboxes = _getBoxesToCopy(); 65662 65663 if (jboxes.length) { 65664 var msg1 = '<p style="letter-spacing: 0;">This will copy ' + UTIL.pluralLabel(jboxes.length, 'timecard') + ' and display the copied timecards for you to edit</p>'; 65665 var msg2 = '<p style="text-align: center;">Select the staff for the new timecards</p>'; 65666 65667 htmFilter = '<div class="timecard-filter" style="margin-bottom: 24px;">' + htmFilter + '</div>'; 65668 var htm = '<div id="pop-copy-timecard-rows">' + msg1 + msg2 + htmFilter + '</div>'; 65669 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Copy Staff Timecards', SA.TimecardManager.copyTimecards, null, true); 65670 var jpop = ojpop.getPopup(); 65671 65672 jpop.find('.btnSave').css({ "margin": "0", "width": "160px" }).find('> a').text('Copy Timecards'); 65673 65674 _initStaffAndServiceFilterPopup(jpop); 65675 ojpop.saveOnEnter(); 65676 } 65677 } 65678 _cTimecardManager.copyTimecards = function() { 65679 var jpop = $('#pop-copy-timecard-rows').closest('.glopop'); 65680 var jstaff = jpop.find('#New_Timecard_Staff_id'); 65681 var jservice = jpop.find('#New_Timecard_Service_id'); 65682 65683 var staffId = jstaff.val(), staffName = jstaff.find('option:selected').text(); 65684 var serviceId = jservice.val(), serviceName = jservice.find('option:selected').text(); 65685 65686 var trnew1, copyCount = 0; 65687 var jtbl = $('#timecard-list'); 65688 var tbody = jtbl.find('tbody'); 65689 var trs = jtbl.find('tbody tr'); //_getBoxesToCopy(); 65690 65691 for (var i=0; i < trs.length; i++) { 65692 var tr = trs.eq(i); 65693 65694 if (tr.find('.timecard-copy-checkbox').prop('checked')) { 65695 ++copyCount; 65696 65697 var day = new Date(tr.attr('day_d')); 65698 var trhtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName); 65699 var trnew = _loadNewRow(tbody, trhtm, day); 65700 65701 var clockIn = tr.find('.tc-column-clockin').text(); 65702 var clockOut = tr.find('.tc-column-clockout').text(); 65703 65704 //trnew.find('.timecard-day').val(day).change(); 65705 trnew.find('.clockin-time').val(clockIn).change(); 65706 trnew.find('.clockout-time').val(clockOut).change(); 65707 65708 if (i == 0) { trnew1 = trnew; } 65709 65710 //tr.removeAttr('schedule_id').removeAttr('schedule_multi_id').removeAttr('special_request_vcl'); 65711 //tr.attr('staff_id', staffId).attr('service_id', serviceId); 65712 //tr.find('.tc-column-staff-name').text(staffName); 65713 //tr.find('.tc-column-service-name').text(serviceName); 65714 //tr.find('.timecard-copy-checkbox').remove(); 65715 } 65716 65717 tr.remove(); 65718 } 65719 65720 jtbl.find('thead').find('#timecard-all-checkboxes').remove(); 65721 jtbl.addClass('timecard-list-copy'); 65722 65723 GLO.Popup.close(); 65724 _displayCopyTimecardMessage(copyCount); 65725 65726 var jday = trnew1.find('.timecard-day:first'); 65727 65728 if (UTIL.isEmpty(jday.val)) { 65729 jday.focus(); 65730 } 65731 } 65732 function _displayCopyTimecardMessage(copyCount) { 65733 var btnSave = '<span id="btnTimecardManagerSavePopup" class="btnSave"> <a onclick="SA.TimecardManager.openSave()">Save</a> </span>'; 65734 var header = UTIL.pluralLabel(copyCount, 'Timecard') + ' Copied'; 65735 var msg1 = '<p>' + header + ' + Only the New Copied Timecards are displayed</p>'; 65736 var msg2 = '<p>Change the timecards as needed then press ' + btnSave + ' to create these new timecards</p>'; 65737 65738 var htm = '<div id="pop-copy-timecard-success">' + msg1 + msg2 + '</div>'; 65739 var ojpop = GLO.Popup.Custom.openSimple(htm, 'Copy Staff Timecards', SA.TimecardManager.copyTimecards, null, true); 65740 var jpop = ojpop.getPopup(); 65741 65742 GLO.Popup.Custom.singleButton(jpop, 'Close'); 65743 ojpop.saveOnEnter(); 65744 } 65745 function _getBoxesToCopy() { 65746 var boxes = $('#timecard-list tbody .timecard-copy-checkbox:checked'); 65747 65748 if (boxes.length === 0) { 65749 var msg = '<p>Check the box next to the timecard(s) you would like to copy</p>'; 65750 var fn = function() { 65751 UI.highlight($('#timecard-list .tc-column-checkbox')); 65752 } 65753 65754 GLO.Popup.Warning.open('<div id="pop-warn-timecard-copy">' + msg + '</div>', 'No Timecards Selected to Copy', fn); 65755 } 65756 65757 return boxes; 65758 } 65759
65760 _cTimecardManager.switchRowToEdit = function(btn) { 65761 var trCurrent = $(btn).closest('tr'); 65762 65763 var staffId = trCurrent.attr('staff_id'); 65764 var serviceId = trCurrent.attr('service_id'); 65765 var staffName = trCurrent.find('.tc-column-staff-name').text(); 65766 var serviceName = trCurrent.find('.tc-column-service-name').text() 65767 65768 var scheduleMultiId = trCurrent.attr('schedule_multi_id'); 65769 var scheduleId = trCurrent.attr('schedule_id'); 65770 65771 var day = new Date(trCurrent.attr('day_d')); 65772 var tmIn = trCurrent.find('.tc-column-clockin').text(); 65773 var tmOut = trCurrent.find('.tc-column-clockout').text(); 65774 65775 var trHtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName, scheduleMultiId, scheduleId, day); 65776 trCurrent.replaceWith(trHtm); 65777 var trNew = $('#timecard-list').find('.timecard-is-loading').removeClass('timecard-is-loading'); 65778 65779 _setRowDateAndTime(trNew, day); 65780 65781 trNew.find('.clockin-time').val(tmIn); 65782 trNew.find('.clockout-time').val(tmOut).change(); 65783 } 65784 65785 _cTimecardManager.openSave = function() { 65786 GLO.Popup.close($('#pop-copy-timecard-success').closest('.glopop')); 65787 65788 var newTimecardCount = $('#timecard-list').find('tr.timecard-is-new, tr.timecard-is-edit').length; 65789 var msg = '<p>Do you want to save ' + UTIL.pluralLabel(newTimecardCount, 'timecard') + '</p>'; 65790 var htm = '<div id="pop-confirm-timecard-save">' + msg + '</div>'; 65791 65792 var fn = function() { 65793 SA.TimecardManager.openSaveConfirmed(newTimecardCount); 65794 } 65795 65796 GLO.Popup.Confirm.open(htm, 'Confirm Save Timecards', fn); 65797 } 65798 _cTimecardManager.openSaveConfirmed = function(newTimecardCount) { 65799 var xml = _getTimecardXml(); 65800 65801 if (UTIL.coalesceInt(xml.length, 0) < 20) { //= do NOT invalid save invalid timecard. 65802 return; 65803 } 65804 65805 var url = GLO.Link.WebsiteDomain + 'schedule/TimecardSave'; 65806 var jdata = { "timecards": UTIL.htmlEncode(xml) }; 65807 65808 GLO.UI.Form.beginProcessing($('#btnTimecardManagerSave')); 65809 65810 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdata }) 65811 .success(function(data, textStatus, jqXHR) { 65812 var jfilter = $('#timecard-manager-search .timecard-filter'); 65813 var staffName = jfilter.find('#Timecard_Staff_id option:selected').text(); 65814 var dateFilter = jfilter.find('.Begin_dt ').val() + ' - ' + jfilter.find('.End_dt ').val(); 65815 65816 var msg1 = '<p>' + UTIL.pluralLabel(newTimecardCount, 'Timecard') + ' Saved</p>'; 65817 var msg2 = '<p>Re-loading Timecards for ' + staffName + ' between ' + dateFilter + '...</p>'; 65818 65819 //GLO.UI.Form.resetProcessing(); 65820 GLO.Popup.Success.open('<div id="pop-timecard-save">' + msg1 + msg2 + '</div>', 'Save Successful'); 65821 65822 _cTimecardManager.search(); 65823 }) 65824 .error(function(jqXHR, textStatus, errorThrown) { 65825 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65826 GLO.UI.Form.resetProcessing(); 65827 }); 65828 } 65829 function _getTimecardXml() { 65830 var xml = ''; 65831 var trs = $('#timecard-list > tbody').find('tr.timecard-is-new, tr.timecard-is-edit'); 65832 65833 for (var i=0; i < trs.length; i++) { 65834 var tr = trs.eq(i); 65835 var staffId = tr.attr('staff_id'); //.find('.timecard-staff').val(); 65836 var serviceId = tr.attr('service_id'); 65837 65838 var scheduleId = $.trim(tr.attr('schedule_id')); 65839 var breakTime = $.trim(tr.find('.tc-column-break-time').text().replace('minutes', '').replace('min', '').replace('hr', '')); 65840 65841 var day = UTIL.coalesceDate(tr.find('.timecard-day').val(), tr.attr('day_d')).toGloDate(); 65842 var tmIn = tr.find('.clockin-time').val(); 65843 var tmOut = tr.find('.clockout-time').val(); 65844 65845 var dtIn = day + ' ' + $.trim(tmIn); 65846 var dtOut = day + ' ' + $.trim(tmOut); 65847 65848 if (!UTIL.isValidTime(tmIn)) { 65849 return GLO.Popup.Warning.open('Please Enter Valid Clock-In Time', 'Invalid Clock-In Time'); 65850 } else if (!UTIL.isValidTime(tmOut)) { 65851 return GLO.Popup.Warning.open('Please Enter Valid Clock-Out Time', 'Invalid Clock-Out Time'); 65852 } else if (!UTIL.isDate(dtIn)) { 65853 return GLO.Popup.Warning.open('Please Enter Valid Day for the Timecard', 'Invalid Clock-In Time'); 65854 } 65855 65856 xml += '<timecard staff_id="' + staffId + '" service_id="' + serviceId + '" schedule_id="' + scheduleId + '" break_sr="' + breakTime + '" in_dt="' + dtIn + '" out_dt="' + dtOut + '"/>'; 65857 } 65858 65859 return '<manager>' + xml + '</manager>'; 65860 } 65861 65862 _cTimecardManager.openDelete = function() { 65863 var deleteCount = $('#timecard-list tbody .tc-column-checkbox input:checked').length; 65864 65865 if (deleteCount == 0) { 65866 var msg1 = '<p>No Timecards Selected</p>'; 65867 var msg2 = '<p>Check the box next to the timecard(s) you would like to delete</p>'; 65868 var fn = function() { 65869 UI.highlight($('#timecard-list .tc-column-checkbox')); 65870 } 65871 65872 GLO.Popup.Warning.open('<div id="pop-warn-timecard-delete">' + msg1 + msg2 + '</div>', 'No Timecards Selected to Delete', fn); 65873 } else { 65874 var msg = '<p>Do you want to delete ' + UTIL.pluralLabel(deleteCount, 'timecard') + '</p>'; 65875 var htm = '<div id="pop-confirm-timecard-save">' + msg + '</div>'; 65876 65877 var fn = function() { 65878 SA.TimecardManager.openDeleteConfirmed(deleteCount); 65879 } 65880 65881 GLO.Popup.Confirm.open(htm, 'Confirm Delete Timecards', fn); 65882 } 65883 } 65884 _cTimecardManager.openDeleteConfirmed = function(deleteTimecardCount) { 65885 var xml = '', trs = $('#timecard-list tbody .tc-column-checkbox input:checked').closest('tr'); 65886 var deleteReason = ''; //toDo: add field in UI 65887 65888 for (var i=0; i < trs.length; i++) { 65889 xml += '<dl schedule_multi_id="' + trs.eq(i).attr('schedule_multi_id') + '" schedule_id="' + trs.eq(i).attr('schedule_id') + '"/>'; 65890 } 65891 65892 var xml = UTIL.htmlEncode('<ul>' + xml + '</ul>'); 65893 var jdata = { "timecards": xml, "reason": deleteReason }; 65894 var url = GLO.Link.WebsiteDomain + 'schedule/TimecardDelete'; 65895 65896 GLO.UI.Form.beginProcessing($('#btnTimecardManagerDelete')); 65897
65898 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdata }) 65899 .success(function(data, textStatus, jqXHR) { 65900 var jfilter = $('#timecard-manager-search .timecard-filter'); 65901 var staffName = jfilter.find('#Timecard_Staff_id option:selected').text(); 65902 var dateFilter = jfilter.find('.Begin_dt ').val() + ' - ' + jfilter.find('.End_dt ').val(); 65903 65904 var msg1 = '<p>' + UTIL.pluralLabel(deleteTimecardCount, 'Timecard') + ' Deleted</p>'; 65905 var msg2 = '<p>Re-loading Timecards for ' + staffName + ' between ' + dateFilter + '...</p>'; 65906 65907 //GLO.UI.Form.resetProcessing(); 65908 GLO.Popup.Success.open('<div id="pop-timecard-delete-success">' + msg1 + msg2 + '</div>', 'Delete Successful'); 65909 65910 _cTimecardManager.search(); 65911 }) 65912 .error(function(jqXHR, textStatus, errorThrown) { 65913 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65914 GLO.UI.Form.resetProcessing(); 65915 }); 65916 } 65917 65918 _cTimecardManager.openPrint = function() { 65919 window.print(); 65920 } 65921 65922 function _setPrintHeader() { 65923 var header2 = '<b>' + GLO.Data.provider.name + '</b> <span>' + UTIL.formatPhone(GLO.Data.provider.phone) + '</span>'; 65924 var jfilter = $('#timecard-manager-search'); 65925 var jheader = $('#timecard-manager-print-header'); 65926 65927 var staffId = jfilter.find('#Timecard_Staff_id').val(); 65928 var staffName = jfilter.find('#Timecard_Staff_id option:selected').text(); 65929 var start = jfilter.find('.Begin_dt').val(); 65930 var end = jfilter.find('.End_dt').val(); 65931 65932 jheader.find('#timecard-manager-print-header-dates').html(start + ' - ' + end); 65933 jheader.find('h4').html(header2); 65934 } 65935 65936 _cTimecardManager.search = function() { 65937 var jfilter = $('#timecard-manager-search'); 65938 var staffId = jfilter.find('#Timecard_Staff_id').val(); 65939 var serviceId = $.trim(jfilter.find('#Timecard_Service_id').val()); 65940 var start = jfilter.find('.Begin_dt').val(); 65941 var end = jfilter.find('.End_dt').val(); 65942 65943 var queryString = 'staff=' + staffId + '&service=' + serviceId + '&start=' + start + '&end=' + end; 65944 var url = GLO.Link.WebsiteDomain + 'schedule/TimecardManagerSearch?' + queryString; 65945 65946 GLO.UI.Form.beginProcessing(jfilter.find('#btnTimecardSearch')); 65947 $('#timecard-manager-data .noResults').text('Looking up Timecards...'); 65948 65949 var jqxhr = $.ajax({ type: "GET", url: url, "cache": false }) 65950 .success(function(data, textStatus, jqXHR) { 65951 GLO.UI.Form.resetProcessing(); 65952 var jrpt = $('#timecard-manager-data.report-container'); 65953 65954 jrpt.html(data); 65955 var jtbl = $('#timecard-manager-data #timecard-list.tablesorter'); 65956 65957 UI.initTableSorter(jtbl, null, true); 65958 GLO.Report.enableFullPageCheck(); 65959 GLO.Report.CellSummary.initReport(jtbl, true, true); 65960 65961 _setPrintHeader(); 65962 65963 try { 65964 url = GLO.Link.WebsiteDomain + 'schedule/TimecardManage?' + queryString; 65965 window.history.pushState("", "Timecard Manager", url); 65966 } catch (e) { } 65967 }) 65968 .error(function(jqXHR, textStatus, errorThrown) { 65969 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 65970 GLO.UI.Form.resetProcessing(); 65971 }); 65972 } 65973 65974 return _cTimecardManager; 65975})(); 65976 65977GLO.RunningTotal = (function() { 65978 function _conRunTotal() { } 65979 _conRunTotal.unRequestedHours; 65980 var isInitialized = false, _sortByPrice = (GLO.runningTotalOrder == 1), _sortByTurns = (GLO.runningTotalOrder == 3); 65981 var _sortByTime = (!_sortByPrice && !_sortByTurns); 65982 65983 function _init() { 65984 var sid, arr = []; 65985 var ths = $('.fc-view-resourceDay .fc-agenda-days').find('thead').find('th'); 65986 65987 for (var i=1; i < ths.length-1; i++) { 65988 sid = ths.eq(i).attr('id'); 65989 65990 arr.push({ "id": sid, "hrs": "", "price": "", "turns": "" }); 65991 } 65992 65993 _conRunTotal.unRequestedHours = arr; 65994 isInitialized = true; 65995 } 65996 65997 _conRunTotal.displayRunningTotal = function() { 65998 if (GLO.displayRunningTotal) { 65999 if (!isInitialized) { _init(); } 66000 66001 if (GLO.Calendar.isToday()) { 66002 var arr = _calculate(); 66003 _setup(arr); 66004 _conRunTotal.TurnTracker.setStaffOrderHeader(); 66005 } else { 66006 _tearDown(); 66007 } 66008 } 66009 } 66010 66011 function _isClientService(calEvent) { 66012 if (!calEvent.className.has("cal-monthDayPersonal") && !calEvent.className.has("cal-InternalService") && !calEvent.className.has("cal-time-off") && !calEvent.className.has("cal-time-off-end")) { 66013 if (!UTIL.parseBool(calEvent.is_finish_out_fl)) { 66014 return true; 66015 } 66016 } 66017 66018 return false; 66019 } 66020 66021 function _calculate() { 66022 var sid, hrs, svc, price, oj; 66023 var evs = GLO.Calendar.cal.fullCalendar('clientEvents'); 66024 66025 for (var a=0; a < _conRunTotal.unRequestedHours.length; a++) { 66026 _conRunTotal.unRequestedHours[a].hrs = 0; 66027 _conRunTotal.unRequestedHours[a].price = 0; 66028 _conRunTotal.unRequestedHours[a].turns = 0; 66029 } 66030 66031 for (var i=0; i < evs.length; i++) { //~ loop in case there is a finish out. 66032 if (!UTIL.parseBool(evs[i].client_request_fl) && _isClientService(evs[i])) { 66033 sid = evs[i].staff_id; 66034 svc = UserPortal.Calendar.lookupService(evs[i].service_id); 66035 66036 if (!UTIL.isEmpty(svc)) { // = cannot lookup service in diff location. 66037 hrs = UTIL.coalesceFloat(svc.total_minutes_nr, evs[i].minutes_nr, 0) / 60; 66038 66039 price = UTIL.cleanString(svc.price).replace('+', ''); 66040 price = UTIL.coalesceMoney(price, evs[i].price_mn, 0); 66041 66042 turns = UTIL.coalesceFloat(evs[i].turns_dr, 0); 66043 66044 oj = UTIL.findObjectInArray(_conRunTotal.unRequestedHours, sid); 66045 oj.hrs = UTIL.roundMoney(UTIL.coalesceFloat(oj.hrs, 0) + hrs); 66046 oj.price = UTIL.roundMoney(UTIL.coalesceMoney(oj.price, 0) + price); 66047 oj.turns = UTIL.coalesceFloat(UTIL.coalesceFloat(oj.turns, 0) + turns); 66048 } 66049 } 66050 } 66051 } 66052 66053 function _significantDiff(amt, compare) { //= difference must be >= $10 or 10 minutes + > 5% 66054 if (amt < compare) { 66055 return true; 66056 66057 /* if (amt + 10 < compare) { 66058 if (amt * .95 < compare) { 66059 return true; 66060 } 66061 } */ 66062 } 66063 } 66064 66065 _conRunTotal.getResourceStaffColor = function(staffId) { 66066 var i = 0; 66067 var len = GLO.resourceHours.length; 66068 66069 for (; i < len; i++) { 66070 if (staffId == GLO.resourceHours[i].id) { 66071 return GLO.resourceHours[i].color; 66072 } 66073 } 66074 } 66075 66076 function _setup(arr) {
66077 var htm, sid, ojHrs, amt, next = null, ondeck = null; 66078 var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead'); 66079 var ths = thead.find('th'); 66080 66081 if (ths.eq(2).find('.turn-tracker-staff').length > 0) { 66082 var hasSpan = true, spanTitle = ''; 66083 } else { 66084 var hasSpan = false, spanTitle = SA.Resource.UnrequestedClientHours; 66085 } 66086 66087 for (var i=1; i < ths.length-1; i++) { 66088 var thClass = '', th = ths.eq(i); 66089 sid = th.attr('id'); 66090 ojHrs = UTIL.findObjectInArray(_conRunTotal.unRequestedHours, sid); 66091 66092 if (_sortByPrice) { 66093 amt = ojHrs.price; 66094 } else if (_sortByTurns) { 66095 amt = ojHrs["turns"]; 66096 } else { 66097 amt = ojHrs["hrs"]; 66098 } 66099 66100 if (!UTIL.isDate(GLO.staffResources[i-1].signin)) { 66101 if (amt === 0) { amt = SA.Resource.Signin.toLowerCase(); } 66102 66103 thClass = 'run-total-sign-in'; 66104 spanTitle = SA.Resource.SigninHelp; 66105 } else { 66106 spanTitle = SA.Resource.ServiceTotalToday; 66107 66108 if (next === null || _significantDiff(amt, next)) { 66109 ondeck = next; 66110 next = amt; 66111 _setNext(thead, th, hasSpan); 66112 66113 if (amt == 0) { amt = SA.Resource.Next.toLowerCase(); } 66114 } else if (ondeck === null || _significantDiff(amt, ondeck)) { 66115 ondeck = amt; 66116 _setOnDeck(thead, th, hasSpan); 66117 66118 if (amt == 0) { amt = ''; } 66119 } 66120 } 66121 66122 if (GLO.Info.roleType < 220 || amt == 0) { 66123 amt = ''; 66124 } else if (UTIL.isNumber(amt)) { 66125 if (_sortByPrice) { 66126 amt = '$' + parseInt(amt); 66127 } else if (_sortByTurns) { 66128 if (amt > 0) { //= bonus are counted as decimals: replace the decimals with '+' 66129 var bonusCount = parseInt((amt - parseInt(amt)) * 10); 66130 66131 for (var i=0; i < bonusCount; i++) { 66132 amt = UTIL.coalesceString(amt) + '+'; 66133 } 66134 } else { 66135 amt = ''; 66136 } 66137 } else { 66138 if (amt == 1) { 66139 amt = amt + ' hr'; // + SA.Resource.Hour.toLowerCase(); 66140 } else { 66141 amt = amt + ' hr'; // + SA.Resource.Hours.toLowerCase(); 66142 } 66143 66144 if (amt.substring(0,2) === '0.') { amt = amt.substring(1); } 66145 } 66146 } 66147 66148 if (th.hasClass('fc-col-first-available') || (i == 1 && $('#calendar .fc-col-first-available').length > 0) ) { //= first check handles page load, second handles sign-in. 66149 } else { 66150 if (hasSpan) { 66151 th.find('.run-total').text(amt); 66152 } else { 66153 htm = '<span class="turn-tracker-staff" onclick="GLO.RunningTotal.clickHeader(event, this)" title="' + spanTitle + '"><span class="run-total">
66153' + amt + '</span></span>'; 66154 var cssStyle = '', color = th.css('color'); 66155 66156 if (th.hasClass('hasCustomColor')) { 66157 //cssStyle = ' style="background-color: ' + color + ';"'; 66158 th.css({ "background-color": " + color + " }); 66159 } 66160 66161 th.html(htm + '<span class="run-total-staff-name"' + cssStyle + '>' + ths.eq(i).text() + '</span>'); 66162 66163 th.off('click', GLO.Calendar.resourceHeaderClick); 66164 th.find('.run-total-staff-name').click(GLO.Calendar.resourceHeaderClick); 66165 } 66166 66167 th.addClass(thClass); 66168 } 66169 } 66170 } 66171 66172 function _setNext(thead, th, hasSpan) { 66173 var className = 'run-total-next', cssOnDeck = 'run-total-on-deck'; 66174 66175 thead.find('.' + cssOnDeck).removeClass(cssOnDeck) 66176 var prev = thead.find('.' + className).removeClass(className).addClass(cssOnDeck); 66177 66178 if (prev.text() === '') { prev.text('next'); } 66179 66180 th.addClass(className); 66181 return className; 66182 } 66183 66184 function _setOnDeck(thead, th, hasSpan) { 66185 var className = 'run-total-on-deck'; 66186 var prev = thead.find('.' + className).removeClass(className); 66187 66188 //if (prev.text() === 'next') { prev.text(''); } 66189 //if (hasSpan) { th.addClass(className); } 66190 66191 th.addClass(className); 66192 return className; 66193 } 66194 66195 function _tearDown() { 66196 if (_conRunTotal.unRequestedHours && _conRunTotal.unRequestedHours.length) { 66197 for (var i=0; i < _conRunTotal.unRequestedHours.length; i++) { 66198 _conRunTotal.unRequestedHours[i].hrs = ""; 66199 _conRunTotal.unRequestedHours[i].price = 0; 66200 _conRunTotal.unRequestedHours[i].turns = 0; 66201 } 66202 } 66203 66204 var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead'); 66205 thead.find('th .turn-tracker-staff').css({ "background-color": "" }).text(''); 66206 66207 thead.find('th').removeClass('has-staff-order'); 66208 thead.find('th').off('click', GLO.Calendar.resourceHeaderClick); //= avoids duplicate calls to: resourceHeaderClick 66209 thead.find('th').on('click', GLO.Calendar.resourceHeaderClick); 66210 } 66211 66212 _conRunTotal.clickHeader = function(event, element) { 66213 var el = $(element); 66214 var th = el.closest('th'); 66215 66216 if (th.hasClass('run-total-sign-in')) { 66217 _conRunTotal.signin(th); 66218 } else { 66219 var firstName = th.find('.run-total-staff-name').text(); 66220 _conRunTotal.OrderCalendar.openPopup(th, firstName); 66221 } 66222 66223 //return UTIL.cancelEvent(event); 66224 } 66225 66226 _conRunTotal.signinByStaffId = function(staffid) { 66227 var ths = $('.fc-view-resourceDay').find('thead th'); 66228 66229 for (var i=0; i < ths.length; i++) { 66230 if (ths.eq(i).attr('id') == staffid) { 66231 _conRunTotal.signin(ths.eq(i)); 66232 break; 66233 } 66234 } 66235 } 66236 66237 _conRunTotal.signin = function(th) { 66238 var sid = th.attr('id'); 66239 var sname = th.find('.run-total-staff-name').text(); 66240 var url = GLO.Link.WebsiteDomain + 'schedule/signin?staffid=' + sid; 66241 66242 var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignIn2 + ' ' + sname + '</h1><div class="friendly-msg2">' + SA.Resource.Signing_in + ' ' + sname + '...</div></div>'; 66243 var ojProcessing = new GLO.Popup.Processing(msg); //UI.displayProcessingLayer(); 66244 66245 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 66246 .success(function(data, textStatus, jqXHR) { 66247 ojProcessing.close(); //GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66248 var now = $(data).attr('now_dt'); 66249 66250 if (UTIL.isDate(now)) { 66251 _signinSuccess(sid, sname, now); 66252 th.find('.run-total-sign-in').removeClass('run-total-sign-in').removeAttr('title'); 66253 } 66254 }) 66255 .error(function(jqXHR, textStatus, errorThrown) { 66256 ojProcessing.close(); //GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66257 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 66258 }); 66259 } 66260 66261 _conRunTotal.signout = function(staffid, staffFirstName) { 66262 if (UTIL.isEmpty(staffFirstName)) { staffFirstName = UserPortal.lookupStaffName(staffid); } 66263 66264 var url = GLO.Link.WebsiteDomain + 'schedule/signout?staffid=' + staffid; 66265 var jpop = $('#pop-calendar-order').closest('.glopop'); 66266 var jbtn = jpop.find('#btnSignout'); 66267 66268 GLO.UI.Form.beginProcessing(jbtn); 66269
66270 var jqxhr = $.ajax({ type: "POST", url: url, "cache": false }) 66271 .success(function(data, textStatus, jqXHR) { 66272 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66273 GLO.Popup.close(jpop); 66274 66275 _signoutSuccess(staffid, staffFirstName); 66276 }) 66277 .error(function(jqXHR, textStatus, errorThrown) { 66278 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66279 GLO.Log.processesSecurityException(null, null, textStatus, jqXHR); 66280 }); 66281 } 66282 66283 function _reorderCalendar(showMessage) { 66284 if (GLO.Calendar === undefined) { return; } 66285 66286 if (showMessage) { 66287 var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.ReOrderCalendar + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingStaffOrderCalendar + '...</div></div>'; 66288 var ojProcessing = new GLO.Popup.Processing(msg); 66289 } 66290 66291 GLO.Schedule.Calendar.reloadCalendar(null, ojProcessing); 66292 } 66293 66294 function _signoutSuccess(sid, staffFirstName) { 66295 var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignOut + ' ' + staffFirstName + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingOrderFor + ' ' + staffFirstName + '...</div></div>'; 66296 var ojProcessing = new GLO.Popup.Processing(msg); 66297 66298 var fn = function() { _moveToLast(sid); }; 66299 66300 GLO.Schedule.Calendar.reloadCalendar(fn, ojProcessing); 66301 } 66302 66303 function _signinSuccess(sid, sname, now) { 66304 var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignIn2 + ' ' + sname + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingOrderFor + ' ' + sname + '...</div></div>'; 66305 var ojProcessing = new GLO.Popup.Processing(msg); 66306 var fn = function() { _reorderStaff(sid, now); } 66307 66308 GLO.Schedule.Calendar.reloadCalendar(fn, ojProcessing); 66309 } 66310 66311 function _moveToLast(sid) { 66312 var arrStaff; 66313 66314 for (var s=0; s < GLO.staffResources.length; s++) { 66315 if (sid == GLO.staffResources[s].id) { 66316 arrStaff = GLO.staffResources[s]; 66317 arrStaff.signin = ""; 66318 GLO.staffResources.splice(s, 1); 66319 break; 66320 } 66321 } 66322 66323 if (arrStaff) { GLO.staffResources.push(arrStaff); } 66324 } 66325 66326 function _reorderStaff(sid, now) { 66327 var moveTo = null, arrStaff; 66328 //var hasFA = $('#calendar .fc-col-first-available').length; 66329 66330 for (var s=0; s < GLO.staffResources.length; s++) { 66331 if (moveTo === null && UTIL.isEmpty(GLO.staffResources[s].signin) && !UTIL.parseBool(GLO.staffResources[s].is_first_available_fl)) { 66332 moveTo = s; 66333 } 66334 66335 if (sid == GLO.staffResources[s].id) { 66336 arrStaff = GLO.staffResources[s]; 66337 arrStaff.signin = now; 66338 GLO.staffResources.splice(s, 1); 66339 66340 sid = null; 66341 if (moveTo !== null) { break; } 66342 } 66343 } 66344 66345 if (moveTo !== null && arrStaff) { 66346 //if (hasFA) { ++moveTo; } 66347 GLO.staffResources.splice(moveTo, 0, arrStaff); 66348 } 66349 } 66350 66351 _conRunTotal.getSigninStatus = function(staffid) { //returns: 'in' (currently signed-in), 'out' (currently signed-out), or null (if staff not in GLO.staffResources). 66352 var oj = UserPortal.Calendar.findStaffResource(staffid); 66353 66354 if (UTIL.isEmptyObject(oj)) { 66355 return null; 66356 } else if (UTIL.isDate(oj.signin)) { 66357 return 'in' 66358 } else { 66359 return 'out' 66360 } 66361 } 66362 66363 66364 _conRunTotal.TurnTracker = (function() { //= GLO.RunningTotal.TurnTracker 66365 function _cTurnTracker() { } 66366 66367 _cTurnTracker.displayApptHeader = function(jappt) { 66368 if (UserPortal.isLoading) { return; } 66369 if (UserPortal.Edit.isLoadFromCreate) { return; } 66370 if (!UserPortal.apptIsNow(jappt, 2000)) { return; } 66371 66372 if (jappt.hasClass('simplemodal-container')) { 66373 var jmodal = jappt; 66374 jappt = jappt.find('.shadow'); 66375 } else { 66376 var jmodal = jappt.closest('#simplemodal-container'); 66377 } 66378 66379 //jmodal.find('.hello-bar-appt').remove(); 66380 var arrStaffForSvc = _getNextStaffForServiceArray(jappt); 66381 var isCreateAppt = (jappt.attr('id') === 'ba-CreateAppointment'); 66382 66383 if (arrStaffForSvc.length) { 66384 var htm = _getNextStaffApptHeaderHtm(arrStaffForSvc); 66385 var cssClass = 'hello-bar-turn-tracker-next-staff'; 66386 66387 if (arrStaffForSvc.length > 7 || (isCreateAppt && arrStaffForSvc.length === 1)) { 66388 cssClass += ' hello-bar-narrow-text'; //jmodal.find('.hello-bar-turn-tracker-next-staff').addClass('hello-bar-narrow-text'); 66389 } 66390 66391 if (isCreateAppt) { 66392 UserPortal.Calendar.addHelloBarCreateAppt(jappt, htm, cssClass); 66393 } else { 66394 UserPortal.Calendar.addHelloBarEditAppt(jappt, htm, cssClass); 66395 } 66396 } 66397 } 66398 function _getNextStaffApptHeaderHtm(arrStaffForSvc) { 66399 var htm = '', labelText = 'Turn Tracking Next Staff'; 66400 66401 if (arrStaffForSvc.length > 14) { 66402 labelText = ''; 66403 } else if (arrStaffForSvc.length > 9) { 66404 labelText = 'Next Staff'; 66405 } 66406 66407 for (var i=0; i < arrStaffForSvc.length; i++) { 66408 if (i > 0) { 66409 htm += '<i>•</i>'; 66410 } 66411 66412 var sid = arrStaffForSvc[i].staff_id; 66413 var serviceId = arrStaffForSvc[i].service_id; 66414 66415 var sname = UserPortal.getStaffName(sid);
66416 var rowIndex = arrStaffForSvc[i].row_index_sr; 66417 var title = (rowIndex + 1) + ': ' + sname; 66418 66419 if (!UTIL.isEmpty(serviceId)) { 66420 var svcName = UserPortal.getServiceName(serviceId); 66421 title += ' for ' + svcName; 66422 } 66423 66424 var fnOnClick = 'GLO.RunningTotal.TurnTracker.setStaff(' + rowIndex + ', ' + sid + ')'; 66425 htm += '<b class="turn-tracker-staff" row_index_sr="' + rowIndex + '" staff_id="' + sid + '" onclick="' + fnOnClick + '">' + UTIL.maxString(sname, 12, true) + '</b>'; 66426 } 66427 66428 var btn = '<span id="btnSetTurnTrackerStaff" class="btnAdd"><a onclick="GLO.RunningTotal.TurnTracker.setStaffAll()">Set</a></span>'; 66429 return '<div id="turn-tracker-appt-hello-bar"> <label>' + labelText + '</label>' + htm + btn + '</div>'; 66430 } 66431 function _getNextStaffForServiceArray(jappt) { 66432 var faid = UserPortal.getFirstAvailableStaffId(); 66433 var jsvc = jappt.find('.serviceDD:visible'); 66434 var jstaff = jappt.find('.staffDD:visible'); 66435 var arr = [], ignoreStaffIds = ''; 66436 66437 for (var i=0; i < jstaff.length; i++) { 66438 if (jstaff.eq(i).val() == faid || UTIL.isEmpty(jstaff.eq(i).val())) { 66439 var svcid = jsvc.eq(i).val(); //= this looks off but is ok: above loop is looping thru staff (i.e. service rows), there will be the same number of staff and service drop downs. 66440 var sid = _cTurnTracker.getNextStaff(svcid, ignoreStaffIds); 66441 66442 if (UTIL.isNumber(sid)) { 66443 if (ignoreStaffIds !== '') { 66444 ignoreStaffIds += ','; 66445 } 66446 66447 ignoreStaffIds += sid; 66448 arr.push({ "row_index_sr": i, "staff_id": sid, "service_id": svcid }); 66449 } 66450 } 66451 } 66452 66453 return arr; 66454 } 66455 _cTurnTracker.getNextStaff = function(serviceId, ignoreStaffIds) { 66456 var arr = _cTurnTracker.getStaffOrderArray(serviceId, ignoreStaffIds); 66457 66458 if (arr.length === 0) { 66459 return null; 66460 } else { 66461 return arr[0].id; 66462 } 66463 } 66464 _cTurnTracker.getStaffOrderArray = function(serviceId, ignoreStaffIds) { 66465 var jstaff = $('#calendar table.fc-agenda-days').find('th:not(.run-total-sign-in) .turn-tracker-staff'); 66466 var arr = []; 66467 66468 for (var i=0; i < jstaff.length; i++) { 66469 var js = jstaff.eq(i); 66470 var sid = js.parent().attr('id'); 66471 var turn = $.trim(js.find('.run-total').text().replace('$', '').replace('hr', '').replace('hrs', '').replace('next', '')); 66472 66473 if (UTIL.isNumber(turn) && _sortByTime) { 66474 turn = UTIL.coalesceFloat(turn) * 60; 66475 } 66476 66477 turn = UTIL.coalesceInt(turn, 0); //filter out bonus 66478 66479 //incorporate signin date to turn value 66480 if (js.hasClass('run-total-on-deck')) { 66481 turn += .0001; 66482 } else if (!js.hasClass('run-total-next')) { 66483 turn = UTIL.roundNumber(turn + .0001 + (i + 1) * .0001, 4); 66484 } 66485 66486 arr.push({ "id": sid, "turn": turn }); 66487 } 66488 66489 if (arr.length > 0) { 66490 var arr2 = []; 66491 var staffIdsWhoDoService = _getSignedInStaffArray(serviceId, ignoreStaffIds, arr); 66492 66493 for (var i=0; i < arr.length; i++) { 66494 if (staffIdsWhoDoService.has(arr[i].id)) { 66495 arr2.push(arr[i]); 66496 } 66497 } 66498 66499 arr = arr2; 66500 } 66501 66502 return UTIL.sortArray(arr, "turn"); 66503 } 66504 function _getSignedInStaffArray(serviceId, ignoreStaffIds, arr) { 66505 if (UTIL.isNumber(serviceId)) { 66506 var staffIds = $('#allServiceOptions').find('option[value="' + serviceId + '"]').attr('staff_ids').split(','); 66507 } else { 66508 var staffIds = []; 66509 66510 for (var i = 0; i < arr.length; i++) { 66511 staffIds.push(arr[i].id); 66512 } 66513 } 66514 66515 if (!UTIL.isEmpty(ignoreStaffIds)) { 66516 var ignoreIds = ignoreStaffIds.split(','); 66517 66518 for (var a = staffIds.length -1; a >= 0; a--) { 66519 var sid = staffIds[a]; 66520 66521 for (var i = ignoreIds.length - 1; i >= 0; i--) { 66522 if (sid == ignoreIds[i]) { 66523 staffIds.splice(a, 1); 66524 ignoreIds.splice(i, 1); 66525 break; 66526 } 66527 } 66528 } 66529 } 66530 66531 return staffIds; 66532 } 66533 66534 _cTurnTracker.setStaffOrderHeader = function() { 66535 var arr = _cTurnTracker.getStaffOrderArray(); 66536 var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead'); 66537 66538 for (var i=0; i < arr.length; i++) { 66539 var th = thead.find('th[id="' + arr[i].id + '"]').addClass('has-staff-order');
66540 var title = _getStaffHeaderTitle(arr[i], th, i + 1); 66541 66542 if ($('body').hasClass('cal-very-narrow')) { 66543 var label = (i + 1); 66544 } else { 66545 var label = '#' + (i + 1); 66546 } 66547 66548 var htm = '<b class="run-total-order">' + label + '</b>'; 66549 66550 th.find('.run-total-order').remove(); 66551 th.find('.turn-tracker-staff').attr('title', title); 66552 th.find('.turn-tracker-staff').prepend(htm); 66553 } 66554 } 66555 function _getStaffHeaderTitle(jsonStaff, th, orderNumber) { 66556 title = 'Turn Order #' + orderNumber; 66557 66558 if (_sortByPrice || _sortByTime) { 66559 var val = th.find('.run-total').text(); 66560 66561 if (!UTIL.isEmpty(val)) { 66562 title += '\n' + SA.Resource.ServiceTotalToday + ' (not including client appointment requests): ' + val; 66563 } 66564 } 66565 66566 return title; 66567 } 66568 66569 _cTurnTracker.setStaffAll = function() { 66570 var jappt = UserPortal.getAppt(); 66571 var jturns = $('#turn-tracker-appt-hello-bar .turn-tracker-staff'); 66572 var jstaff = jappt.find('.staffDD'); 66573 var jddLastStaff = null; 66574 66575 for (var i=0; i < jturns.length; i++) { 66576 var rowIndex = jturns.eq(i).attr('row_index_sr'), sid = jturns.eq(i).attr('staff_id'); 66577 jddLastStaff = jstaff.eq(rowIndex).val(sid); 66578 } 66579 66580 if (jddLastStaff) { 66581 jddLastStaff.change(); 66582 } 66583 } 66584 _cTurnTracker.setStaff = function(rowIndex, staffId) { 66585 var jappt = UserPortal.getAppt(); 66586 //var isCreate = (jappt.attr('id') === 'ba-CreateAppointment'); 66587 66588 //var jsvc = jappt.find('.serviceDD').eq(rowIndex); 66589 var jstaff = jappt.find('.staffDD').eq(rowIndex); 66590 66591 jstaff.val(staffId).change(); 66592 } 66593 66594 return _cTurnTracker; 66595 })(); 66596 66597 66598 _conRunTotal.OrderCalendar = (function() { 66599 function _conOrderCalendar() { } 66600 66601 _conOrderCalendar.openPopup = function(th) { 66602 if (GLO.Calendar === undefined && !GLO.Provider.Advanced.canSaveChanges()) { GLO.Provider.Advanced.initReadOnlyCheck(); return; } 66603 66604 if (th) { 66605 var sid = th.attr('id'); 66606 var htmStaffHeader = _getStaffHtmlHeader(sid); 66607 } else { 66608 var htmStaffHeader = ''; 66609 } 66610 66611 var h1 = '<h1 class="friendly-msg2">' + SA.Resource.OrderCalendar + '</h1>'; 66612 var btnClose = '<span class="btnCancel btn" style="float: none; margin-right: 8px; letter-spacing: 1px;"> <a onclick="GLO.RunningTotal.OrderCalendar.close()">' + SA.Resource.Close + '</a> </span>'; 66613 66614 var msg1 = GLO.Provider.Advanced.Help.Calendar.getStaffOrderList('Change order staff displayed on'); 66615 var msg2 = '<p id="pop-calendar-order-list-help">' + SA.Resource.DragStaffNameUpOrDown + '</p>'; 66616 66617 var htm = htmStaffHeader + msg1 + msg2 66618 + '<div id="pop-calendar-order-list" style="margin-top: 2px; margin-bottom: 20px;">' + _staffOrderList() + '</div>' 66619 + '<div id="pop-calendar-order-buttons">' + btnClose + '</div>'; 66620 66621 var css = ' style="text-align: center; letter-spacing: 1px;"'; 66622 var jhtm = $('<div id="pop-calendar-order" style="min-width: 310px;">' + h1 + '<div' + css + '>' + htm + '</div> </div>'); 66623 66624 var ojpop = new GLO.Popup.Custom(jhtm); 66625 var jpop = ojpop.getPopup().addClass('no-persist'); 66626 jpop.find('.pop-buttons').remove(); 66627 66628 $('#pop-calendar-order-list ol').sortable({ 66629 //cancel: ".disable-sort-item", 66630 update: function(event, ui) { 66631 ui.item.attr('updated_fl', 1); 66632 66633 setTimeout(function() { 66634 _displaySaveButton(ui.item); 66635 }, 900); 66636 } 66637 66638 , stop: function (event, ui) { 66639 if (!_isValidStaffSort(event, ui)) { 66640 ui.item.removeAttr('updated_fl'); 66641 $(this).sortable('cancel'); 66642 } 66643 } 66644 66645 //, change: function(event, ui) { } 66646 //, sort: function(event, ui) { } 66647 }); 66648 66649 _setWhoIsNextColors(jpop); 66650 } 66651 66652 function _isValidStaffSort(event, ui) { 66653 if (ui.item.hasClass('is-first-available')) { 66654 var htm = '<div class="friendly-msg3">Cannot Move <b><i>First Available</i></b></div>'; 66655 new GLO.Popup.Warning(htm); 66656 return false; 66657 } else if (ui.item.index() === 0 && ui.item.closest('ol').find('li.is-first-available').length > 0) { 66658 var htm = '<div class="friendly-msg3">Cannot Move Before <b><i>First Available</i></b></div>'; 66659 new GLO.Popup.Warning(htm); 66660 return false; 66661 } 66662 66663 return true; 66664 } 66665 66666 function _setWhoIsNextColors(jpop) { 66667 if (!GLO.isFrontDeskCalendar) { return; } 66668 66669 var thead = $('.fc-view-resourceDay').find('thead'); 66670 var nextSID = thead.find('.run-total-next').attr('id'); 66671 var ondeckSID = thead.find('.run-total-on-deck').attr('id'); 66672 66673 var lis = jpop.find('#pop-calendar-order-list').find('ol > li'); 66674 66675 for (var i=0; i < lis.length; i++) { 66676 var li = lis.eq(i); 66677 var sid = li.attr('staff_id'); 66678 66679 if (nextSID == sid) { 66680 var bgc = thead.find('.run-total-next').css('background-color'); 66681 li.find('a').css({ "background-color": bgc }); 66682 } 66683 66684 if (ondeckSID == sid) { 66685 var bgc = thead.find('.run-total-on-deck').css('background-color'); 66686 li.find('a').css({ "background-color": bgc }); 66687 } 66688 } 66689 } 66690 66691 function _getStaffHtmlHeader(sid) { 66692 if (UTIL.isEmpty(sid)) { return ''; } 66693 66694 var nm = UserPortal.lookupStaffName(sid); 66695 var cleanName = nm.replace(/"/g, '').replace(/'/g, ''); 66696 var signin = UserPortal.Calendar.findStaffResource(sid).signin; 66697 66698 var htmStaffHeader = '<div id="pop-calendar-order-top" style="line-height: 300%; margin-bottom: 20px;">' 66699 + '<div> <a onclick="GLO.RunningTotal.OrderCalendar.gotoCalendar(event, ' + sid + ', \'' + cleanName + '\')">' + SA.Resource.GoTo + ' ' + nm + '\'s + ' + SA.Resource.Calendar + '</a> </div>'; 66700 66701 if (UTIL.isDate(signin)) { 66702 var title = 'Signed-in ' + new Date(signin).toGloTime(); //signin.toSADate(true) 66703 66704 htmStaffHeader += '<div> <span id="btnSignout" class="btn btnAdd">' 66705 + '<a onclick="GLO.RunningTotal.signout(' + sid + ', \'' + cleanName + '\')" title="' + title + '" style="background-color: rgba(255, 120, 0, .9);">Sign Out ' + nm + '</a>' 66706 + '</span> </div>' 66707 } 66708 66709 return htmStaffHeader + '</div>'; 66710 } 66711 66712 function _displaySaveButton(jitem) { 66713 if (!UTIL.parseBool(jitem.attr('updated_fl'))) { 66714 return; 66715 } 66716 66717 var jpop = $('#pop-calendar-order').closest('.glopop'); 66718 var jbtns = jpop.find('#pop-calendar-order-buttons'); 66719 66720 if (jbtns.find('.btnSave:visible').length > 0) { 66721 return; 66722 } 66723 66724 var aSave = '<a onclick="GLO.RunningTotal.OrderCalendar.save()">' + SA.Resource.Save + '</a>'; 66725 var btnSave = '<span class="btn btnSave" style="position: absolute; right: 0; letter-spacing: 1px;">' + aSave + '</span>';
66726 var divSave = '<div style="margin-top: 16px; margin-bottom: 24px;"><span class="btn btnSave">' + aSave + '</span></div>'; 66727 66728 jbtns.css({ "position": "relative", "min-height": "24px", "padding-top": "12px" }).find('.btnCancel').css({ "position": "absolute", "left": "8px" }); 66729 jbtns.append(btnSave); 66730 66731 jpop.find('#staff-order-sort-help').replaceWith(divSave); 66732 } 66733 66734 function _staffOrderList() { 66735 var cnt = 0, htm = '<ol>', signinOnly = false; 66736 66737 if (UTIL.isDate(GLO.staffResources[0].signin)) { signinOnly = true; } 66738 66739 for (var s=0; s < GLO.staffResources.length; s++) { 66740 if (!signinOnly || UTIL.isDate(GLO.staffResources[s].signin)) { 66741 if (UTIL.parseBool(GLO.staffResources[s].is_first_available_fl)) { 66742 cssClass = ' class="is-first-available"'; 66743 } else { 66744 cssClass = ''; 66745 } 66746 66747 var sid = GLO.staffResources[s].id, signin = GLO.staffResources[s].signin, name = GLO.staffResources[s].name; 66748 var title = UTIL.coalesceString(GLO.staffResources[s].title); 66749 66750 htm += '<li' + cssClass + ' staff_id="' + sid + '" signin_dt="' + signin + '" title="' + title + '"> <a>' + name + '</a> </li>'; 66751 ++cnt; 66752 } 66753 } 66754 66755 if (cnt > 1) { 66756 return htm + '</ol>'; 66757 } else { 66758 return ''; 66759 } 66760 } 66761 66762 function _dateToString(dt) { 66763 if (UTIL.isEmpty(dt)) { dt = new Date(); } 66764 return dt.toGloDate() + ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds(); 66765 } 66766 66767 function _reOrderList() { 66768 var order = 100, hasSignin = false, arr = [], dt = new Date(); 66769 var lis = $('#pop-calendar-order-list ol').find('li'); 66770 66771 dt = new Date(dt.setSeconds(dt.getSeconds() - 100)); 66772 66773 if (UTIL.isDate(GLO.staffResources[0].signin)) { hasSignin = true; } 66774 var htm = '<ol is_signin_fl="' + hasSignin + '">'; 66775 66776 for (var i=0; i < lis.length; i++) { 66777 var sid = lis.eq(i).attr('staff_id'); 66778 var oj = UserPortal.Calendar.findStaffResource(sid); 66779 66780 dt = new Date(dt.setSeconds(dt.getSeconds() + 1)); 66781 htm += '<li staff_id="' + sid + '" signin_dt="' + _dateToString(dt) + '" order_sr="' + (++order) + '"/>'; 66782 66783 arr.push(oj); 66784 } 66785 66786 if (hasSignin) { 66787 for (var s=0; s < GLO.staffResources.length; s++) { 66788 if (!UTIL.isDate(GLO.staffResources[s].signin)) { 66789 arr.push(GLO.staffResources[s]); 66790 } 66791 } 66792 } 66793 66794 GLO.staffResources = arr; 66795 return htm + '</ol>'; 66796 } 66797 66798 _conOrderCalendar.gotoCalendar = function(ev, staffid, staffName) { 66799 url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=' + staffid; 66800 66801 var dt = GLO.Uri.url('dt'); 66802 if (!UTIL.isEmpty(dt)) { url += '&dt=' + dt; } 66803 66804 _conOrderCalendar.close(); 66805 66806 if (ev && ev.ctrlKey) { 66807 window.open(url); 66808 } else { 66809 UI.displayProcessingLayer(); 66810 setTimeout(function() { document.location = url; }, 200); 66811 } 66812 } 66813 66814 _conOrderCalendar.close = function() { 66815 var jpop = $('#pop-calendar-order').closest('.glopop'); 66816 GLO.Popup.close(jpop); 66817 } 66818 66819 _conOrderCalendar.save = function() { 66820 var ol = UTIL.htmlEncode(_reOrderList()); 66821 _reorderCalendar(); 66822 66823 var uri = GLO.Link.WebsiteDomain + 'schedule/OrderCalendar'; 66824 var jpop = $('#pop-calendar-order').closest('.glopop'); 66825 var jbtn = jpop.find('.btnSave'); 66826 66827 GLO.UI.Form.beginProcessing(jbtn); 66828 66829 var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "ol": ol } }) 66830 .success(function(data, textStatus, jqXHR) { 66831 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66832 GLO.Popup.close(jpop); 66833 66834 if (GLO.isPOS) { 66835 GLO.Popup.Success.open('New Staff Order Saved<br/><br/>Loading Changes....', 'Staff Sort Order'); 66836 66837 setTimeout(function() { 66838 location.reload(); 66839 }, 100); 66840 } 66841 }) 66842 .error(function(jqXHR, textStatus, errorThrown) { 66843 GLO.UI.Form.resetProcessing(); //UI.removeProcessingLayer(); 66844 //new GLO.Popup.Error('Unable to order the calendars staff'); 66845 }); 66846 } 66847 66848 return _conOrderCalendar; 66849 })(); 66850 66851 return _conRunTotal; 66852})(); 66853 66854 66855 66856$(function() { 66857 var url = document.location.pathname; 66858 66859 if (url.indexOf('/provider/profile') !== -1) { 66860 $('#hd-profile-menu-text').addClass('selectedLink'); 66861 } else if (url.indexOf('/provider/inventory') !== -1) { 66862 $('#hd-product-menu-text').addClass('selectedLink'); 66863 } else if (url.indexOf('/provider/calendar') !== -1 || url.indexOf('/provider/reminders') !== -1 || url.indexOf('/provider/apptportal') !== -1) { 66864 $('#hd-schedule-menu-text').addClass('selectedLink'); 66865 } else if (url.indexOf('/reports/') !== -1) { 66866 $('#hd-reports-menu-text').addClass('selectedLink'); 66867 } 66868
66869 SA.Menu.init(); 66870 Search.init('#easySearch_text', GLO.Link.Object.Provider.UserSearch + '?include-inventory=1'); 66871 $('#runSearch').click(Search.run); 66872 66873 $('#top-searchBox').bind('keydown', function(e) { 66874 if (e.which === 13) { // ENTER 66875 if (!Search.inProgress) { 66876 Search.run(); e.preventDefault(); 66877 } 66878 } 66879 }); 66880 66881 var jPageHeader = $('#search-bar'); 66882 jPageHeader.find('#staff-filter, #easySearch_text').focus(function() { 66883 var simpleModal = $('#simplemodal-container'); 66884 var glopop = $('.glopop:visible'); 66885 var element; 66886 66887 if (glopop.size() > 0) { //set focus on first element in simple modal. 66888 element = glopop.eq(0).find('input, select, textarea, button'); 66889 if (element.size() > 0) { element.eq(0).focus(); } 66890 } else if (simpleModal.css('display') !== undefined) { //set focus on first element in simple modal. 66891 element = simpleModal.find('input, select, textarea, button'); 66892 if (element.size() > 0) { element.eq(0).focus(); } 66893 } 66894 }); 66895 66896 GLO.Staff.Filter.initOnPageLoad(); 66897 SA.Kiosk.init(); 66898});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.