Kenji776

hostapp

Aug 16th, 2012
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <apex:page sidebar="false" showHeader="false" standardStylesheets="false">
  2.     <head>
  3.    
  4.     <!--- Stylesheets--->
  5.     <link type="text/css" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/themes/flick/jquery-ui.css" />
  6.     <link type="text/css" rel="stylesheet" href="{!URLFOR($Resource.tableSorter, '/css/ui/style.css')}" />
  7.     <!---- jQuery libraries --->
  8.     <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" />
  9.     <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js" />
  10.  
  11.     <!---- Apex connection Libraries --->
  12.     <script src="/soap/ajax/25.0/connection.js" type="text/javascript"></script>
  13.     <script src="/soap/ajax/15.0/apex.js" type="text/javascript"></script>
  14.     <script src="../static/102010/js/picklist.js"></script>
  15.    
  16.     <!--- table sorter libraries --->
  17.     <script src="{!URLFOR($Resource.tableSorter, '/js/jquery.tablesorter.min.js')}"></script>
  18.     <script src="{!URLFOR($Resource.tableSorter, '/js/jquery.tablesorter.widgets.min.js')}"></script>
  19.  
  20.   <!--- theme switcher--->
  21.      
  22.     <style>
  23.         body
  24.         {
  25.             font-size:11px;
  26.         }
  27.         #container
  28.         {
  29.             min-height:500px;
  30.         }
  31.         #toolbar
  32.         {
  33.             padding:5px;
  34.         }
  35.  
  36.         #respondent_attributes li
  37.         {
  38.             list-style-type:none;
  39.         }        
  40.         #log
  41.         {
  42.             margin:15px;
  43.             font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
  44.             color: #000000;
  45.             background-color: #eee;
  46.             font-size: 12px;
  47.             border: 1px dashed #999999;
  48.             line-height: 14px;
  49.             padding: 5px;
  50.             height:300px;        
  51.             overflow: auto;
  52.            
  53.         }
  54.         #bulkChangeProgressBar
  55.         {
  56.             height:15px;
  57.             float:left;
  58.             width:75%;
  59.             display:none;
  60.         }
  61.         #bulkChangeProgressVal
  62.         {
  63.             float:right;
  64.             text-align:right;
  65.             font-weight:bold;
  66.             width:15%;
  67.             padding-right:5px;
  68.             display:none;
  69.         }
  70.         #switcher { display: inline-block; padding-bottom: 5px; margin-right:25px; float:right; }
  71.        
  72.     </style>
  73.     <script type="text/javascript">
  74.         setInterval("checkOnline()",500);
  75.         var totals = new Object();
  76.         var campaigns = new Object();
  77.         var payments = new Object();
  78.         var respondentNumbers = new Object();
  79.         var codes = new Object();
  80.  
  81.         var lastRespNum  = -1;
  82.         var lastStatus = 'NA';
  83.         var offlineCount = 0;
  84.         var lastContact;
  85.         var lastPayment;
  86.         var reportId;
  87.        
  88.         var statusListValues = '';
  89.         sforce.connection.sessionId = '{!$Api.Session_ID}';
  90.        
  91.         var describeResults = sforce.connection.describeSObject('payments__c'); // the object we want picklists from
  92.  
  93.         $(document).ready(function()
  94.         {
  95.             writeLogEntry('Initializing Interface');
  96.             //prevent accidental window closing
  97.             $(window).bind('beforeunload', function(){
  98.                 //return 'Are you sure you wish to leave this page?';
  99.             });
  100.            
  101.             //get status__c picklist values
  102.             var statusList = getPicklistValues('Status__c').values;
  103.            
  104.             setPickVals('#bulkChangeFrom',statusList);
  105.             setPickVals('#bulkChangeTo',statusList);
  106.             for(var i = 0; i < statusList.length; i++)
  107.             {
  108.                 statusListValues += '<option value="'+statusList[i].value+'">'+statusList[i].label+'</option>';
  109.             }
  110.            
  111.              
  112.              $('#saveDQRow').click(function(){
  113.                     var saveResult = evalRespondentRecord($('.statusList[contact='+lastContact+']').val(), lastContact,lastPayment,false);
  114.                    
  115.                     if(!saveResult.success)
  116.                     {
  117.                         $('#dqSaveResult').html(saveResult.message);
  118.                         $(this).val(lastStatus);
  119.                     }  
  120.                     else
  121.                     {
  122.                         $('#selectDQReason').dialog('close');
  123.                     }
  124.                  
  125.              });
  126.                          
  127.              $('#cancelDQRow').click(function(){
  128.                  $('#selectDQReason').dialog('close');
  129.              });
  130.              
  131.              $('#bulkStatusChangeButton').click(function(){
  132.                  $('#bulkStatusChange').dialog('open');
  133.              });
  134.              $('#bulkStatusChangeSubmit').click(function(){
  135.                   $('#bulkStatusChangeSubmit').button("disable");
  136.                   $('#bulkChangeProgressVal').show();
  137.                   $('#bulkChangeProgressBar').show();
  138.                  
  139.                  var startVal = $('#bulkChangeFrom').val();
  140.                  var endVal = $('#bulkChangeTo').val();
  141.                  var totalToSave = 0;
  142.                  var completed = 0;
  143.                  $('.statusList').each(function(){
  144.                      if($(this).val() == startVal)
  145.                      {
  146.                          totalToSave++;
  147.                      }
  148.                  });
  149.                                  
  150.                  $('.statusList').each(function(i){
  151.                       var selectItem = $(this);
  152.                       if($(this).val() == startVal)
  153.                       {
  154.                             lastStatus = startVal;
  155.                             setTimeout((function(i,selectItem) {
  156.                                 return function() {
  157.                                     $(selectItem).val(endVal).trigger("focus").trigger("change");
  158.                                      completed++;
  159.                                      var percent = Math.round(completed/totalToSave*100);
  160.                                       $('#bulkChangeProgressVal').html(percent +'%');
  161.                                       $('#bulkChangeProgressBar' ).progressbar( "value" , percent);
  162.                                       if(percent == 100)
  163.                                       {
  164.                                           $('#bulkChangeProgressVal').html('0%');
  165.                                           $('#bulkChangeProgressBar' ).progressbar( "value" , 0);      
  166.                                           $('#bulkChangeProgressVal').hide();
  167.                                           $('#bulkChangeProgressBar').hide();      
  168.                                           $('#bulkStatusChangeSubmit').button("enable");
  169.                                           $('#bulkStatusChange').dialog('close');                                                                
  170.                                       }
  171.                                 }
  172.                             })(i,selectItem), 200*i);  
  173.                       }                  
  174.                  });
  175.  
  176.                  return false;
  177.              });  
  178.  
  179.             $( "#bulkChangeProgressBar" ).progressbar({
  180.                 value: 0
  181.             });
  182.                                
  183.             // Theme switcher
  184.             //$('#switcher').themeswitcher({loadTheme: 'Smoothness'} );
  185.                    
  186.             //register dialog boxes
  187.             $('.dialog').dialog({
  188.                 autoOpen: false,
  189.                 modal: true
  190.             });
  191.  
  192.             $('#clearLog').click(function(){
  193.                 $('#log').html(null);
  194.             });
  195.            
  196.             $(':button[value="Cancel"]').click(function(){
  197.                 $($(this).parent().parent()).dialog('close');
  198.             });
  199.            
  200.             //register the attribute update button
  201.             $('#updateAttributes').click(function(event,ui){
  202.                 writeLogEntry('Updating respondent attributes');
  203.                 var paymentId =  $('#updateAttributePaymentId').val();
  204.                                              
  205.                 var respondentsToUpdate = new Array();
  206.                 var thisRespondent = new sforce.SObject("Respondent__c");
  207.                 thisRespondent.Id = payments[paymentId].RespondentRecord__r.Id;
  208.                            
  209.                 $('.attrib_box').each(function(index){
  210.                     if($(this).attr('checked'))
  211.                     {
  212.                         thisRespondent['Attribute_'+parseInt(index+1,10)+'_Met__c'] = true;
  213.                     }
  214.                     else
  215.                     {
  216.                         thisRespondent['Attribute_'+parseInt(index+1,10)+'_Met__c'] = false;
  217.                     }                  
  218.                 });        
  219.                 respondentsToUpdate.push(thisRespondent);
  220.                 result = saveObject(respondentsToUpdate);
  221.              
  222.                 writeLogEntry('Respondent update success: ' + result[0].success);
  223.                 if(result[0].success == 'true')
  224.                 {
  225.                     $('#updateAttributeStatus').html(null);
  226.                    
  227.                     $('.attrib_box').each(function(index){
  228.                         if($(this).attr('checked'))
  229.                         {
  230.                             payments[paymentId].RespondentRecord__r['Attribute_'+parseInt(index+1,10)+'_Met__c'] = 'true';
  231.                         }
  232.                         else
  233.                         {
  234.                             payments[paymentId].RespondentRecord__r['Attribute_'+parseInt(index+1,10)+'_Met__c'] = 'false';
  235.                         }                  
  236.                     });  
  237.                     $( "#attributes" ).dialog('close');                                
  238.                 }
  239.                 else
  240.                 {
  241.                     $('#updateAttributeStatus').html('Error updating respondent: ' + result.message);
  242.                 }
  243.                        
  244.             });
  245.            
  246.             $('#assignCheckButton').click(function(){
  247.  
  248.                 if(!$.isNumeric($('#checkNumber').val()))
  249.                 {
  250.                     $('#updateCheckStatus').html('Please enter a valid check number');
  251.                     return false;
  252.                 }
  253.                
  254.                 runQuery("select id,name, payment__c, payment__r.name from check__c where name = '"+$('#checkNumber').val()+"'",function(data){
  255.                         console.log(data);    
  256.                         if(data.records.length == 0)
  257.                         {
  258.                              $('#updateCheckStatus').html('No check with that number could be found. Please double check the number and try again.');
  259.                              return false;
  260.                         }
  261.                         if(data.records[0].Payment__c != null)
  262.                         {
  263.                              $('#updateCheckStatus').html('Check has already been assigned to payment ' +data.records[0].Payment__r.Name );
  264.                              return false;                            
  265.                         }
  266.                         reportId = data.records[0].Id;
  267.                         var payment = new Object();
  268.                         payment.id = $('#updateCheckPaymentId').val();
  269.                         payment.check__c = data.records[0].Id;
  270.                         saveResult = savePayment(payment);
  271.                        
  272.                         if(!saveResult.success)
  273.                         {
  274.                             $('#updateCheckStatus').html(saveResult.message.message);
  275.                         }
  276.                         else
  277.                         {
  278.                             $('#updateCheckStatus').html('Update successfull!');
  279.                            
  280.                             $('.check[check="'+data.records[0].Id+'"]').each(function(){$(this).html(null)});
  281.                             $('.check[check="'+data.records[0].Id+'"]').each(function(){$(this).attr('check',null)});
  282.                            
  283.                             $('.check[payment="'+$("#updateCheckPaymentId").val()+'"]').each(function(){$(this).html(data.records[0].Name)});
  284.                             $('.check[payment="'+$("#updateCheckPaymentId").val()+'"]').each(function(){$(this).attr('check',data.records[0].Id)});
  285.                             $('#assignCheck').dialog('close');
  286.                         }  
  287.                     });          
  288.             });
  289.            
  290.             $('#container').tabs();
  291.             $('#tabs').hide();
  292.              $('input[type=checkbox]').button();
  293.             $('.button').button();
  294.             $('#reportLink').button('disable');
  295.  
  296.             $('#useRotation').click(function(){
  297.                 if($(this).is(':checked'))
  298.                 {
  299.                     writeLogEntry('Enabling rotation assigner');
  300.                     $('.respondentNumber').attr("disabled","disabled");
  301.                     //$('#tabs li:nth-child(2)').show().next().show();
  302.                 }
  303.                 else
  304.                 {
  305.                     writeLogEntry('Disabling rotation assigner');
  306.                     $('.respondentNumber').removeAttr("disabled");
  307.                     //$('#tabs li:nth-child(2)').hide().next().hide();
  308.                 }
  309.             });
  310.             $( "input[type=checkbox]" ).button({ icons: {primary:'ui-icon-circle-close'} }).click(function(){
  311.                     if($(this).is(':checked'))
  312.                     {
  313.                         $(this).next().children('.ui-button-icon-primary').addClass("ui-icon-circle-check").removeClass("ui-icon-circle-close");
  314.                     }
  315.                     else
  316.                     {
  317.                         $(this).next().children('.ui-button-icon-primary').addClass("ui-icon-circle-close").removeClass("ui-icon-circle-check");
  318.                     }
  319.             }).each(function(){
  320.                     if($(this).is(':checked'))
  321.                     {
  322.                         $(this).next().children('.ui-button-icon-primary').addClass("ui-icon-circle-check").removeClass("ui-icon-circle-close");
  323.                     }
  324.                     else
  325.                     {
  326.                         $(this).next().children('.ui-button-icon-primary').addClass("ui-icon-circle-close").removeClass("ui-icon-circle-check");
  327.                     }            
  328.             });
  329.                                          
  330.            //get master campaign list when the umbrella campaign changes.
  331.            $('#umbrellacampaigns').change(function(){
  332.                 if($(this).val() == '--Select One--')
  333.                 {
  334.                     return false;
  335.                 }  
  336.                writeLogEntry('Umbrella campaign changed to ' + $(this).val());
  337.                getMasterCampaignList($(this).val());
  338.                setLink($(this+':selected').text());
  339.                $('.reportLink').button('enable');
  340.  
  341.             });  
  342.            
  343.             $('#clearButton').click(function(){
  344.                 $('#filter-box').val(null);
  345.                 $("#checkInTableGrid tr:hidden").show();
  346.                 $('#filter-box').focus();
  347.             });
  348.  
  349.             $("#lostConnection").dialog({
  350.                closeOnEscape: false,
  351.                modal: true,
  352.                autoOpen: false,
  353.                open: function(event, ui) { $(".ui-dialog-titlebar-close", ui.dialog || ui).hide(); }
  354.             }).parent().addClass("ui-state-error");
  355.            
  356.             $('#cancelUpdateAttributes').click(function(){
  357.                 $('#attributes').dialog('close');
  358.             });
  359.            
  360.             //when a master campaign is chosen, parse the CSV content, serve scores, etc.
  361.             $('#mastercampaigns').change(function(){
  362.                 writeLogEntry('Master campaign changed to ' + $(this).val());
  363.                 $('#bulkStatusChangeButton').button('enable');
  364.                 if($(this).val() == '--Select One--')
  365.                 {
  366.                     return false;
  367.                 }      
  368.                 $('#tabs').show();
  369.                 //$('#tabs li:nth-child(2)').hide().next().hide();
  370.                
  371.                 if(campaigns[$(this).val()].Serve_Rotation__c != null)
  372.                 {
  373.                     try
  374.                     {
  375.                         var parseServe = parseCSV(campaigns[$(this).val()].Serve_Rotation__c);  
  376.                         var calcScores= calculateServeScores();
  377.                        
  378.                        
  379.                         if(parseServe.success && calcScores.success)
  380.                         {
  381.                             $('#useRotation').button("enable");  
  382.                         }
  383.                         else
  384.                         {
  385.                             $('#useRotation').attr("checked","false");
  386.                             $('#useRotation').hide();
  387.                             showAlert('Test has a rotation defined, but it is invalid. Please ensure the rotation is in the expected format and try again');
  388.                         }
  389.                     }
  390.                     catch(ex)
  391.                     {
  392.                    
  393.                     }      
  394.                            
  395.                 }
  396.                 getRespondentList($(this).val());
  397.                
  398.                $('#progressTrackerFrame').attr('src', '/apex/studyprogresstrackersimple?core.apexpages.devmode.url=0&campaignid='+$(this).val());
  399.                
  400.                 writeLogEntry('Master campaign data load complete');
  401.             }).attr("disabled", true);
  402.  
  403.          
  404.             //get the list of umbrella campaigns.
  405.            getUmbrellaCampaignList();
  406.  
  407.         });      
  408.    
  409.         //set all the checked attributes for a given payment
  410.         function setCheckedAttributes(paymentId)
  411.         {
  412.            writeLogEntry('Finding all attributes for payment' + paymentId);
  413.             var returnObj = new returnObject();
  414.             try
  415.             {        
  416.                 $('#updateAttributePaymentId').val(paymentId);
  417.                 $( "#attributes" ).dialog('option', 'title', 'Attributes for ' + payments[paymentId].Contact__r.Name);
  418.                 $('.attrib_box').each(function(index){
  419.                     if(payments[paymentId]['RespondentRecord__r']['Attribute_'+parseInt(index+1,10)+'_Met__c'] == 'true')
  420.                     {
  421.                         $(this).attr('checked',true);
  422.                     }
  423.                     else
  424.                     {
  425.                         $(this).removeAttr("checked")
  426.                     }                
  427.                 });
  428.             }
  429.             catch(exception)
  430.             {
  431.                 returnObj.success = false;
  432.                 returnObj.message = exception;showAlert(exception.message);
  433.             }
  434.             writeLogEntry('Finding all attributes for payment' + paymentId + ' complete');
  435.             return  returnObj;                
  436.         }
  437.         // function to get the picklist values of a field. Finds all potential options. Simple pass it in a field id. Will return object with data in the values key.
  438.         function getPicklistValues(field)
  439.         {
  440.             //create return object
  441.             var returnObj = new returnObject();
  442.            
  443.             try
  444.             {
  445.                 var validField = false;
  446.                 for(var i = 0; i < describeResults.fields.length; i++)
  447.                 {
  448.                     var fieldList = describeResults.fields[i];
  449.                     var fieldName = fieldList.name;
  450.              
  451.                     if(fieldName.toLowerCase() == field.toLowerCase())
  452.                     {
  453.                         validField = true;
  454.                         for(var j = 0; j < fieldList.picklistValues.length; j++)
  455.                         {
  456.                            
  457.                             var newValue = new Object();
  458.                             newValue.label = fieldList.picklistValues[j].label;
  459.                             newValue.value = fieldList.picklistValues[j].value;
  460.                             newValue.default = fieldList.picklistValues[j].defaultValue;
  461.                             if(fieldList.picklistValues[j].hasOwnProperty('validFor'))
  462.                             {
  463.                                 newValue.validFor = fieldList.picklistValues[j].validFor;
  464.                             }
  465.                             returnObj.values.push(newValue);
  466.                         }
  467.                         break;
  468.                     }
  469.                 }
  470.                 if(!validField)
  471.                 {
  472.                     throw 'Invalid field '+field+' specified for object ' + params.object;
  473.                 }
  474.             }
  475.             catch(exception)
  476.             {
  477.                 returnObj.message = exception;showAlert(exception.message);
  478.                 returnObj.success = false;
  479.             }        
  480.            
  481.             return returnObj;
  482.         }
  483.  
  484.         function setPickVals(field,optionsArray)
  485.         {
  486.                 var options = '';
  487.                  for(var i = 0; i < optionsArray.length; i++)
  488.                  {
  489.                      options += '<option value="'+optionsArray[i].value+'">'+optionsArray[i].label+'</option>';
  490.                  }        
  491.                  $(field).html(options);
  492.         }
  493.        
  494.         function getDependentValues(field, value)
  495.         {
  496.             var returnObj = new returnObject();
  497.             try
  498.             {    
  499.                 var dependencyCode = new Array();          
  500.                 var getValues = getPicklistValues(field);        
  501.                 if(!getValues.success)
  502.                 {
  503.                     throw getValues.message;
  504.                 }
  505.                 var picklistValues =  getValues.values;
  506.                 var getController = getControllerName(field);
  507.                        
  508.                 if(!getController.success)
  509.                 {
  510.                     throw getController.message;
  511.                 }              
  512.                 var controller = getController.values;
  513.                    
  514.                 // sub function to do the validFor test
  515.                 function isDependentValue(index, validFor)
  516.                 {
  517.                     var base64 = new sforce.Base64Binary("");
  518.                     var decoded = base64.decode(validFor);
  519.                     var bits = decoded.charCodeAt(index>>3);
  520.                    
  521.                     return ((bits & (0x80 >> (index%8))) != 0);
  522.                 }
  523.                 var controllerFields =getPicklistValues(controller);
  524.                      
  525.                 for(var item = 0; item < controllerFields.values.length; item++)
  526.                 {
  527.                     if(controllerFields.values[item].value.toLowerCase() == value.toLowerCase())
  528.                      {
  529.                         for(var i = 0; i < picklistValues.length; i++)
  530.                         {
  531.                             if(isDependentValue(item, picklistValues[i].validFor))
  532.                             {
  533.                                 var newValue = new Object();
  534.                                 newValue.label = picklistValues[i].label;
  535.                                 newValue.value = picklistValues[i].value;
  536.                                 newValue.default = picklistValues[i].defaultValue;
  537.                                 newValue.validFor = picklistValues[i].validFor;
  538.                                 newValue.validForName =controllerFields.values[item].value;
  539.                                 returnObj.values.push(newValue);                                                              
  540.                             }
  541.                         }
  542.                     }
  543.                 }
  544.             }
  545.        
  546.             catch(exception)
  547.             {
  548.                 returnObj.success = false;
  549.                 returnObj.message = exception;showAlert(exception.message);
  550.             }
  551.             return returnObj;        
  552.         }
  553.        
  554.        
  555.         // get the controller field name
  556.         function getControllerName(field)
  557.         {
  558.             var returnObj = new returnObject();
  559.            
  560.             try
  561.             {
  562.                 var isValid = false;
  563.                
  564.                 for(var i = 0; i < describeResults.fields.length; i++)
  565.                 {
  566.                     var fieldList = describeResults.fields[i];
  567.                     var fieldName = fieldList.name;
  568.            
  569.                     if(fieldName.toLowerCase() == field.toLowerCase())
  570.                     {
  571.                         if(fieldList.controllerName == undefined)
  572.                         {
  573.                             throw 'Field has no controller';
  574.                         }
  575.                         else
  576.                         {
  577.                             returnObj.values = fieldList.controllerName;
  578.                             isValid = true;
  579.                         }
  580.                         break;
  581.                     }
  582.                 }
  583.                
  584.                 if(!isValid)
  585.                 {
  586.                     throw 'Invalid field '+field+' specified';
  587.                 }
  588.             }
  589.             catch(exception)
  590.             {
  591.                 returnObj.success = false;
  592.                 returnObj.message = exception;showAlert(exception.message);
  593.             }
  594.             return  returnObj;
  595.         }
  596.        
  597.         function returnObject()
  598.         {
  599.             this.success = true;
  600.             this.message = 'Operation Ran Successfully';
  601.             this.values = new Array();
  602.         }
  603.        
  604.         function getUmbrellaCampaignList()
  605.         {
  606.             writeLogEntry('Getting umbrella campaigns');
  607.             var returnObj = new returnObject();
  608.             try
  609.             {              
  610.                 $('#umbrellacampaigns').empty();
  611.                 $('#umbrellacampaigns').append($('<option value="--Select One--">', { value :null }) .text('--Select One--'));
  612.    
  613.                 var selectList = '';
  614.    
  615.                 var queryString = "Select name, id from campaign where isActive = true and recordType.Name = 'FPI Umbrella Campaign' ";
  616.                
  617.                
  618.                 runQuery(queryString,function(data){
  619.        
  620.                     for(var i = 0; i < data.records.length; i++)
  621.                     {
  622.                         $('#umbrellacampaigns').append($('<option>', { value : data.records[i].Id }).text(data.records[i].Name));
  623.                     }        
  624.                 });  
  625.             }
  626.             catch(exception)
  627.             {
  628.                 returnObj.success = false;
  629.                 returnObj.message = exception;showAlert(exception.message);
  630.             }
  631.             writeLogEntry('Getting umbrella campaigns complete');
  632.             return  returnObj;                                                
  633.         }  
  634.        
  635.         function getMasterCampaignList(umbrellaCampaignId)
  636.         {
  637.             writeLogEntry('Getting master campaigns for umbrella ' +  umbrellaCampaignId);
  638.             var returnObj = new returnObject();
  639.             try
  640.             {        
  641.                 $('#mastercampaigns').empty();
  642.                 $('#mastercampaigns').append($('<option value="--Select One--">', { value :null }) .text('--Select One--'));
  643.    
  644.                 var selectList = '';
  645.                 for(i = 1; i < 16; i++)
  646.                 {
  647.                     selectList += 'Attribute_'+i+'__c,Attribute_'+i+'_Description__c,';
  648.                 }
  649.                 var queryString = "Select "+selectList+" name, id, serve_rotation__c from campaign where isActive = true and recordType.Name = 'FPI Parent Campaign' and parentId = '"+umbrellaCampaignId+"'";
  650.                
  651.                
  652.                 runQuery(queryString,function(data){
  653.    
  654.                     if(data.records.length == 0)
  655.                     {
  656.                         $('#mastercampaigns').attr("disabled", true);
  657.                     }
  658.                     else
  659.                     {
  660.                         $('#mastercampaigns').removeAttr("disabled");
  661.                     }  
  662.                                
  663.                     for(var i = 0; i < data.records.length; i++)
  664.                     {
  665.                         campaigns[data.records[i].Id] = data.records[i];
  666.                         campaigns[data.records[i].Id]['attributes'] = new Array();
  667.                         for(j = 1; j < 16; j++)
  668.                         {
  669.                             if(data.records[i]['Attribute_'+j+'__c'] == null)
  670.                             {
  671.                                 break;
  672.                             }
  673.                             campaigns[data.records[i].Id]['attributes'][j] =  data.records[i]['Attribute_'+j+'__c'];
  674.                         }
  675.                         $('#mastercampaigns').append($('<option>', { value : data.records[i].Id }).text(data.records[i].Name));
  676.                     }    
  677.                                              
  678.                 });                                  
  679.             }
  680.             catch(exception)
  681.             {
  682.                 returnObj.success = false;
  683.                 returnObj.message = exception;showAlert(exception.message);
  684.             }
  685.             writeLogEntry('Getting master campaigns for umbrella ' +  umbrellaCampaignId + ' complete');
  686.             return  returnObj;          
  687.         }    
  688.  
  689.         function tableSortify(tableId)
  690.         {
  691.             writeLogEntry('Adding table sort logic to table ' + tableId );
  692.             var returnObj = new returnObject();
  693.             try
  694.             {
  695.                 $(tableId).tablesorter({
  696.                     widthFixed: true,
  697.            
  698.                     // widget code now contained in the jquery.tablesorter.widgets.js file
  699.                     widgets : ['uitheme', 'zebra'],
  700.            
  701.                     widgetOptions : {
  702.                         // adding zebra striping, using content and default styles - the ui css removes the background from default
  703.                         // even and odd class names included for this demo to allow switching themes
  704.                         zebra   : ["ui-widget-content even", "ui-state-default odd"],
  705.            
  706.                         // change default uitheme icons - find the full list of icons here: http://jqueryui.com/themeroller/ (hover over them for their name)
  707.                         // default icons: ["ui-icon-arrowthick-2-n-s", "ui-icon-arrowthick-1-s", "ui-icon-arrowthick-1-n"]
  708.                         // ["up/down arrow (cssHeaders/unsorted)", "down arrow (cssDesc/descending)", "up arrow (cssAsc/ascending)" ]
  709.                         uitheme : ["ui-icon-carat-2-n-s", "ui-icon-carat-1-s", "ui-icon-carat-1-n"]
  710.                     }
  711.                 })    
  712.             }
  713.             catch(exception)
  714.             {
  715.                 returnObj.success = false;
  716.                 returnObj.message = exception;showAlert(exception.message);
  717.             }
  718.             writeLogEntry('Adding table sort logic to table ' + tableId + ' complete' );
  719.             return  returnObj;        
  720.         }
  721.        
  722.         function getRespondentList(campaignId)
  723.         {
  724.             writeLogEntry('Getting respondents for campaign ' + campaignId );
  725.             var returnObj = new returnObject();
  726.             try
  727.             {        
  728.                 var selectList = '';
  729.                 for(i = 1; i < 16; i++)
  730.                 {
  731.                     selectList += 'RespondentRecord__r.Attribute_'+i+'_Met__c,';
  732.                 }
  733.                 var queryString = "Select "+selectList+" name, Contact__c, Contact__r.name, Contact__r.Firstname, Contact__r.Lastname, Contact__r.Gender__c, Contact__r.Age__c, Contact__r.Id, Contact__r.pid__c, Respondent_Number__c, Status__c, RespondentRecord__r.Child_Campaign__r.Time_Slot__c, Organization__r.Name, check__c, check__r.Name, RespondentRecord__r.Id, id from payments__c where Parent_Study__c = '"+campaignId+"'";
  734.                
  735.                
  736.                 runQuery(queryString,function(data){    
  737.                     for(var i = 0; i < data.records.length; i++)
  738.                     {
  739.                         payments[data.records[i].Id] = data.records[i];
  740.                        
  741.                         var respNo = parseInt(Math.round(data.records[i].Respondent_Number__c),10);
  742.                         if(respNo > 0 && respNo != null)
  743.                         {
  744.                             if(!respondentNumbers.hasOwnProperty(respNo))
  745.                             {
  746.                                 respondentNumbers[respNo] = new Object();
  747.                             }
  748.                             respondentNumbers[respNo]['available'] = false;
  749.                             $('#pid_'+respNo).html(data.records[i].Contact__r.Name);
  750.                         }
  751.                     }        
  752.                    
  753.                     //Draw the actual table on the screen for the user
  754.                     drawCheckIntable(data);
  755.                    
  756.                     //apply the filtering as you type code
  757.                      $("#filter-box").keyup(function(){
  758.                        var s = $(this).val().toLowerCase().split(" ");
  759.                        $("#checkInTableGrid tr:hidden").show();
  760.                        $.each(s, function(){
  761.                            $("#checkInTableGrid tr:visible .indexColumn:not(:contains('"
  762.                               + this + "'))").parent().hide();
  763.                        });
  764.                      });
  765.              
  766.                      $("#checkInTableGrid tr:has(td)").each(function(){
  767.                        var t = $(this).text().toLowerCase(); //all row text
  768.                        $("<td class='indexColumn'></td>")
  769.                         .hide().text(t).appendTo(this);
  770.                      });//each tr      
  771.                      calculateServeScores();
  772.                      drawTotalsTable();      
  773.                 });              
  774.             }
  775.             catch(exception)
  776.             {
  777.                 returnObj.success = false;
  778.                 returnObj.message = exception;showAlert(exception.message);
  779.             }
  780.             writeLogEntry('Getting respondents for campaign ' + campaignId + ' complete' );
  781.             return  returnObj;                                      
  782.         }
  783.  
  784.         function drawCheckIntable(paymentList)
  785.         {
  786.             writeLogEntry('Creating check in table using respondent data');
  787.             var returnObj = new returnObject();
  788.             var org = '';
  789.             var check = '';
  790.             try
  791.             {        
  792.                 var html = '<table id="checkInTableGrid" class="tablesorter">';
  793.                 html +='<thead><tr><th width="75">Action</th><th width="75">Resp No</th><th>Session</th><th>Firstname</th><th>Lastname</th><th>PID</th><th>Gender</th><th>Age</th><th>Org</th><th>Check</th><th>Details</th></thead><tbody>';
  794.                
  795.                 for(var i = 0; i<paymentList.records.length;i++)
  796.                 {    
  797.                     org = '';
  798.                     check = '';
  799.                     checkId = '';
  800.                     if(paymentList.records[i].Organization__r != null)
  801.                     {
  802.                         org = paymentList.records[i].Organization__r.Name;
  803.                     }
  804.                     if(paymentList.records[i].Check__r != null)
  805.                     {
  806.                         check = paymentList.records[i].Check__r.Name;
  807.                         checkId = paymentList.records[i].Check__c;
  808.                     }
  809.                     if(!paymentList.records[i].RespondentRecord__r.hasOwnProperty('Child_Campaign__r'))
  810.                     {
  811.                         paymentList.records[i].RespondentRecord__r.Child_Campaign__r = new Object();
  812.                         paymentList.records[i].RespondentRecord__r.Child_Campaign__r.Time_Slot__c = 'Unknown';
  813.                     }
  814.                     html+='<tr><td><select class="statusList" startStatus="'+paymentList.records[i].Status__c+'" contact="'+paymentList.records[i].Contact__c+'" payment="'+paymentList.records[i].Id+'">'+statusListValues+'</select><td><input type="text" class="respondentNumber" contact="'+paymentList.records[i].Contact__c+'" payment="'+paymentList.records[i].Id+'" size="4" maxlength="3" value="'+parseInt(Math.round(paymentList.records[i].Respondent_Number__c),10)+'"/></td><td>'+paymentList.records[i].RespondentRecord__r.Child_Campaign__r.Time_Slot__c+'</td><td>'+paymentList.records[i].Contact__r.FirstName+'</td><td>'+paymentList.records[i].Contact__r.LastName+'</td><td>'+paymentList.records[i].Contact__r.PID__c+'</td><td>'+paymentList.records[i].Contact__r.Gender__c+'</td><td>'+paymentList.records[i].Contact__r.Age__c+'</td><td>'+ org +'</td><td><div class="check" check="'+checkId+'" contact="'+paymentList.records[i].Contact__c+'" payment="'+paymentList.records[i].Id+'">'+check+'</div></td><td><button class="detailButton"  contact="'+paymentList.records[i].Contact__c+'" payment="'+paymentList.records[i].Id+'" >Attribute and Quota Info</button><button class="assignCheckButton"  contact="'+paymentList.records[i].Contact__c+'" payment="'+paymentList.records[i].Id+'" >Assign Check</button></td></tr>';
  815.                 }
  816.                
  817.                 html += '</tbody></table>';
  818.                 $('#checkinTable').html(html);
  819.                
  820.                 //set the default value of each select list to the value specified in the startStatus attribute
  821.                 $('.statusList').each(function(index){
  822.                     $(this).val($(this).attr('startStatus'));          
  823.                 });
  824.                
  825.                 //whena  respondent record changes, get the possible value for the DQ reason field based on the status, then attempt to evaluate the respondent record.
  826.                 $('.statusList').change(function(event, ui){
  827.                     setPickVals('#dqReason',getDependentValues('Disqualification_Reason__c',$(this).val()).values);
  828.                    
  829.                     var saveResult = evalRespondentRecord($(this).val(), $(this).attr('contact'),  $(this).attr('payment'),true);
  830.                     console.log(saveResult);
  831.                     if(!saveResult.success)
  832.                     {
  833.                         $(this).val(lastStatus);
  834.                     }  
  835.                     lastStatus = $(this).val();
  836.  
  837.                    
  838.                 }).focus(function(){
  839.                     setCheckedAttributes($(this).attr('payment'));
  840.                     lastStatus = $(this).val();
  841.                     lastContact = $(this).attr('contact');
  842.                     lastPayment = $(this).attr('payment');                    
  843.                 });
  844.                
  845.                 $('.respondentNumber').blur(function(ui,event){
  846.                     //only bother attempting to save if the value has changed.
  847.                     if(lastRespNum  != $(this).val())
  848.                     {
  849.                         //evalRespondentRecord( $('.statusList[contact='+$(this).attr('contact')+']').val(), $(this).attr('contact'),  $(this).attr('payment'));
  850.                     }
  851.                 }).focus(function(ui,event){
  852.                     lastRespNum  = $(this).val();
  853.                 }).keydown(function(event) {
  854.                     // Allow: backspace, delete, tab, escape, and enter
  855.                     if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
  856.                          // Allow: Ctrl+A
  857.                         (event.keyCode == 65 && event.ctrlKey === true) ||
  858.                          // Allow: home, end, left, right
  859.                         (event.keyCode >= 35 && event.keyCode <= 39)) {
  860.                              // let it happen, dont do anything
  861.                              return;
  862.                     }
  863.                     else {
  864.                         // Ensure that it is a number and stop the keypress
  865.                         if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {
  866.                             event.preventDefault();
  867.                         }  
  868.                     }
  869.                 });
  870.                
  871.                 tableSortify('#checkInTableGrid');    
  872.                 $( ".detailButton" ).button({
  873.                         icons: {
  874.                             primary: "ui-icon-shuffle"
  875.                         },
  876.                         text: false
  877.                     }).click(function(){
  878.                          setCheckedAttributes($(this).attr('payment'));
  879.                         $('#attributes').data('payment',$(this).attr('payment')).data('contact',$(this).attr('contact')).dialog('open');
  880.                 });    
  881.  
  882.                 $( ".assignCheckButton" ).button({
  883.                         icons: {
  884.                             primary: "ui-icon-pencil"
  885.                         },
  886.                         text: false
  887.                     }).click(function(){
  888.                         $('#updateCheckStatus').html(null);
  889.                         $('#assignCheck').dialog('option', 'title', 'Assign Check to for ' + payments[$(this).attr('payment')].Contact__r.Name);
  890.                         $('#assignCheck').data('payment',$(this).attr('payment')).data('contact',$(this).attr('contact')).dialog('open');
  891.                         $('#checkNumber').val( $('.check[payment="'+$(this).attr('payment')+ '"]').html());
  892.                         $('#updateCheckPaymentId').val($(this).attr('payment'));
  893.                        
  894.                        
  895.                 });                    
  896.        
  897.                
  898.      
  899.             }
  900.             catch(exception)
  901.             {
  902.                 returnObj.success = false;
  903.                 returnObj.message = exception;showAlert(exception.message);
  904.             }
  905.             writeLogEntry('Creating check in table using respondent data complete');
  906.             return  returnObj;                
  907.         }
  908.  
  909.  
  910.        
  911.         function parseCSV(text)
  912.         {
  913.             writeLogEntry('Parsing rotation CSV content');
  914.             var returnObj = new returnObject();
  915.             try
  916.             {        
  917.                totals = new Object();
  918.                text = text + '\n';
  919.                var fields = text.split(/\n/);
  920.                fields.pop(fields.length-1);
  921.                        
  922.                var headers = fields[0].split(','), html = '<table cellspacing="2" cellpadding="2" border="1" width="550" id="serveTable" class="tablesorter">';
  923.                
  924.                html += '<thead><tr>';
  925.                
  926.                for(var i = 0; i < headers.length; i += 1)
  927.                {          
  928.                   html += '<th scope="col" width="75">' + headers[i].trim() + '</th>';                                      
  929.                }          
  930.                html += '<th width="75">Score</th><th scope="col" width="85">Respondent</th>';
  931.                html += '</tr></thead><tbody> ';          
  932.                var data = fields.slice(1, fields.length);
  933.                
  934.                
  935.                var attributes = '';  
  936.          
  937.                for(var j = 0; j < data.length; j++)
  938.                {                          
  939.                   var dataFields = data[j].split(',');
  940.                  
  941.                   var respNum = new Object();    
  942.                   respNum['available'] = true;  
  943.                   respNum['serves'] = new Object();    
  944.                   respNum['score'] = 0;
  945.                   respNum['baseScore'] = 0;
  946.                   respNum['scoremod'] = 0;
  947.                   respNum['respno'] = dataFields[0].trim();    
  948.  
  949.                   html += '<tr>';
  950.                   for(var k =0; k < dataFields.length; k++)
  951.                   {
  952.                       dataFields[k] = dataFields[k].trim();
  953.                       if(k != 1)
  954.                       {
  955.                           html += '<td>' + dataFields[k] + '</td>';
  956.                       }
  957.                       else
  958.                       {
  959.                           html += '<td><input type="number" class="scoremod" disabled="disabled" readonly id="scoremod' + dataFields[0] +'" value="'+dataFields[k]+'" size="2" maxlength="3" /> </td>';
  960.                           respNum['scoremod'] = dataFields[k];
  961.                       }
  962.                      
  963.                       if(k > 1 && !codes.hasOwnProperty(dataFields[k]))
  964.                       {        
  965.                           codes[dataFields[k]] =  campaigns[$('#mastercampaigns').val()]['attributes'][Object.keys(codes).length+1];    
  966.                           attributes += '<li><input type="checkbox" name="attribBox_'+dataFields[k]+'"  code="'+dataFields[k]+'" attribute="'+campaigns[$('#mastercampaigns').val()]['attributes'][k]+'" id="attribBox_'+dataFields[k]+'" class="attrib_box" value="'+dataFields[k]+'"><label for="attribBox_'+dataFields[k]+'">'+dataFields[k]+' (' +codes[dataFields[k]]+')</label></li>';
  967.                          
  968.                       }
  969.                       if(k > 1)
  970.                       {
  971.                           respNum['serves'][dataFields[k]] = 1;
  972.                       }
  973.                   }
  974.                   respondentNumbers[dataFields[0]] = respNum;
  975.                   html += '<td><div id="score_'+dataFields[0]+'">0</div></td>';
  976.                   html += '<td><div id="pid_'+dataFields[0]+'"></div></td>';
  977.                   html += '</tr>';                
  978.                }          
  979.                html += '</tbody></table>';
  980.    
  981.                $('#rotationTable').html(html);
  982.                
  983.                tableSortify('#serveTable');
  984.                
  985.                drawTotalsTable();
  986.                $('#respondent_attributes').html(attributes);              
  987.             }
  988.             catch(exception)
  989.             {
  990.                 returnObj.success = false;
  991.                 returnObj.message = exception;showAlert(exception.message);
  992.             }
  993.             writeLogEntry('CSV Parsing complete');
  994.             return  returnObj;        
  995.         }
  996.        
  997.         function calculateServeScores()
  998.         {
  999.             writeLogEntry('Calculating serve scores');
  1000.             var returnObj = new returnObject();
  1001.             try
  1002.             {        
  1003.                 for(respNo in respondentNumbers)
  1004.                 {
  1005.                     if(respondentNumbers[respNo]['available'] == true)
  1006.                     {
  1007.                         respondentNumbers[respNo]['score'] = 0;
  1008.                         for(serve in respondentNumbers[respNo]['serves'])
  1009.                         {
  1010.                              respondentNumbers[respNo]['score']  += parseInt(totals[serve]['unused'],10);
  1011.                         }
  1012.                         $('#score_'+respNo).html(respondentNumbers[respNo]['score']);
  1013.                    }
  1014.                    else
  1015.                    {
  1016.                         //$('#score_'+respNo).html('----');
  1017.                    }
  1018.                 }
  1019.             }
  1020.             catch(exception)
  1021.             {
  1022.                 returnObj.success = false;
  1023.                 returnObj.message = exception;showAlert(exception.message);
  1024.             }
  1025.             writeLogEntry('Calculating serve scores complete');
  1026.             return  returnObj;                      
  1027.         }
  1028.        
  1029.         function drawTotalsTable()
  1030.         {
  1031.             writeLogEntry('Drawing totals table');
  1032.             var returnObj = new returnObject();
  1033.             try
  1034.             {
  1035.                var totalServes = 0;
  1036.                totals = new Object();
  1037.                for(respNo in respondentNumbers)
  1038.                {
  1039.                    
  1040.                    for(serve in respondentNumbers[respNo]['serves'])
  1041.                    {
  1042.                          totalServes++;
  1043.                          if(!totals.hasOwnProperty(serve))
  1044.                           {
  1045.                               totals[serve] = new Object();
  1046.                               totals[serve]['total'] = 0;  
  1047.                               totals[serve]['used'] = 0;  
  1048.                               totals[serve]['unused'] = 0;                      
  1049.                           }
  1050.                           if(respondentNumbers[respNo]['available'])
  1051.                           {
  1052.                               totals[serve]['unused']++;
  1053.                           }
  1054.                           else
  1055.                           {
  1056.                               totals[serve]['used']++;
  1057.                           }
  1058.                           totals[serve]['total']++;
  1059.                     }      
  1060.                }
  1061.    
  1062.                var totalsTable = '<table class="tablesorter" id="totalsTable" cellspacing="2" cellpadding="2" border="1" width="550">';
  1063.                totalsTable += '<thead><tr><th width="75">Serve</th><th width="75">Total</th><th width="85">Percent Of Total</th><th width="75">Assigned</th><th width="75">Remaining</th></thead><tbody>';
  1064.                          
  1065.                for(key in totals)
  1066.                {
  1067.                    totalsTable+= '<tr><td>'+key+' ('+codes[key]+')</td><td>'+totals[key]['total']+'</td><td>'+parseInt(totals[key]['total']/totalServes*100,10)+'%</td><td><div id="assigned_'+key+'">'+totals[key]['used']+'</div></td><td><div id="remaining_'+key+'">'+totals[key]['unused']+'</div></td></tr>';
  1068.                }
  1069.                totalsTable += '</tbody></table>';
  1070.                
  1071.                $('#totals').html(totalsTable);      
  1072.                 tableSortify('#totalsTable');    
  1073.             }
  1074.             catch(exception)
  1075.             {
  1076.                 returnObj.success = false;
  1077.                 returnObj.message = exception;showAlert(exception.message);
  1078.             }
  1079.             writeLogEntry('Drawing totals table complete');
  1080.             return  returnObj;        
  1081.         }
  1082.        
  1083.  
  1084.  
  1085.         function  evalRespondentRecord(status, contact, payment,showDQPopup)
  1086.         {
  1087.             writeLogEntry('Evaluating payment record ' + payment + ' with status ' + status);
  1088.             var returnObj = new returnObject();
  1089.             try
  1090.             {        
  1091.                 var currentRespondentNumber =  $('.respondentNumber[contact='+payments[payment].Contact__r.Id+']').val();
  1092.                 writeLogEntry('Found record has respondent number  ' + currentRespondentNumber);        
  1093.                
  1094.                 if( (status == 'Disqualified - Paid' || status == 'Disqualified - Not Paid') && showDQPopup)
  1095.                 {
  1096.                     writeLogEntry('Respondent has disqualified status, but no reason specified. Presenting reason dialog');  
  1097.                    $( "#selectDQReason" ).dialog( "open" );
  1098.                    currentRespondentNumber = unassignRespondentNumber(payment).data;
  1099.                    returnObj.message = 'Respondent Not Saved. Disqualified Status with No reason selected';
  1100.                    return returnObj;
  1101.                 }    
  1102.                 else if(status != 'Tested' && status != 'In Progress')
  1103.                 {
  1104.                     writeLogEntry('Respondent has non tested status. Clearing respondent number.');
  1105.                     currentRespondentNumber = unassignRespondentNumber(payment).data;
  1106.                 }
  1107.                 else if(status == 'Tested' || status == 'In Progress')
  1108.                 {
  1109.                     unassignRespondentNumber(payment);
  1110.                 }
  1111.                
  1112.                 var saveRespondent = assignRespondentNumber(payment,currentRespondentNumber,$('#useRotation').is(':checked'),status);                  
  1113.                
  1114.                
  1115.                 if(saveRespondent.success)
  1116.                 {
  1117.                     calculateServeScores();
  1118.                     $('#dqReason').val('none');
  1119.                     drawTotalsTable();      
  1120.                 }
  1121.                 else
  1122.                 {
  1123.                     writeLogEntry('Respondent record not saved. Reverting changes');
  1124.                     throw new UserException(saveRespondent.message.message);
  1125.                 }
  1126.             }
  1127.             catch(exception)
  1128.             {
  1129.                 returnObj.success = false;
  1130.                 returnObj.message = exception;
  1131.                 showAlert(exception.message);
  1132.             }
  1133.             return  returnObj;            
  1134.         }        
  1135.  
  1136.         function savePayment(obj)
  1137.         {
  1138.             setStatusMessage('Saving payment for ' + obj.Id);
  1139.             var returnObj = new returnObject();
  1140.             returnObj.data = 0;
  1141.             try
  1142.             {        
  1143.                 var paymentsToUpdate = new Array();
  1144.                 var thisPayment = new sforce.SObject("Payments__c");
  1145.                 for(field in obj)
  1146.                 {
  1147.                     thisPayment[field] = obj[field];
  1148.                 }
  1149.                 paymentsToUpdate.push(thisPayment);                  
  1150.                 saveResult = saveObject(paymentsToUpdate);
  1151.                  
  1152.                 if(saveResult[0].success == 'false')
  1153.                 {
  1154.                     throw new UserException('Save error: ' + saveResult[0].errors.message + ' ' + saveResult[0].errors.statusCode);
  1155.                 }
  1156.                  
  1157.                 returnObj.values = saveResult;    
  1158.                 setStatusMessage('');
  1159.             }
  1160.             catch(exception)
  1161.             {
  1162.                 returnObj.success = false;
  1163.                 returnObj.message = exception;
  1164.                 showAlert(exception.message);
  1165.             }        
  1166.            
  1167.             return returnObj;
  1168.         }
  1169.        
  1170.         function assignRespondentNumber(paymentId,respNum,useRotation,status)
  1171.         {  
  1172.             var returnObj = new returnObject();
  1173.             returnObj.data = 0;
  1174.             try
  1175.             {        
  1176.                 //if we are passed a numm respondent number, that means we want to use the rotation assigner to generate one.
  1177.                 if((respNum == null || respNum <=0) && useRotation && (status == 'Tested' || status == 'In Progress'))
  1178.                 {
  1179.                     writeLogEntry('Respondent is null or 0. Using rotation assigner. Finding valid rotation');
  1180.                     var getRespNo = findAvailableRespondentNumber(paymentId);
  1181.                     if(getRespNo.success)
  1182.                     {
  1183.                         writeLogEntry('Rotation found. Assigning respondent number ' + getRespNo.data);
  1184.                         unassignRespondentNumber(paymentId);
  1185.                         respNum = getRespNo.data;
  1186.                     }
  1187.                     else
  1188.                     {
  1189.                         writeLogEntry('No valid rotation could be located. Tossing error');
  1190.                         $('.respondentNumber[contact='+payments[paymentId].Contact__r.Id+']').effect( "shake", 100 ).addClass('ui-state-error');
  1191.                         throw new UserException("No valid rotation could be found for this respondent. Please adjust attributes or disqualify respondent.");
  1192.                     }
  1193.                 }
  1194.                 else if((respNum == null || respNum <= 0) && (status == 'Tested' || status == 'In Progress') &&  !useRotation)
  1195.                 {                
  1196.                      writeLogEntry('Respondent is null or 0 and not using rotation assigner. Invalid respondent number, tossing error');
  1197.                      $('.respondentNumber[contact='+payments[paymentId].Contact__r.Id+']').effect( "shake", 100 ).addClass('ui-state-error');
  1198.                      throw new UserException("Invalid respondent number. Respondent number must not be 0 if not using rotation assigner");              
  1199.                 }
  1200.  
  1201.                  returnObj.data = respNum;
  1202.                  
  1203.                 //create payment object to be saved
  1204.                 var thisPayment = new Object();
  1205.                 thisPayment.id = paymentId;
  1206.                 thisPayment.Respondent_Number__c = respNum;
  1207.                 thisPayment.Status__c = status;
  1208.                
  1209.                 writeLogEntry('Prepping record(s) for save...');
  1210.                 var saveResult = savePayment(thisPayment);
  1211.                                  
  1212.                 if(saveResult.success)
  1213.                 {
  1214.                     $('#pid_'+ respNum).html(payments[paymentId].Contact__r.Name);
  1215.                     payments[paymentId].Respondent_Number__c = respNum;
  1216.                     $('.respondentNumber[contact='+payments[paymentId].Contact__r.Id+']').val(respNum).removeClass('ui-state-error');
  1217.                    
  1218.                     if(respNum > 0)
  1219.                     {
  1220.                         respondentNumbers[respNum]['available'] = false;
  1221.                         writeLogEntry('Incrimenting used count for serves in this rotation');
  1222.                        
  1223.                         for(serve in respondentNumbers[respNum]['serves'])
  1224.                         {
  1225.                             writeLogEntry('Incrimenting serve to have total of ' + serve);
  1226.                             totals[serve]['used']++;
  1227.                             totals[serve]['unused']--;
  1228.                         }                    
  1229.                     }
  1230.                     else
  1231.                     {
  1232.                         writeLogEntry('No ajustments in total since respondent has been unassigned and did not receive new respondent number.');
  1233.                     }
  1234.                 }
  1235.                 else
  1236.                 {
  1237.                     throw new UserException("Error saving payment: " + saveResult.message.message);
  1238.                 }                        
  1239.          
  1240.             }
  1241.             catch(exception)
  1242.             {
  1243.                 returnObj.success = false;
  1244.                 returnObj.message = exception;
  1245.             }        
  1246.            
  1247.             return returnObj;
  1248.         }        
  1249.  
  1250.         function findAvailableRespondentNumber(paymentId)
  1251.         {
  1252.             writeLogEntry('Trying to find available rotation for respondent');
  1253.             var returnObj = new returnObject();
  1254.             try
  1255.             {        
  1256.                  var assignedAttributes = new Array();
  1257.                      
  1258.                  $('.attrib_box:checked').each(function(index){                    
  1259.                      assignedAttributes.push($(this).val());
  1260.                  });
  1261.                  
  1262.                 writeLogEntry('Respondent has attributes: '+assignedAttributes.join(", "));    
  1263.                 var potentials = new Array();
  1264.                
  1265.                 for(respNo in respondentNumbers)
  1266.                 {
  1267.                     var isValid = true;
  1268.                     if(!respondentNumbers[respNo]['available'])
  1269.                     {
  1270.                         continue;
  1271.                     }
  1272.                     for(serve in respondentNumbers[respNo]['serves'])
  1273.                     {
  1274.                         if($.inArray(serve, assignedAttributes) < 0)
  1275.                         {
  1276.                             isValid = false;
  1277.                         }
  1278.                     }
  1279.                     if(isValid)
  1280.                     {
  1281.                         potentials.push(respondentNumbers[respNo]);
  1282.                         writeLogEntry('Found potential respondent numbers/serve codes : '+respNo);
  1283.                     }
  1284.                 }
  1285.                
  1286.                
  1287.                 var score = 100000;
  1288.                 var respNo = -1;
  1289.                
  1290.                 for(var i = 0; i< potentials.length; i++)
  1291.                 {
  1292.                     if(potentials[i]['score'] < score && potentials[i]['score'] > 0)
  1293.                     {
  1294.                         score = potentials[i]['score'] ;
  1295.                         respNo = potentials[i]['respno'] ;
  1296.                     }
  1297.                 }
  1298.                 returnObj.data = respNo;
  1299.                 if(respNo < 0)
  1300.                 {
  1301.                     throw new UserException("No matching code found for attributes on respondent.");
  1302.                 }
  1303.             }
  1304.             catch(exception)
  1305.             {
  1306.                 returnObj.success = false;
  1307.                 returnObj.message = exception;
  1308.                 showAlert(exception.message);
  1309.             }
  1310.             return  returnObj;            
  1311.            
  1312.         }
  1313.  
  1314.         function unassignRespondentNumber(paymentId)
  1315.         {
  1316.             var returnObj = new returnObject();
  1317.             try
  1318.             {
  1319.                 returnObj.data = 0;
  1320.                 var respNo = parseInt(Math.round(payments[paymentId].Respondent_Number__c),10);
  1321.                 writeLogEntry('Clearing stored information for respondent number : '+respNo);
  1322.                 if(respondentNumbers.hasOwnProperty(respNo) && respondentNumbers[respNo].hasOwnProperty('serves') && respNo > 0)
  1323.                 {
  1324.                     for(serve in respondentNumbers[respNo]['serves'])
  1325.                     {
  1326.                         totals[serve]['used']--;
  1327.                         totals[serve]['unused']++;
  1328.                     }
  1329.                 }                
  1330.                
  1331.                 $('#pid_'+ respNo).html(null);
  1332.                 payments[paymentId].Respondent_Number__c = 0;
  1333.                 $('.respondentNumber[contact='+payments[paymentId].Contact__r.Id+']').val(0);
  1334.                 if(respondentNumbers.hasOwnProperty(respNo) && respNo > 0)
  1335.                 {
  1336.                     respondentNumbers[respNo]['available'] = true;                              
  1337.                 }    
  1338.                
  1339.             }
  1340.             catch(exception)
  1341.             {
  1342.                 returnObj.success = false;
  1343.                 returnObj.message = exception;
  1344.                 showAlert(exception.message + ' on line ' + exception.lineNumber);
  1345.             }
  1346.             return  returnObj;
  1347.         }
  1348.                        
  1349.         function setStatusMessage(message)
  1350.         {
  1351.             $('#statusDiv').html(message);
  1352.         }
  1353.        
  1354.  
  1355.         function saveObject(objectList)
  1356.         {
  1357.                 var saveResult = sforce.connection.update(objectList);
  1358.                 return saveResult;
  1359.         }
  1360.        
  1361.         function runQuery(queryString,callback)
  1362.         {
  1363.             var resultHandler = {onSuccess : function(queryResult){
  1364.                     if(queryResult.size == 0)
  1365.                     {
  1366.                         queryResult.records = new Array();
  1367.                     }
  1368.                     if(queryResult.size == 1)
  1369.                     {
  1370.                         var dataArray = new Array();
  1371.                         dataArray[0] = new Object();
  1372.                        
  1373.                         for(key in queryResult.records)
  1374.                         {
  1375.                                 dataArray[0][key] = queryResult.records[key];
  1376.                        }
  1377.                            
  1378.                         delete queryResult['records'];        
  1379.                         queryResult.records = dataArray;                        
  1380.                     }
  1381.                  
  1382.                     callback(queryResult);
  1383.                 },
  1384.                 onFailure : function(e){
  1385.                     console.log(e);
  1386.                     alert('Error: ' + e);
  1387.                 }
  1388.             };
  1389.             var queryResult = sforce.connection.query(queryString, resultHandler);          
  1390.         }    
  1391.        
  1392.         function showAlert(message)
  1393.         {
  1394.             writeLogEntry(message);
  1395.             $('#statusDiv').html(message);
  1396.         }                        
  1397.         function UserException(message) {
  1398.            this.message = message;
  1399.            this.name = "UserException";
  1400.         }
  1401.        
  1402.        function checkOnline()
  1403.        {
  1404.            if (!navigator.onLine)
  1405.            {
  1406.                writeLogEntry('Internet connectivity interuption. This has happened ' + offlineCount + ' times');
  1407.                 offlineCount++;
  1408.             }
  1409.             else
  1410.             {
  1411.                 if(offlineCount > 5)
  1412.                 {
  1413.                     writeLogEntry('Connectivity Restored');
  1414.                 }
  1415.                 offlineCount = 0;
  1416.                 $('#lostConnection').dialog('close');
  1417.             }
  1418.             if(offlineCount > 5)
  1419.             {
  1420.                 $('#lostConnection').dialog('open');
  1421.             }
  1422.        }
  1423.        
  1424.        function writeLogEntry(message)
  1425.        {
  1426.            $('#log').append(message + '<br/>');
  1427.        }
  1428.  
  1429.         function setLink(campaignName)
  1430.         {
  1431.             var reportName = 'Payments Report grouped by Study #';
  1432.             var campaignId = campaignName.substring(0,campaignName.indexOf('-'));
  1433.             var instance = 'na2';
  1434.            
  1435.             try
  1436.             {
  1437.                   var url = window.location.toString();
  1438.                   instance = url.substring(10,13);    
  1439.             }
  1440.             catch(ex){ }
  1441.             if(reportId == null)
  1442.             {
  1443.                 runQuery("select id from report where name = '"+reportName+"'",function(data){
  1444.                     reportId = data.records[0].Id;
  1445.                      var basePath = 'https://'+instance+'.salesforce.com/'+reportId+'?pv0='+campaignId;      
  1446.                     $("#reportLink").prop("href", basePath);
  1447.                     $('#filter-box').val(null);  
  1448.                 });
  1449.             }
  1450.             else
  1451.             {
  1452.                 var basePath = 'https://'+instance+'.salesforce.com/'+reportId+'?pv0='+campaignId;      
  1453.                 $("#reportLink").prop("href", basePath);
  1454.                 $('#filter-box').val(null);              
  1455.             }
  1456.         }
  1457.  
  1458.     </script>
  1459.     <title>Host Check In EXTREME!</title>
  1460.     </head>
  1461.    
  1462.     <body>
  1463.  
  1464.  
  1465.  
  1466.         <div id="toolbar" class="ui-widget-header ui-corner-all">
  1467.  
  1468.             <label for="mastercampaigns">Select Campaign</label>
  1469.             <select id="umbrellacampaigns"><option>--Select One--</option></select>
  1470.             <select id="mastercampaigns"><option>--Select One--</option></select>
  1471.              <!-----  
  1472.              <button id="tlbrBtn1">Rotation Table</button>
  1473.              <button id="tlbrBtn2">Report Link</button>
  1474.              <button id="tlbrBtn3">Progress Tracker</button>
  1475.              <button id="tlbrBtn4">Reload Respondent List</button>
  1476.              ------>      
  1477.              
  1478.             Search: <input name="filter" id="filter-box" value="" maxlength="30" size="30" type="text" />          
  1479.             <button class="button" id="clearButton">Clear</button>
  1480.             <div class="clear"></div>      
  1481.             <input type="checkbox" id="useRotation" name="useRotation" disabled="disabled" /><label for="useRotation">Use Rotation Assigner</label>
  1482.             <button class="button" id="bulkStatusChangeButton"  disabled="disabled">Change Statuses</button>  
  1483.             <a class="reportLink button" href="https://na2.salesforce.com/00O40000002jNnY?pv0=02585" id="reportLink" target="_blank" >Report Link</a>
  1484.             <span id="statusDiv"></span>                
  1485.             <div id="switcher"></div>          
  1486.         </div>
  1487.                    
  1488.         <div id="container">
  1489.        
  1490.             <ul id="tabs">
  1491.                 <li><a href="#tabs-1">Check In</a></li>
  1492.                 <li><a href="#tabs-2">Rotation Tables</a></li>
  1493.                 <li><a href="#tabs-3">Rotation Totals</a></li>
  1494.                 <li><a href="#tabs-4">Progress Tracker</a></li>
  1495.                 <li><a href="#tabs-5">Log</a></li>
  1496.             </ul>
  1497.            
  1498.             <div id="tabs-1">    
  1499.                  <div id="checkinTable"></div>
  1500.             </div>
  1501.             <div id="tabs-2">
  1502.                 <div id="rotationTable"></div>
  1503.             </div>              
  1504.             <div id="tabs-3">
  1505.                 <div id="totals"></div>
  1506.             </div>              
  1507.             <div id="tabs-4">
  1508.                 <iframe id="progressTrackerFrame" width="100%" height="500" frameborder="0"></iframe>
  1509.             </div>            
  1510.             <div id="tabs-5">
  1511.                 <div id="log"></div><br />
  1512.                 <button id="clearLog" class="button">Clear Log</button>
  1513.             </div>              
  1514.             <div id="reportLink" class="dialog" title="Report"></div>
  1515.            
  1516.             <div id="progressTracker" class="dialog" title="Progress Tracker"></div>
  1517.            
  1518.             <div id="selectDQReason" class="dialog" title="Select Disqualification Reason">
  1519.                 <p>Please select the reason this person is being disqualified.</p>
  1520.                 <select id="dqReason" size="1"></select>    
  1521.              
  1522.                 <div id="dqSaveResult"></div>
  1523.                 <input type="button"  class="button" name="submitRow" id="saveDQRow" value="Save" />
  1524.                 <input type="button"  class="button" name="cancelSave" id="cancelDQRow" value="Cancel" />            
  1525.             </div>
  1526.            
  1527.             <div id="showAlert" class="dialog" title="Alert!"></div>
  1528.            
  1529.             <div id="attributes" class="dialog" title="Respondent Attributes">
  1530.                 View/Edit Respondent Attributes/Serve Codes
  1531.                 <ul id="respondent_attributes"></ul>
  1532.                 <div id="updateAttributeStatus"></div>
  1533.                 <input id="updateAttributePaymentId" type="hidden" />
  1534.                 <center><input type="button" value="Update" id="updateAttributes" class="button"/><input type="button" value="Cancel" class="button"/></center>            
  1535.             </div>
  1536.  
  1537.             <div id="assignCheck" class="dialog" title="Assign Check To Respondent">
  1538.                <label for="checkNumber">Check Number</label>
  1539.                 <input type="text" name="checkNumber" id="checkNumber" />
  1540.                <div id="updateCheckStatus"></div>
  1541.                <br /><br/>
  1542.                <center><input type="button" value="Update" id="assignCheckButton" class="button"/><input type="button" value="Cancel" class="button"/></center>            
  1543.                  <input id="updateCheckPaymentId" type="hidden" />
  1544.             </div>
  1545.                    
  1546.         </div>
  1547.        
  1548.         <div id="bulkStatusChange" title="Bulk Change Status" class="dialog">
  1549.                 <table>
  1550.                     <tr>
  1551.                         <td><label for="bulkChangeFrom">Change Payments With Status</label></td><td><select id="bulkChangeFrom"></select></td>
  1552.                     </tr>
  1553.                     <tr>
  1554.                         <td><label for="bulkChangeTo">To Have Status</label></td><td><select id="bulkChangeTo"></select></td>
  1555.                     </tr>  
  1556.                     <tr>
  1557.                         <td> <button class="button" id="bulkStatusChangeSubmit">Change</button> </td><td><div id="bulkChangeProgressBar"></div><div  id="bulkChangeProgressVal"></div></td>
  1558.                     </tr>            
  1559.                 </table>
  1560.         </div>
  1561.         <div id="lostConnection" title="No Internet Connection!">It seems internet connectivity has been lost. Please check your connection. This dialog will automatically close when connection has been re-established.</div>
  1562.     </body>
  1563.  
  1564.  
  1565. </apex:page>
Add Comment
Please, Sign In to add comment