[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/layouts/vlayout/modules/Inventory/resources/ -> Edit.js (source)

   1  /*+***********************************************************************************
   2   * The contents of this file are subject to the vtiger CRM Public License Version 1.0
   3   * ("License"); You may not use this file except in compliance with the License
   4   * The Original Code is:  vtiger CRM Open Source
   5   * The Initial Developer of the Original Code is vtiger.
   6   * Portions created by vtiger are Copyright (C) vtiger.
   7   * All Rights Reserved.
   8   *************************************************************************************/
   9  
  10  Vtiger_Edit_Js("Inventory_Edit_Js",{
  11  
  12      zeroDiscountType : 'zero' ,
  13      percentageDiscountType : 'percentage',
  14      directAmountDiscountType : 'amount',
  15  
  16      individualTaxType : 'individual',
  17      groupTaxType :  'group'
  18  },{
  19  
  20      //Container which stores the line item elements
  21      lineItemContentsContainer : false,
  22      //Container which stores line item result details
  23      lineItemResultContainer : false,
  24      //contains edit view form element
  25      editViewForm : false,
  26  
  27      //a variable which will be used to hold the sequence of the row
  28      rowSequenceHolder : false,
  29  
  30      //holds the element which has basic hidden row which we can clone to add rows
  31      basicRow : false,
  32  
  33      //will be having class which is used to identify the rows
  34      rowClass : 'lineItemRow',
  35      
  36      prevSelectedCurrencyConversionRate : false,
  37  
  38      //Will have the mapping of address fields based on the modules
  39      addressFieldsMapping : {'Contacts' :
  40                                  {'bill_street' :  'mailingstreet',
  41                                  'ship_street' : 'otherstreet',
  42                                  'bill_pobox' : 'mailingpobox',
  43                                  'ship_pobox' : 'otherpobox',
  44                                  'bill_city' : 'mailingcity',
  45                                  'ship_city'  : 'othercity',
  46                                  'bill_state' : 'mailingstate',
  47                                  'ship_state' : 'otherstate',
  48                                  'bill_code' : 'mailingzip',
  49                                  'ship_code' : 'otherzip',
  50                                  'bill_country' : 'mailingcountry',
  51                                  'ship_country' : 'othercountry'
  52                                  } ,
  53  
  54                              'Accounts' :
  55                                  {
  56                                  'bill_street' :  'bill_street',
  57                                  'ship_street' : 'ship_street',
  58                                  'bill_pobox' : 'bill_pobox',
  59                                  'ship_pobox' : 'ship_pobox',
  60                                  'bill_city' : 'bill_city',
  61                                  'ship_city'  : 'ship_city',
  62                                  'bill_state' : 'bill_state',
  63                                  'ship_state' : 'ship_state',
  64                                  'bill_code' : 'bill_code',
  65                                  'ship_code' : 'ship_code',
  66                                  'bill_country' : 'bill_country',
  67                                  'ship_country' : 'ship_country'
  68                                  },
  69  
  70                              'Vendors' :
  71                                  {
  72                                  'bill_street' : 'street',
  73                                  'ship_street' : 'street',
  74                                  'bill_pobox' : 'pobox',
  75                                  'ship_pobox' : 'pobox',
  76                                  'bill_city' : 'city',
  77                                  'ship_city'  : 'city',
  78                                  'bill_state' : 'state',
  79                                  'ship_state' : 'state',
  80                                  'bill_code' : 'postalcode',
  81                                  'ship_code' : 'postalcode',
  82                                  'bill_country' : 'country',
  83                                  'ship_country' : 'country'
  84                                  }
  85                              },
  86  
  87      //Address field mapping between modules specific for billing and shipping
  88      addressFieldsMappingBetweenModules:{
  89                                  'AccountsBillMap' : {
  90                                      'bill_street' :  'bill_street',
  91                                      'bill_pobox' : 'bill_pobox',
  92                                      'bill_city' : 'bill_city',
  93                                      'bill_state' : 'bill_state',
  94                                      'bill_code' : 'bill_code',
  95                                      'bill_country' : 'bill_country'
  96                                      },
  97                                  'AccountsShipMap' : {
  98                                      'ship_street' : 'ship_street',
  99                                      'ship_pobox' : 'ship_pobox',
 100                                      'ship_city'  : 'ship_city',
 101                                      'ship_state' : 'ship_state',
 102                                      'ship_code' : 'ship_code',
 103                                      'ship_country' : 'ship_country'
 104                                      },
 105                                  'ContactsBillMap' : {
 106                                      'bill_street' :  'mailingstreet',
 107                                      'bill_pobox' : 'mailingpobox',
 108                                      'bill_city' : 'mailingcity',
 109                                      'bill_state' : 'mailingstate',
 110                                      'bill_code' : 'mailingzip',
 111                                      'bill_country' : 'mailingcountry'
 112                                      },
 113                                  'ContactsShipMap' : {
 114                                      'ship_street' : 'otherstreet',
 115                                      'ship_pobox' : 'otherpobox',
 116                                      'ship_city'  : 'othercity',
 117                                      'ship_state' : 'otherstate',
 118                                      'ship_code' : 'otherzip',
 119                                      'ship_country' : 'othercountry'
 120                                      }
 121  
 122      },
 123  
 124      //Address field mapping within module
 125      addressFieldsMappingInModule : {
 126                                          'bill_street':'ship_street',
 127                                          'bill_pobox':'ship_pobox',
 128                                          'bill_city'    :'ship_city',
 129                                          'bill_state':'ship_state',
 130                                          'bill_code'    :'ship_code',
 131                                          'bill_country':'ship_country'
 132                                  },
 133  
 134      /**
 135       * Function that is used to get the line item container
 136       * @return : jQuery object
 137       */
 138      getLineItemContentsContainer : function() {
 139          if(this.lineItemContentsContainer == false) {
 140              this.setLineItemContainer(jQuery('#lineItemTab'));
 141          }
 142          return this.lineItemContentsContainer;
 143      },
 144  
 145      /**
 146       * Function to set line item container
 147       * @params : element - jQuery object which represents line item container
 148       * @return : current instance ;
 149       */
 150      setLineItemContainer : function(element) {
 151          this.lineItemContentsContainer = element;
 152          return this;
 153      },
 154  
 155      /**
 156       * Function to get the line item result container
 157       * @result : jQuery object which represent line item result container
 158       */
 159      getLineItemResultContainer : function(){
 160          if(this.lineItemResultContainer == false) {
 161              this.setLinteItemResultContainer(jQuery('#lineItemResult'));
 162          }
 163          return this.lineItemResultContainer;
 164      },
 165  
 166      /**
 167       * Function to set line item result container
 168       * @param : element - jQuery object which represents line item result container
 169       * @result : current instance
 170       */
 171      setLinteItemResultContainer : function(element) {
 172          this.lineItemResultContainer = element;
 173          return this;
 174      },
 175  
 176      /**
 177       * Function which will give the closest line item row element
 178       * @return : jQuery object
 179       */
 180      getClosestLineItemRow : function(element){
 181          return element.closest('tr.'+this.rowClass);
 182      },
 183  
 184      getShippingAndHandlingControlElement : function(){
 185          return jQuery('#shipping_handling_charge');
 186      },
 187  
 188      getAdjustmentTypeElement : function() {
 189          return jQuery('input:radio[name="adjustmentType"]');
 190      },
 191  
 192      getAdjustmentTextElement : function(){
 193          return jQuery('#adjustment');
 194      },
 195  
 196      getTaxTypeSelectElement : function(){
 197          return jQuery('#taxtype');
 198      },
 199  
 200      isIndividualTaxMode : function() {
 201          var taxTypeElement = this.getTaxTypeSelectElement();
 202          var selectedOption = taxTypeElement.find('option:selected');
 203          if(selectedOption.val() == Inventory_Edit_Js.individualTaxType){
 204              return true;
 205          }
 206          return false;
 207      },
 208  
 209      isGroupTaxMode : function() {
 210          var taxTypeElement = this.getTaxTypeSelectElement();
 211          var selectedOption = taxTypeElement.find('option:selected');
 212          if(selectedOption.val() == Inventory_Edit_Js.groupTaxType){
 213              return true;
 214          }
 215          return false;
 216      },
 217  
 218      /**
 219       * Function which gives edit view form
 220       * @return : jQuery object which represents the form element
 221       */
 222      getForm : function() {
 223          if(this.editViewForm == false){
 224              this.editViewForm = jQuery('#EditView');
 225          }
 226          return this.editViewForm;
 227      },
 228  
 229      /**
 230       * Function which gives quantity value
 231       * @params : lineItemRow - row which represents the line item
 232       * @return : string
 233       */
 234      getQuantityValue : function(lineItemRow){
 235          return parseFloat(jQuery('.qty', lineItemRow).val());
 236      },
 237  
 238      /**
 239       * Function which will give me list price value
 240       * @params : lineItemRow - row which represents the line item
 241       * @return : string
 242       */
 243      getListPriceValue : function(lineItemRow) {
 244          return parseFloat(jQuery('.listPrice',lineItemRow).val());
 245      },
 246  
 247      setListPriceValue : function(lineItemRow, listPriceValue) {
 248          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 249          var listPrice = parseFloat(listPriceValue).toFixed(numberOfDecimal);
 250          lineItemRow.find('.listPrice').val(listPrice);
 251          return this;
 252      },
 253  
 254  
 255      /**
 256       * Function which will set the line item total value excluding tax and discount
 257       * @params : lineItemRow - row which represents the line item
 258       *             lineItemTotalValue - value which has line item total  (qty*listprice)
 259       * @return : current instance;
 260       */
 261      setLineItemTotal : function(lineItemRow, lineItemTotalValue) {
 262          jQuery('.productTotal', lineItemRow).text(lineItemTotalValue);
 263          return this;
 264      },
 265  
 266      /**
 267       * Function which will get the value of line item total (qty*listprice)
 268       * @params : lineItemRow - row which represents the line item
 269       * @return : string
 270       */
 271      getLineItemTotal : function(lineItemRow) {
 272          return parseFloat(this.getLineItemTotalElement(lineItemRow).text());
 273      },
 274  
 275      /**
 276       * Function which will get the line item total element
 277       * @params : lineItemRow - row which represents the line item
 278       * @return : jQuery element
 279       */
 280      getLineItemTotalElement : function(lineItemRow) {
 281          return jQuery('.productTotal', lineItemRow);
 282      },
 283  
 284      /**
 285       * Function which will set the discount total value for line item
 286       * @params : lineItemRow - row which represents the line item
 287       *             discountValue - discount value
 288       * @return : current instance;
 289       */
 290      setDiscountTotal : function(lineItemRow, discountValue) {
 291          jQuery('.discountTotal',lineItemRow).text(discountValue);
 292          return this;
 293      },
 294  
 295      /**
 296       * Function which will get the value of total discount
 297       * @params : lineItemRow - row which represents the line item
 298       * @return : string
 299       */
 300      getDiscountTotal : function(lineItemRow) {
 301          return parseFloat(jQuery('.discountTotal',lineItemRow).text());
 302      },
 303  
 304      /**
 305       * Function which will set the total after discount value
 306       * @params : lineItemRow - row which represents the line item
 307       *             totalAfterDiscountValue - total after discount value
 308       * @return : current instance;
 309       */
 310      setTotalAfterDiscount : function(lineItemRow, totalAfterDiscountValue){
 311          jQuery('.totalAfterDiscount',lineItemRow).text(totalAfterDiscountValue);
 312          return this;
 313      },
 314  
 315      /**
 316       * Function which will get the value of total after discount
 317       * @params : lineItemRow - row which represents the line item
 318       * @return : string
 319       */
 320      getTotalAfterDiscount : function(lineItemRow) {
 321          return parseFloat(jQuery('.totalAfterDiscount',lineItemRow).text());
 322      },
 323  
 324      /**
 325       * Function which will set the tax total
 326       * @params : lineItemRow - row which represents the line item
 327       *             taxTotal -  tax total
 328       * @return : current instance;
 329       */
 330      setLineItemTaxTotal : function(lineItemRow, taxTotal) {
 331          jQuery('.productTaxTotal', lineItemRow).text(taxTotal);
 332          return this;
 333      },
 334  
 335      /**
 336       * Function which will get the value of total tax
 337       * @params : lineItemRow - row which represents the line item
 338       * @return : string
 339       */
 340      getLineItemTaxTotal : function(lineItemRow){
 341          return parseFloat(jQuery('.productTaxTotal', lineItemRow).text());
 342      },
 343  
 344      /**
 345       * Function which will set the line item net price
 346       * @params : lineItemRow - row which represents the line item
 347       *             lineItemNetPriceValue -  line item net price value
 348       * @return : current instance;
 349       */
 350      setLineItemNetPrice : function(lineItemRow, lineItemNetPriceValue){
 351          jQuery('.netPrice',lineItemRow).text(lineItemNetPriceValue);
 352          return this;
 353      },
 354  
 355      /**
 356       * Function which will get the value of net price
 357       * @params : lineItemRow - row which represents the line item
 358       * @return : string
 359       */
 360      getLineItemNetPrice : function(lineItemRow) {
 361          return parseFloat(jQuery('.netPrice',lineItemRow).text());
 362      },
 363  
 364      setNetTotal : function(netTotalValue){
 365          jQuery('#netTotal').text(netTotalValue);
 366          return this;
 367      },
 368  
 369      getNetTotal : function() {
 370          return parseFloat(jQuery('#netTotal').text());
 371      },
 372  
 373      /**
 374       * Function to set the final discount total
 375       */
 376      setFinalDiscountTotal : function(finalDiscountValue){
 377          jQuery('#discountTotal_final').text(finalDiscountValue);
 378          return this;
 379      },
 380  
 381      getFinalDiscountTotal : function() {
 382          return parseFloat(jQuery('#discountTotal_final').text());
 383      },
 384  
 385      setGroupTaxTotal : function(groupTaxTotalValue) {
 386          jQuery('#tax_final').text(groupTaxTotalValue);
 387      },
 388  
 389      getGroupTaxTotal : function() {
 390          return parseFloat(jQuery('#tax_final').text());
 391      },
 392  
 393      getShippingAndHandling : function() {
 394          return parseFloat(this.getShippingAndHandlingControlElement().val());
 395      },
 396  
 397      setShippingAndHandlingTaxTotal : function() {
 398          var shippingTotal = jQuery('.shippingTaxTotal');
 399          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 400          var shippingFinalTaxTotal = 0;
 401          jQuery.each(shippingTotal,function(index,domElement){
 402              var totalVal = parseFloat(jQuery(domElement).val());
 403              shippingFinalTaxTotal += totalVal;
 404          });
 405          shippingFinalTaxTotal = shippingFinalTaxTotal.toFixed(numberOfDecimal);
 406          jQuery('#shipping_handling_tax').text(shippingFinalTaxTotal);
 407          return this;
 408      },
 409  
 410      getShippingAndHandlingTaxTotal : function() {
 411          return parseFloat(jQuery('#shipping_handling_tax').text());
 412      },
 413  
 414      getAdjustmentValue : function() {
 415          return parseFloat(this.getAdjustmentTextElement().val());
 416      },
 417  
 418      isAdjustMentAddType : function() {
 419          var adjustmentSelectElement = this.getAdjustmentTypeElement();
 420          var selectionOption;
 421          adjustmentSelectElement.each(function(){
 422              if(jQuery(this).is(':checked')){
 423                  selectionOption = jQuery(this);
 424              }
 425          })
 426          if(typeof selectionOption != "undefined"){
 427              if(selectionOption.val() == '+'){
 428                  return true;
 429              }
 430          }
 431          return false;
 432      },
 433  
 434      isAdjustMentDeductType : function() {
 435          var adjustmentSelectElement = this.getAdjustmentTypeElement();
 436          var selectionOption;
 437          adjustmentSelectElement.each(function(){
 438              if(jQuery(this).is(':checked')){
 439                  selectionOption = jQuery(this);
 440              }
 441          })
 442          if(typeof selectionOption != "undefined"){
 443              if(selectionOption.val() == '-'){
 444                  return true;
 445              }
 446          }
 447          return false;
 448      },
 449  
 450      setGrandTotal : function(grandTotalValue) {
 451          jQuery('#grandTotal').text(grandTotalValue);
 452          return this;
 453      },
 454  
 455      getGrandTotal : function() {
 456          return parseFloat(jQuery('#grandTotal').text());
 457      },
 458  
 459      loadRowSequenceNumber: function() {
 460          if(this.rowSequenceHolder == false) {
 461              this.rowSequenceHolder = jQuery('.' + this.rowClass, this.getLineItemContentsContainer()).length;
 462          }
 463          return this;
 464      },
 465  
 466      getNextLineItemRowNumber : function() {
 467          if(this.rowSequenceHolder == false){
 468              this.loadRowSequenceNumber();
 469          }
 470          return ++this.rowSequenceHolder;
 471      },
 472  
 473      /**
 474       * Function which will return the basic row which can be used to add new rows
 475       * @return jQuery object which you can use to
 476       */
 477      getBasicRow : function() {
 478          if(this.basicRow == false){
 479              var lineItemTable = this.getLineItemContentsContainer();
 480              this.basicRow = jQuery('.lineItemCloneCopy',lineItemTable)
 481          }
 482          var newRow = this.basicRow.clone(true,true);
 483          var individualTax = this.isIndividualTaxMode();
 484          if(individualTax){
 485              newRow.find('.individualTaxContainer').removeClass('hide');
 486          }
 487          return newRow.removeClass('hide lineItemCloneCopy');
 488      },
 489  
 490      registerAddingNewProductsAndServices: function(){
 491          var thisInstance = this;
 492          var lineItemTable = this.getLineItemContentsContainer();
 493          jQuery('#addProduct').on('click',function(){
 494              var newRow = thisInstance.getBasicRow().addClass(thisInstance.rowClass);
 495              jQuery('.lineItemPopup[data-module-name="Services"]',newRow).remove();
 496              var sequenceNumber = thisInstance.getNextLineItemRowNumber();
 497              newRow = newRow.appendTo(lineItemTable);
 498              thisInstance.checkLineItemRow();
 499              newRow.find('input.rowNumber').val(sequenceNumber);
 500              thisInstance.updateLineItemsElementWithSequenceNumber(newRow,sequenceNumber);
 501              newRow.find('input.productName').addClass('autoComplete');
 502              thisInstance.registerLineItemAutoComplete(newRow);
 503          });
 504          jQuery('#addService').on('click',function(){
 505              var newRow = thisInstance.getBasicRow().addClass(thisInstance.rowClass);
 506              jQuery('.lineItemPopup[data-module-name="Products"]',newRow).remove();
 507              var sequenceNumber = thisInstance.getNextLineItemRowNumber();
 508              newRow = newRow.appendTo(lineItemTable);
 509              thisInstance.checkLineItemRow();
 510              newRow.find('input.rowNumber').val(sequenceNumber);
 511              thisInstance.updateLineItemsElementWithSequenceNumber(newRow,sequenceNumber);
 512              newRow.find('input.productName').addClass('autoComplete');
 513              thisInstance.registerLineItemAutoComplete(newRow);
 514          });
 515      },
 516      getTaxDiv: function(taxObj,parentRow){
 517          var rowNumber = jQuery('input.rowNumber',parentRow).val();
 518          var loopIterator = 1;
 519          var taxDiv = '<div class="taxUI validCheck hide" id="tax_div'+rowNumber+'">'+
 520              '<table width="100%" border="0" cellpadding="5" cellspacing="0" class="table table-nobordered popupTable" id="tax_table'+rowNumber+'">'+
 521                 '<tr>'+
 522                      '<th id="tax_div_title'+rowNumber+'" align="left" ><b>Set Tax for :</b></th>'+
 523                      '<th colspan="2"><button aria-hidden="true" data-dismiss="modal" class="close closeDiv" type="button">x</button>'+
 524                          '</th>'+
 525                 '</tr>';
 526             if(!jQuery.isEmptyObject(taxObj)){
 527                 for(var taxName in taxObj){
 528                     var taxInfo = taxObj[taxName]
 529                     taxDiv += '<tr>'+
 530                      '<td>'+
 531                      '<input type="text" name="'+taxName+'_percentage'+rowNumber+'" data-validation-engine="validate[funcCall[Vtiger_PositiveNumber_Validator_Js.invokeValidation]]" id="'+taxName+'_percentage'+rowNumber+'" value="'+taxInfo.percentage+'" class="smallInputBox taxPercentage">&nbsp;%'+
 532                      '</td>'+
 533                      '<td><div class="textOverflowEllipsis">'+taxInfo.label+'</div></td> '+
 534                      '<td>'+
 535                      '<input type="text" name="popup_tax_row'+rowNumber+'" class="cursorPointer smallInputBox taxTotal" value="0.0" readonly>'+
 536                      '</td>'+
 537                     '</tr>';
 538                     loopIterator++;
 539                 }
 540             }else{
 541                  taxDiv += '<tr>'+
 542                              '<td>'+app.vtranslate("JS_LBL_NO_TAXES")+'</td>'+
 543                            '</tr>';
 544             }
 545          taxDiv += '</table><div class="modal-footer lineItemPopupModalFooter modal-footer-padding">'+
 546                  '<div class=" pull-right cancelLinkContainer">'+
 547                      '<a class="cancelLink" type="reset" data-dismiss="modal">'+app.vtranslate("JS_LBL_CANCEL")+'</a>'+
 548                  '</div>'+
 549                  '<button class="btn btn-success taxSave" type="button" name="lineItemActionSave"><strong>'+app.vtranslate("JS_LBL_SAVE")+'</strong></button>'+
 550              '</div></div>';
 551          return jQuery(taxDiv);
 552      },
 553  
 554      loadSubProducts : function(lineItemRow) {
 555          var recordId = jQuery('input.selectedModuleId',lineItemRow).val();
 556          var subProrductParams = {
 557          'module' : "Products",
 558          'action' : "SubProducts",
 559          'record' : recordId
 560          }
 561          var progressInstace = jQuery.progressIndicator();
 562          AppConnector.request(subProrductParams).then(
 563              function(data){
 564  
 565                  var responseData = data.result;
 566                  var subProductsContainer = jQuery('.subProductsContainer',lineItemRow);
 567                  var subProductIdHolder = jQuery('.subProductIds',lineItemRow);
 568  
 569                  var subProductHtml = '';
 570                  for(var id in responseData) {
 571                      subProductHtml += '<em>-'+responseData[id]+'</em><br>';
 572                  }
 573                  subProductIdHolder.val(Object.keys(responseData).join(':'));
 574                  subProductsContainer.html(subProductHtml);
 575                  progressInstace.hide();
 576              },
 577              function(error,err){
 578                  //TODO : handle the error case
 579              }
 580          );
 581      },
 582  
 583      mapResultsToFields: function(referenceModule,element,responseData){
 584          var parentRow = jQuery(element).closest('tr.'+this.rowClass);
 585          var lineItemNameElment = jQuery('input.productName',parentRow);
 586  
 587          for(var id in responseData){
 588              var recordId = id;
 589              var recordData = responseData[id];
 590              var selectedName = recordData.name;
 591              var unitPrice = recordData.listprice;
 592              var listPriceValues = recordData.listpricevalues;
 593              var taxes = recordData.taxes;
 594              if(referenceModule == 'Products') {
 595                  parentRow.data('quantity-in-stock',recordData.quantityInStock);
 596              }
 597              var description = recordData.description;
 598              jQuery('input.selectedModuleId',parentRow).val(recordId);
 599              jQuery('input.lineItemType',parentRow).val(referenceModule);
 600              lineItemNameElment.val(selectedName);
 601              lineItemNameElment.attr('disabled', 'disabled');
 602              jQuery('input.listPrice',parentRow).val(unitPrice);
 603              var currencyId = jQuery("#currency_id").val();
 604              var listPriceValuesJson  = JSON.stringify(listPriceValues);
 605              if(typeof listPriceValues[currencyId]!= 'undefined') {
 606                  this.setListPriceValue(parentRow, listPriceValues[currencyId]);
 607                  this.lineItemRowCalculations(parentRow);
 608              }
 609              jQuery('input.listPrice',parentRow).attr('list-info',listPriceValuesJson);
 610              jQuery('textarea.lineItemCommentBox',parentRow).val(description);
 611              var taxUI = this.getTaxDiv(taxes,parentRow);
 612              jQuery('.taxDivContainer',parentRow).html(taxUI);
 613              if(this.isIndividualTaxMode()) {
 614                  parentRow.find('.productTaxTotal').removeClass('hide')
 615              }else{
 616                  parentRow.find('.productTaxTotal').addClass('hide')
 617              }
 618          }
 619          if(referenceModule == 'Products'){
 620              this.loadSubProducts(parentRow);
 621          }
 622  
 623          jQuery('.qty',parentRow).trigger('focusout');
 624      },
 625  
 626      showPopup : function(params) {
 627          var aDeferred = jQuery.Deferred();
 628          var popupInstance = Vtiger_Popup_Js.getInstance();
 629          popupInstance.show(params, function(data){
 630              aDeferred.resolve(data);
 631          });
 632          return aDeferred.promise();
 633      },
 634  
 635      /*
 636       * Function which is reposible to handle the line item popups
 637       * @params : popupImageElement - popup image element
 638       */
 639      lineItemPopupEventHandler : function(popupImageElement) {
 640          var aDeferred = jQuery.Deferred();
 641          var thisInstance = this;
 642          var referenceModule = popupImageElement.data('moduleName');
 643          var moduleName = app.getModuleName();
 644          //thisInstance.getModulePopUp(e,referenceModule);
 645          var params = {};
 646          params.view = popupImageElement.data('popup');
 647          params.module = moduleName;
 648          params.multi_select = true;
 649          params.currency_id = jQuery('#currency_id option:selected').val();
 650  
 651          this.showPopup(params).then(function(data){
 652              var responseData = JSON.parse(data);
 653              var len = Object.keys(responseData).length;
 654              if(len >1 ){
 655                  for(var i=0;i<len;i++){
 656                      if(i == 0){
 657                          thisInstance.mapResultsToFields(referenceModule,popupImageElement,responseData[i]);
 658                      }else if(i >= 1 && (referenceModule == 'Products' || referenceModule == 'Services')){
 659                          if(referenceModule == 'Products') {
 660                              var row = jQuery('#addProduct').trigger('click');
 661                          } else if(referenceModule == 'Services') {
 662                              var row1 = jQuery('#addService').trigger('click');
 663                          }
 664                          //TODO : CLEAN :  we might synchronus invocation since following elements needs to executed once new row is created
 665                          var newRow = jQuery('#lineItemTab > tbody > tr:last');
 666                          var targetElem = jQuery('.lineItemPopup',newRow);
 667                          thisInstance.mapResultsToFields(referenceModule,targetElem,responseData[i]);
 668                          aDeferred.resolve();
 669                      }
 670                  }
 671              }else{
 672                  thisInstance.mapResultsToFields(referenceModule,popupImageElement,responseData);
 673                  aDeferred.resolve();
 674              }
 675          })
 676          return aDeferred.promise();
 677      },
 678  
 679      /**
 680       * Function which will be used to handle price book popup
 681       * @params :  popupImageElement - popup image element
 682       */
 683      pricebooksPopupHandler : function(popupImageElement){
 684          var thisInstance = this;
 685          var lineItemRow  = popupImageElement.closest('tr.'+ this.rowClass);
 686          var lineItemProductOrServiceElement = lineItemRow.find('input.productName').closest('td');
 687          var params = {};
 688          params.module = 'PriceBooks';
 689          params.src_module = jQuery('img.lineItemPopup',lineItemProductOrServiceElement).data('moduleName');
 690          params.src_field = jQuery('img.lineItemPopup',lineItemProductOrServiceElement).data('fieldName');
 691          params.src_record = jQuery('input.selectedModuleId',lineItemProductOrServiceElement).val();
 692          params.get_url = 'getProductListPriceURL';
 693          params.currency_id = jQuery('#currency_id option:selected').val();
 694          this.showPopup(params).then(function(data){
 695              var responseData = JSON.parse(data);
 696              for(var id in responseData){
 697                  thisInstance.setListPriceValue(lineItemRow,responseData[id]);
 698              }
 699              thisInstance.quantityChangeActions(lineItemRow);
 700          });
 701      },
 702  
 703      /**
 704       * Function which will calculate line item total excluding discount and tax
 705       * @params : lineItemRow - element which will represent lineItemRow
 706       */
 707      calculateLineItemTotal : function (lineItemRow) {
 708          var quantity = this.getQuantityValue(lineItemRow);
 709          var listPrice = this.getListPriceValue(lineItemRow);
 710          var lineItemTotal = parseFloat(quantity) * parseFloat(listPrice);
 711          this.setLineItemTotal(lineItemRow,lineItemTotal);
 712      },
 713  
 714      /**
 715       * Function which will calculate discount for the line item
 716       * @params : lineItemRow - element which will represent lineItemRow
 717       */
 718      calculateDiscountForLineItem : function(lineItemRow) {
 719          var discountContianer = lineItemRow.find('div.discountUI');
 720          var element = discountContianer.find('input.discounts').filter(':checked');
 721          var discountType = element.data('discountType');
 722          var discountRow = element.closest('tr');
 723  
 724          jQuery('input.discount_type',discountContianer).val(discountType);
 725          var rowPercentageField = jQuery('input.discount_percentage',discountContianer);
 726          var rowAmountField = jQuery('input.discount_amount',discountContianer);
 727  
 728          //intially making percentage and amount discount fields as hidden
 729          rowPercentageField.addClass('hide');
 730          rowAmountField.addClass('hide');
 731  
 732          var discountValue = discountRow.find('.discountVal').val();
 733          if(discountValue == ""){
 734              discountValue = 0;
 735          }
 736          if(isNaN(discountValue) ||  discountValue < 0){
 737             discountValue = 0;
 738          }
 739          if(discountType == Inventory_Edit_Js.percentageDiscountType){
 740                  rowPercentageField.removeClass('hide').focus();
 741                  //since it is percentage
 742                  var productTotal = this.getLineItemTotal(lineItemRow);
 743                  discountValue = (productTotal * discountValue)/100;
 744          }else if(discountType == Inventory_Edit_Js.directAmountDiscountType){
 745                  rowAmountField.removeClass('hide').focus();
 746          }
 747          this.setDiscountTotal(lineItemRow,discountValue)
 748              .calculateTotalAfterDiscount(lineItemRow);
 749      },
 750  
 751      /**
 752       * Function which will calculate line item total after discount
 753       * @params : lineItemRow - element which will represent lineItemRow
 754       */
 755      calculateTotalAfterDiscount: function(lineItemRow) {
 756          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 757          var productTotal = this.getLineItemTotal(lineItemRow);
 758          var discountTotal = this.getDiscountTotal(lineItemRow);
 759          var totalAfterDiscount = productTotal - discountTotal;
 760          totalAfterDiscount = totalAfterDiscount.toFixed(numberOfDecimal);
 761          this.setTotalAfterDiscount(lineItemRow,totalAfterDiscount);
 762      },
 763  
 764      /**
 765       * Function which will calculate tax for the line item total after discount
 766       */
 767      calculateTaxForLineItem : function(lineItemRow) {
 768          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 769          var totalAfterDiscount = this.getTotalAfterDiscount(lineItemRow);
 770          var taxPercentages = jQuery('.taxPercentage',lineItemRow);
 771          //intially make the tax as zero
 772          var taxTotal = 0;
 773          jQuery.each(taxPercentages,function(index,domElement){
 774              var taxPercentage = jQuery(domElement);
 775              var individualTaxRow = taxPercentage.closest('tr');
 776              var individualTaxPercentage = taxPercentage.val();
 777              if(individualTaxPercentage == ""){
 778                  individualTaxPercentage = "0.00";
 779              }
 780               if(isNaN(individualTaxPercentage)){
 781                  var individualTaxTotal = "0.00";
 782              } else {
 783                  var individualTaxPercentage = parseFloat(individualTaxPercentage);
 784                  var individualTaxTotal = Math.abs(individualTaxPercentage * totalAfterDiscount)/100;
 785                  individualTaxTotal = individualTaxTotal.toFixed(numberOfDecimal);
 786              }
 787              jQuery('.taxTotal',individualTaxRow).val(individualTaxTotal);
 788              taxTotal += parseFloat(individualTaxTotal);
 789          });
 790          taxTotal = parseFloat(taxTotal.toFixed(numberOfDecimal));
 791          this.setLineItemTaxTotal(lineItemRow, taxTotal);
 792      },
 793  
 794      /**
 795       * Function which will calculate net price for the line item
 796       */
 797      calculateLineItemNetPrice : function(lineItemRow) {
 798          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 799          var totalAfterDiscount = this.getTotalAfterDiscount(lineItemRow);
 800          var netPrice = parseFloat(totalAfterDiscount);
 801          if(this.isIndividualTaxMode()) {
 802              var productTaxTotal = this.getLineItemTaxTotal(lineItemRow);
 803              netPrice +=  parseFloat(productTaxTotal)
 804          }
 805          netPrice = netPrice.toFixed(numberOfDecimal);
 806          this.setLineItemNetPrice(lineItemRow,netPrice);
 807      },
 808  
 809      /**
 810       * Function which will caliculate the total net price for all the line items
 811       */
 812      calculateNetTotal : function() {
 813          var thisInstance = this
 814          var lineItemTable = this.getLineItemContentsContainer();
 815          var netTotalValue = 0;
 816          lineItemTable.find('tr.'+this.rowClass).each(function(index,domElement){
 817              var lineItemRow = jQuery(domElement);
 818              netTotalValue += thisInstance.getLineItemNetPrice(lineItemRow);
 819          });
 820          this.setNetTotal(netTotalValue);
 821      },
 822  
 823      calculateFinalDiscount : function() {
 824          var thisInstance = this;
 825          var discountContainer = jQuery('#finalDiscountUI');
 826          var element = discountContainer.find('input.finalDiscounts').filter(':checked');
 827          var discountType = element.data('discountType');
 828          var discountRow = element.closest('tr');
 829          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 830  
 831          jQuery('#discount_type_final').val(discountType);
 832          var rowPercentageField = discountContainer.find('input.discount_percentage_final');
 833          var rowAmountField = discountContainer.find('input.discount_amount_final');
 834          
 835          //intially making percentage and amount discount fields as hidden
 836          rowPercentageField.addClass('hide');
 837          rowAmountField.addClass('hide');
 838  
 839          var discountValue = discountRow.find('.discountVal').val();
 840          if(discountValue == ""){
 841              discountValue = 0;
 842          }
 843          if(isNaN(discountValue) ||  discountValue < 0){
 844             discountValue = 0;
 845          }
 846          if(discountType == Inventory_Edit_Js.percentageDiscountType){
 847              rowPercentageField.removeClass('hide').focus();
 848              //since it is percentage
 849              var productTotal = this.getNetTotal();
 850              discountValue = (productTotal * discountValue)/100;
 851          }else if(discountType == Inventory_Edit_Js.directAmountDiscountType){
 852              if(thisInstance.prevSelectedCurrencyConversionRate){
 853                  var conversionRate = jQuery('#conversion_rate').val();
 854                  conversionRate = conversionRate / thisInstance.prevSelectedCurrencyConversionRate;  
 855                  discountValue = discountValue * conversionRate;
 856                  discountRow.find('.discountVal').val(discountValue);
 857              }
 858              rowAmountField.removeClass('hide').focus();
 859          }
 860          discountValue = parseFloat(discountValue).toFixed(numberOfDecimal);
 861          this.setFinalDiscountTotal(discountValue);
 862          this.calculatePreTaxTotal();
 863      },
 864  
 865      calculateGroupTax : function() {
 866          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 867          var netTotal = this.getNetTotal();
 868          var finalDiscountValue = this.getFinalDiscountTotal();
 869          var amount = netTotal - finalDiscountValue;
 870          amount = parseFloat(amount).toFixed(numberOfDecimal);
 871          var groupTaxContainer = jQuery('#group_tax_div');
 872          var groupTaxTotal = 0;
 873          groupTaxContainer.find('.groupTaxPercentage').each(function(index,domElement){
 874              var groupTaxPercentageElement = jQuery(domElement);
 875              var groupTaxRow = groupTaxPercentageElement.closest('tr');
 876              if(isNaN(groupTaxPercentageElement.val())){
 877                  var groupTaxValue = "0.00";
 878              } else {
 879                  var groupTaxValue = Math.abs(amount * groupTaxPercentageElement.val())/100;
 880              }
 881              groupTaxValue = parseFloat(groupTaxValue).toFixed(numberOfDecimal);
 882              groupTaxRow.find('.groupTaxTotal').val(groupTaxValue);
 883              groupTaxTotal += parseFloat(groupTaxValue);
 884          });
 885          this.setGroupTaxTotal(groupTaxTotal);
 886      },
 887  
 888      calculateShippingAndHandlingTaxCharges : function() {
 889          var shippingHandlingCharge = this.getShippingAndHandling();
 890          var shippingTaxDiv = jQuery('#shipping_handling_div');
 891          var shippingTaxPercentage = shippingTaxDiv.find('.shippingTaxPercentage');
 892  
 893          jQuery.each(shippingTaxPercentage,function(index,domElement){
 894              var currentTaxPer = jQuery(domElement);
 895              var currentParentRow = currentTaxPer.closest('tr');
 896              var currentTaxPerValue = currentTaxPer.val();
 897              var currentTaxTotal = "0.00";
 898              if(currentTaxPerValue == ""){
 899                  currentTaxPerValue = "0.00";
 900              }
 901               if(isNaN(currentTaxPerValue)){
 902                  var currentTaxTotal = "0.00";
 903              } else {
 904                  currentTaxPerValue = parseFloat(currentTaxPerValue);
 905                  var currentTaxTotal = Math.abs(currentTaxPerValue * shippingHandlingCharge)/100;
 906              }
 907              jQuery('.shippingTaxTotal',currentParentRow).val(currentTaxTotal);
 908          });
 909      },
 910  
 911      calculateGrandTotal : function(){
 912          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
 913          var netTotal = this.getNetTotal();
 914          var discountTotal = this.getFinalDiscountTotal();
 915          var shippingHandlingCharge = this.getShippingAndHandling();
 916          var shippingHandlingTax = this.getShippingAndHandlingTaxTotal();
 917          var adjustment = this.getAdjustmentValue();
 918          var grandTotal = parseFloat(netTotal) - parseFloat(discountTotal) + parseFloat(shippingHandlingCharge) + parseFloat(shippingHandlingTax);
 919  
 920          if(this.isGroupTaxMode()){
 921              grandTotal +=  this.getGroupTaxTotal();
 922          }
 923  
 924          if(this.isAdjustMentAddType()) {
 925              grandTotal +=  parseFloat(adjustment);
 926          }else if(this.isAdjustMentDeductType()) {
 927              grandTotal -=  parseFloat(adjustment);
 928          }
 929  
 930          grandTotal = grandTotal.toFixed(numberOfDecimal);
 931          this.setGrandTotal(grandTotal);
 932      },
 933  
 934      registerFinalDiscountShowEvent : function(){
 935          var thisInstance = this;
 936          jQuery('#finalDiscount').on('click',function(e){
 937              var finalDiscountUI = jQuery('#finalDiscountUI');
 938              thisInstance.hideLineItemPopup();
 939              finalDiscountUI.removeClass('hide');
 940          });
 941      },
 942  
 943      registerFinalDiscountChangeEvent : function() {
 944          var lineItemResultTab = this.getLineItemResultContainer();
 945          var thisInstance = this;
 946  
 947          lineItemResultTab.on('change','.finalDiscounts',function(e){
 948              thisInstance.finalDiscountChangeActions();
 949          });
 950      },
 951  
 952      registerFinalDiscountValueChangeEvent : function(){
 953          var thisInstance = this;
 954          jQuery('.finalDiscountSave').on('click',function(e){
 955              thisInstance.finalDiscountChangeActions();
 956          });
 957      },
 958  
 959      registerLineItemActionSaveEvent : function(){
 960          var editForm =  this.getForm();
 961          editForm.on('click','button[name="lineItemActionSave"]',function(){
 962              var match = true;
 963              var formError = jQuery('#EditView').data('jqv').InvalidFields;
 964              var closestDiv = jQuery('button[name="lineItemActionSave"]').closest('.validCheck').find('input[data-validation-engine]').not('.hide');
 965              jQuery(closestDiv).each(function(key,value){
 966                  if(jQuery.inArray(value,formError) != -1){
 967                      match = false;
 968                  }
 969              });
 970              if(!match){
 971                  editForm.removeData('submit');
 972                  return false;
 973              } else {
 974                  jQuery('.closeDiv').trigger('click');
 975              }
 976          });
 977      },
 978  
 979      registerGroupTaxShowEvent : function() {
 980          var thisInstance = this;
 981          jQuery('#finalTax').on('click',function(e){
 982              var groupTaxContainer = jQuery('#group_tax_row');
 983              thisInstance.hideLineItemPopup();
 984              groupTaxContainer.find('.finalTaxUI').removeClass('hide');
 985          });
 986      },
 987  
 988      registerGroupTaxChangeEvent : function() {
 989          var thisInstance = this;
 990          var groupTaxContainer = jQuery('#group_tax_row');
 991  
 992          groupTaxContainer.on('focusout','.groupTaxPercentage',function(e){
 993              thisInstance.calculateGroupTax();
 994              thisInstance.calculateGrandTotal();
 995          });
 996      },
 997  
 998      registerShippingAndHandlingChargesChange : function(){
 999          var thisInstance = this;
1000          this.getShippingAndHandlingControlElement().on('focusout', function(e){
1001              var value = jQuery(e.currentTarget).val();
1002              if(value == ""){
1003                  jQuery(e.currentTarget).val("0.00");
1004              }
1005              thisInstance.shippingAndHandlingChargesChangeActions();
1006          });
1007          jQuery('.shippingTaxPercentage').on('change',function(){
1008              thisInstance.shippingAndHandlingChargesChangeActions();
1009          })
1010          jQuery('.finalTaxSave').on('click',function(){
1011              thisInstance.setShippingAndHandlingTaxTotal();
1012          })
1013      },
1014  
1015      registerShippingAndHandlingTaxShowEvent : function(){
1016          var thisInstance = this;
1017          jQuery('#shippingHandlingTax').on('click',function(e){
1018              var finalShippingHandlingDiv = jQuery('#shipping_handling_div');
1019              thisInstance.hideLineItemPopup();
1020              finalShippingHandlingDiv.removeClass('hide');
1021          });
1022      },
1023  
1024      registerAdjustmentTypeChange : function() {
1025          var thisInstance = this;
1026          this.getAdjustmentTypeElement().on('change', function(e){
1027              thisInstance.calculateGrandTotal();
1028          });
1029      },
1030  
1031      registerAdjustmentValueChange : function() {
1032          var thisInstance = this;
1033          this.getAdjustmentTextElement().on('focusout',function(e){
1034              var value = jQuery(e.currentTarget).val();
1035              if(value == ""){
1036                  jQuery(e.currentTarget).val("0.00");
1037              }
1038              thisInstance.calculateGrandTotal();
1039          });
1040      },
1041  
1042  
1043      registerLineItemsPopUpCancelClickEvent : function(){
1044          var editForm = this.getForm();
1045          editForm.on('click','.cancelLink',function(){
1046              jQuery('.closeDiv').trigger('click')
1047          })
1048      },
1049  
1050      lineItemResultActions: function(){
1051          var thisInstance = this;
1052          var lineItemResultTab = this.getLineItemResultContainer();
1053  
1054          this.registerFinalDiscountShowEvent();
1055          this.registerFinalDiscountValueChangeEvent();
1056          this.registerFinalDiscountChangeEvent();
1057  
1058          this.registerLineItemActionSaveEvent();
1059          this.registerLineItemsPopUpCancelClickEvent();
1060  
1061          this.registerGroupTaxShowEvent();
1062          this.registerGroupTaxChangeEvent();
1063  
1064          this.registerShippingAndHandlingChargesChange();
1065          this.registerShippingAndHandlingTaxShowEvent();
1066  
1067          this.registerAdjustmentTypeChange();
1068          this.registerAdjustmentValueChange();
1069  
1070          lineItemResultTab.on('click','.closeDiv',function(e){
1071              jQuery(e.target).closest('div').addClass('hide');
1072          });
1073      },
1074  
1075  
1076      lineItemRowCalculations : function(lineItemRow) {
1077          this.calculateLineItemTotal(lineItemRow);
1078          this.calculateDiscountForLineItem(lineItemRow);
1079          this.calculateTaxForLineItem(lineItemRow);
1080          this.calculateLineItemNetPrice(lineItemRow);
1081      },
1082  
1083      lineItemToTalResultCalculations : function(){
1084          this.calculateNetTotal();
1085          this.calculateFinalDiscount();
1086          if(this.isGroupTaxMode()){
1087              this.calculateGroupTax();
1088          }
1089          //this.calculateShippingAndHandlingTaxCharges();
1090          this.calculateGrandTotal();
1091      },
1092  
1093      /**
1094       * Function which will handle the actions that need to be preformed once the qty is changed like below
1095       *  - calculate line item total -> discount and tax -> net price of line item -> grand total
1096       * @params : lineItemRow - element which will represent lineItemRow
1097       */
1098      quantityChangeActions : function(lineItemRow) {
1099          this.lineItemRowCalculations(lineItemRow);
1100          this.lineItemToTalResultCalculations();
1101      },
1102  
1103      lineItemDiscountChangeActions : function(lineItemRow){
1104          this.calculateDiscountForLineItem(lineItemRow);
1105          this.calculateTaxForLineItem(lineItemRow);
1106          this.calculateLineItemNetPrice(lineItemRow);
1107  
1108          this.lineItemToTalResultCalculations();
1109      },
1110  
1111  
1112      /**
1113       * Function which will handle the actions that need to be performed once the tax percentage is change for a line item
1114       * @params : lineItemRow - element which will represent lineItemRow
1115       */
1116  
1117      taxPercentageChangeActions : function(lineItemRow){
1118          this.calculateLineItemNetPrice(lineItemRow);
1119          this.calculateNetTotal();
1120          this.calculateFinalDiscount();
1121          if(this.isGroupTaxMode()){
1122              this.calculateGroupTax();
1123          }
1124          //this.calculateShippingAndHandlingTaxCharges();
1125          this.calculateGrandTotal();
1126      },
1127  
1128      lineItemDeleteActions : function() {
1129          this.lineItemToTalResultCalculations();
1130      },
1131  
1132      shippingAndHandlingChargesChangeActions : function(){
1133          this.calculateShippingAndHandlingTaxCharges();
1134          this.setShippingAndHandlingTaxTotal();
1135          this.calculatePreTaxTotal();
1136          this.calculateGrandTotal();
1137      },
1138  
1139      finalDiscountChangeActions : function() {
1140          this.calculateFinalDiscount();
1141          if(this.isGroupTaxMode()){
1142              this.calculateGroupTax();
1143          }
1144          this.calculateGrandTotal();
1145      },
1146  
1147      /**
1148       * Function which will register change event for discounts radio buttons
1149       */
1150      registerDisountChangeEvent : function() {
1151          var thisInstance = this;
1152          var lineItemTable = this.getLineItemContentsContainer();
1153          lineItemTable.on('change','.discounts',function(e){
1154              var lineItemRow = jQuery(e.currentTarget).closest('tr.'+thisInstance.rowClass);
1155              thisInstance.lineItemDiscountChangeActions(lineItemRow);
1156          });
1157      },
1158  
1159      /**
1160       * Function which will register event for focusout of discount input fields like percentage and amount
1161       */
1162      registerDisountValueChange : function() {
1163          var thisInstance = this;
1164          var lineItemTable = this.getLineItemContentsContainer();
1165          lineItemTable.on('click','.discountSave', function(e){
1166              var element = jQuery(e.currentTarget);
1167              //if the element is not hidden then we need to handle the focus out
1168              if(!app.isHidden(element)){
1169                  var lineItemRow = jQuery(e.currentTarget).closest('tr.'+thisInstance.rowClass);
1170                  thisInstance.lineItemDiscountChangeActions(lineItemRow);
1171              }
1172  
1173          });
1174      },
1175  
1176      hideLineItemPopup : function(){
1177          var editForm = this.getForm();
1178          var popUpElementContainer = jQuery('.popupTable',editForm).closest('div');
1179          if(popUpElementContainer.length > 0){
1180              popUpElementContainer.addClass('hide');
1181          }
1182      },
1183  
1184      registerLineItemDiscountShowEvent : function() {
1185          var thisInstance = this;
1186          var lineItemTable = this.getLineItemContentsContainer();
1187  
1188          lineItemTable.on('click','.individualDiscount',function(e){
1189              var element = jQuery(e.currentTarget);
1190              var response = thisInstance.isProductSelected(element);
1191              if(response == true){
1192                  return;
1193              }
1194              var parentElem = jQuery(e.currentTarget).closest('td');
1195              thisInstance.hideLineItemPopup();
1196              parentElem.find('div.discountUI').removeClass('hide');
1197          });
1198      },
1199  
1200      /**
1201       * Function which will regiser events for product and service popup
1202       */
1203      registerProductAndServicePopup : function() {
1204          var thisInstance = this;
1205          var lineItemTable = this.getLineItemContentsContainer();
1206          lineItemTable.on('click','img.lineItemPopup', function(e){
1207              var element = jQuery(e.currentTarget);
1208              thisInstance.lineItemPopupEventHandler(element).then(function(data){
1209                  var parent = element.closest('tr');
1210                  var deletedItemInfo = parent.find('.deletedItem');
1211                  if(deletedItemInfo.length > 0){
1212                      deletedItemInfo.remove();
1213                  }
1214              })
1215          });
1216      },
1217  
1218      /**
1219       * Function which will regisrer price book popup
1220       */
1221       registerPriceBookPopUp : function () {
1222          var thisInstance = this;
1223          var lineItemTable = this.getLineItemContentsContainer();
1224  
1225          lineItemTable.on('click','.priceBookPopup',function(e){
1226              var element = jQuery(e.currentTarget);
1227              var response = thisInstance.isProductSelected(element);
1228              if(response == true){
1229                  return;
1230              }
1231              thisInstance.pricebooksPopupHandler(element);
1232          });
1233       },
1234  
1235       /*
1236        * Function which will register event for quantity change (focusout event)
1237        */
1238       registerQuantityChangeEventHandler : function() {
1239          var thisInstance = this;
1240          var lineItemTable = this.getLineItemContentsContainer();
1241  
1242          lineItemTable.on('focusout','.qty',function(e){
1243              var element = jQuery(e.currentTarget);
1244              var lineItemRow = element.closest('tr.'+thisInstance.rowClass);
1245              var quantityInStock = lineItemRow.data('quantityInStock');
1246              if(typeof quantityInStock  != 'undefined') {
1247                  if(parseFloat(element.val()) > parseFloat(quantityInStock)) {
1248                      lineItemRow.find('.stockAlert').removeClass('hide').find('.maxQuantity').text(quantityInStock);
1249                  }else{
1250                      lineItemRow.find('.stockAlert').addClass('hide');
1251                  }
1252              }
1253              thisInstance.quantityChangeActions(lineItemRow);
1254          });
1255       },
1256  
1257       /**
1258        * Function which will register event for list price event change
1259        */
1260       registerListPriceChangeEvent : function() {
1261          var thisInstance = this;
1262          var lineItemTable = this.getLineItemContentsContainer();
1263  
1264          lineItemTable.on('focusout', 'input.listPrice',function(e){
1265              var element = jQuery(e.currentTarget);
1266              var lineItemRow = thisInstance.getClosestLineItemRow(element);
1267              thisInstance.quantityChangeActions(lineItemRow);
1268          });
1269       },
1270  
1271       registerTaxPercentageChange : function() {
1272          var thisInstance = this;
1273          var lineItemTable = this.getLineItemContentsContainer();
1274  
1275          lineItemTable.on('focusout','.taxPercentage',function(e){
1276              var element = jQuery(e.currentTarget);
1277              var lineItemRow = thisInstance.getClosestLineItemRow(element);
1278              thisInstance.calculateTaxForLineItem(lineItemRow);
1279          });
1280  
1281          lineItemTable.on('click','.taxSave',function(e){
1282              var element = jQuery(e.currentTarget);
1283              var lineItemRow = thisInstance.getClosestLineItemRow(element);
1284              thisInstance.taxPercentageChangeActions(lineItemRow);
1285          });
1286       },
1287  
1288       isProductSelected : function(element){
1289          var parentRow = element.closest('tr');
1290          var productField = parentRow.find('.productName');
1291          var response = productField.validationEngine('validate');
1292          return response;
1293       },
1294  
1295       registerLineItemTaxShowEvent : function() {
1296          var thisInstance = this;
1297          var lineItemTable = this.getLineItemContentsContainer();
1298  
1299          lineItemTable.on('click','.individualTax',function(e){
1300              var element = jQuery(e.currentTarget);
1301              var response = thisInstance.isProductSelected(element);
1302              if(response == true){
1303                  return;
1304              }
1305              var parentElem = jQuery(e.currentTarget).closest('td');
1306              thisInstance.hideLineItemPopup()
1307              parentElem.find('.taxUI').removeClass('hide');
1308          });
1309       },
1310  
1311       registerDeleteLineItemEvent : function(){
1312          var thisInstance = this;
1313          var lineItemTable = this.getLineItemContentsContainer();
1314  
1315          lineItemTable.on('click','.deleteRow',function(e){
1316              var element = jQuery(e.currentTarget);
1317              //removing the row
1318              element.closest('tr.'+ thisInstance.rowClass).remove();
1319              thisInstance.checkLineItemRow();
1320              thisInstance.lineItemDeleteActions();
1321          });
1322       },
1323  
1324       registerTaxTypeChange : function() {
1325          var thisInstance = this;
1326          var lineItemTable = this.getLineItemContentsContainer();
1327  
1328          this.getTaxTypeSelectElement().on('change', function(e){
1329              if(thisInstance.isIndividualTaxMode()) {
1330                  jQuery('#group_tax_row').addClass('hide');
1331                  lineItemTable.find('tr.'+thisInstance.rowClass).each(function(index,domElement){
1332                      var lineItemRow = jQuery(domElement);
1333                      lineItemRow.find('.individualTaxContainer,.productTaxTotal').removeClass('hide');
1334                      thisInstance.lineItemRowCalculations(lineItemRow);
1335                  });
1336              }else{
1337                  jQuery('#group_tax_row').removeClass('hide');
1338                  lineItemTable.find('tr.'+thisInstance.rowClass).each(function(index,domElement){
1339                      var lineItemRow = jQuery(domElement);
1340                      lineItemRow.find('.individualTaxContainer,.productTaxTotal').addClass('hide');
1341                      thisInstance.calculateLineItemNetPrice(lineItemRow);
1342                  });
1343              }
1344              thisInstance.lineItemToTalResultCalculations();
1345          });
1346       },
1347  
1348       registerCurrencyChangeEvent : function() {
1349          var thisInstance = this;
1350          jQuery('#currency_id').change(function(e){
1351              var element = jQuery(e.currentTarget);
1352              var currencyId = element.val();
1353              var conversionRateElem = jQuery('#conversion_rate');
1354              var prevSelectedCurrencyConversionRate = conversionRateElem.val();
1355              thisInstance.prevSelectedCurrencyConversionRate = prevSelectedCurrencyConversionRate;
1356              var optionsSelected = element.find('option:selected');
1357              var conversionRate = optionsSelected.data('conversionRate');
1358              conversionRateElem.val(conversionRate);
1359              conversionRate = parseFloat(conversionRate)/ parseFloat(prevSelectedCurrencyConversionRate);
1360              thisInstance.LineItemDirectDiscountCal(conversionRate);
1361              var lineItemTable = thisInstance.getLineItemContentsContainer();
1362              lineItemTable.find('tr.'+thisInstance.rowClass).each(function(index,domElement){
1363              var lineItemRow = jQuery(domElement);
1364              var listPriceElement = jQuery(lineItemRow).find('[name^=listPrice]');
1365              var listPriceValues = JSON.parse(listPriceElement.attr('list-info'));
1366              if(typeof listPriceValues[currencyId]!= 'undefined') {
1367                  thisInstance.setListPriceValue(lineItemRow, listPriceValues[currencyId]);
1368                  thisInstance.lineItemRowCalculations(lineItemRow);
1369              } else {
1370                  var listPriceVal = thisInstance.getListPriceValue(lineItemRow);
1371                  var convertedListPrice = listPriceVal * conversionRate;
1372                  thisInstance.setListPriceValue(lineItemRow, convertedListPrice);
1373                  thisInstance.lineItemRowCalculations(lineItemRow);
1374              }
1375  
1376              });
1377              thisInstance.AdjustmentShippingResultCalculation(conversionRate);
1378              thisInstance.lineItemToTalResultCalculations();
1379              jQuery('#prev_selected_currency_id').val(optionsSelected.val())
1380          });
1381       },
1382       
1383       AdjustmentShippingResultCalculation: function(conversionRate){
1384           //Adjustment
1385           var thisInstance = this;
1386           var adjustmentElement = thisInstance.getAdjustmentTextElement();
1387           var newAdjustment = jQuery(adjustmentElement).val() * conversionRate;
1388           jQuery(adjustmentElement).val(newAdjustment);
1389           
1390           //Shipping & handling 
1391           var shippingHandlingElement = thisInstance.getShippingAndHandlingControlElement();
1392           var resultVal = jQuery(shippingHandlingElement).val() * conversionRate;
1393           jQuery(shippingHandlingElement).val(resultVal);
1394           jQuery(shippingHandlingElement).trigger('focusout');
1395      }, 
1396      
1397      LineItemDirectDiscountCal: function(conversionRate){
1398           //LineItems Discount Calculations for direct Price reduction
1399          var thisInstance = this;
1400  
1401          var lineItemRows = jQuery('.lineItemRow');
1402          jQuery(lineItemRows).each(function(index) {
1403              var lineItemRow = jQuery(lineItemRows[index]);
1404              var discountContianer = lineItemRow.find('div.discountUI');
1405              var element = discountContianer.find('input.discounts').filter(':checked');
1406              var discountRow = element.closest('tr');
1407              var discountType = element.data('discountType');
1408              var discountValue = discountRow.find('.discountVal').val();
1409              if((discountType == Inventory_Edit_Js.directAmountDiscountType) ){
1410                  var newdiscountValue = conversionRate * discountValue;
1411                  discountRow.find('.discountVal').val(newdiscountValue);
1412                  jQuery(element).closest('tr').find('.discountVal').val(newdiscountValue);
1413                  thisInstance.setDiscountTotal(lineItemRow,newdiscountValue);
1414              }
1415          });
1416      },
1417       
1418      lineItemActions: function() {
1419          var lineItemTable = this.getLineItemContentsContainer();
1420  
1421          this.registerDisountChangeEvent();
1422          this.registerDisountValueChange();
1423          this.registerLineItemDiscountShowEvent();
1424  
1425          this.registerLineItemAutoComplete();
1426          this.registerClearLineItemSelection();
1427  
1428          this.registerProductAndServicePopup();
1429          this.registerPriceBookPopUp();
1430  
1431          this.registerQuantityChangeEventHandler();
1432          this.registerListPriceChangeEvent();
1433  
1434          this.registerTaxPercentageChange();
1435          this.registerLineItemTaxShowEvent();
1436  
1437          this.registerDeleteLineItemEvent();
1438          this.registerTaxTypeChange();
1439          this.registerCurrencyChangeEvent();
1440  
1441  
1442  
1443          lineItemTable.on('click','.closeDiv',function(e){
1444              jQuery(e.currentTarget).closest('div').addClass('hide');
1445          });
1446  
1447          lineItemTable.on('click','.clearComment',function(e){
1448              var elem = jQuery(e.currentTarget);
1449              var parentElem = elem.closest('div');
1450              var comment = jQuery('.lineItemCommentBox',parentElem).val('');
1451          });
1452  
1453      },
1454  
1455      /***
1456       * Function which will update the line item row elements with the sequence number
1457       * @params : lineItemRow - tr line item row for which the sequence need to be updated
1458       *             currentSequenceNUmber - existing sequence number that the elments is having
1459       *             expectedSequenceNumber - sequence number to which it has to update
1460       *
1461       * @return : row element after changes
1462       */
1463      updateLineItemsElementWithSequenceNumber : function(lineItemRow,expectedSequenceNumber , currentSequenceNumber){
1464          if(typeof currentSequenceNumber == 'undefined') {
1465              //by default there will zero current sequence number
1466              currentSequenceNumber = 0;
1467          }
1468  
1469          var idFields = new Array('productName','subproduct_ids','hdnProductId',
1470                                 'comment','qty','listPrice','discount_type','discount_percentage',
1471                                 'discount_amount','lineItemType','searchIcon','netPrice','subprod_names',
1472                                  'productTotal','discountTotal','totalAfterDiscount','taxTotal');
1473  
1474          var nameFields = new Array('discount');
1475          var classFields = new Array('taxPercentage');
1476          //To handle variable tax ids
1477          for(var classIndex in classFields) {
1478              var className = classFields[classIndex];
1479              jQuery('.'+className,lineItemRow).each(function(index, domElement){
1480                  var idString = domElement.id
1481                  //remove last character which will be the row number
1482                  idFields.push(idString.slice(0,(idString.length-1)));
1483              });
1484          }
1485  
1486          var expectedRowId = 'row'+expectedSequenceNumber;
1487          for(var idIndex in idFields ) {
1488              var elementId = idFields[idIndex];
1489              var actualElementId = elementId + currentSequenceNumber;
1490              var expectedElementId = elementId + expectedSequenceNumber;
1491              lineItemRow.find('#'+actualElementId).attr('id',expectedElementId)
1492                         .filter('[name="'+actualElementId+'"]').attr('name',expectedElementId);
1493          }
1494  
1495          for(var nameIndex in nameFields) {
1496              var elementName = nameFields[nameIndex];
1497              var actualElementName = elementName + currentSequenceNumber;
1498              var expectedElementName = elementName + expectedSequenceNumber;
1499              lineItemRow.find('[name="'+actualElementName+'"]').attr('name',expectedElementName);
1500          }
1501  
1502  
1503          return lineItemRow.attr('id',expectedRowId);
1504      },
1505  
1506  
1507      updateLineItemElementByOrder : function () {
1508          var lineItemContentsContainer  = this.getLineItemContentsContainer();
1509          var thisInstance = this;
1510          jQuery('tr.'+this.rowClass ,lineItemContentsContainer).each(function(index,domElement){
1511              var lineItemRow = jQuery(domElement);
1512              var expectedRowIndex = (index+1);
1513              var expectedRowId = 'row'+expectedRowIndex;
1514              var actualRowId = lineItemRow.attr('id');
1515              if(expectedRowId != actualRowId) {
1516                  var actualIdComponents = actualRowId.split('row');
1517                  thisInstance.updateLineItemsElementWithSequenceNumber(lineItemRow, expectedRowIndex, actualIdComponents[1]);
1518              }
1519          });
1520      },
1521  
1522      saveProductCount : function () {
1523          jQuery('#totalProductCount').val(jQuery('tr.'+this.rowClass, this.getLineItemContentsContainer()).length);
1524      },
1525  
1526      saveSubTotalValue : function() {
1527          jQuery('#subtotal').val(this.getNetTotal());
1528      },
1529  
1530      saveTotalValue : function() {
1531          jQuery('#total').val(this.getGrandTotal());
1532      },
1533  
1534      makeLineItemsSortable : function() {
1535          var thisInstance = this;
1536          var lineItemTable = this.getLineItemContentsContainer();
1537          lineItemTable.sortable({
1538              'containment' : lineItemTable,
1539              'items' : 'tr.'+this.rowClass,
1540              'revert' : true,
1541              'tolerance':'pointer',
1542              'helper' : function(e,ui){
1543                  //while dragging helper elements td element will take width as contents width
1544                  //so we are explicity saying that it has to be same width so that element will not
1545                  //look like distrubed
1546                  ui.children().each(function(index,element){
1547                      element = jQuery(element);
1548                      element.width(element.width());
1549                  })
1550                  return ui;
1551              }
1552          }).mousedown(function(event){
1553              //TODO : work around for issue of mouse down even hijack in sortable plugin
1554              thisInstance.getClosestLineItemRow(jQuery(event.target)).find('input:focus').trigger('focusout');
1555          });
1556      },
1557  
1558      registerSubmitEvent : function () {
1559          var thisInstance = this;
1560          var editViewForm = this.getForm();
1561          this._super();
1562          editViewForm.submit(function(e){
1563              var deletedItemInfo = jQuery('.deletedItem',editViewForm);
1564              if(deletedItemInfo.length > 0){
1565                  e.preventDefault();
1566                  var msg = app.vtranslate('JS_PLEASE_REMOVE_LINE_ITEM_THAT_IS_DELETED');
1567                  var params = {
1568                      text : msg,
1569                       type: 'error'
1570                  }
1571                  Vtiger_Helper_Js.showPnotify(params);
1572                  editViewForm.removeData('submit');
1573                  return false;
1574              }
1575              thisInstance.updateLineItemElementByOrder();
1576              var lineItemTable = thisInstance.getLineItemContentsContainer();
1577              jQuery('.discountSave',lineItemTable).trigger('click');
1578              thisInstance.lineItemToTalResultCalculations();
1579              thisInstance.saveProductCount();
1580              thisInstance.saveSubTotalValue();
1581              thisInstance.saveTotalValue();
1582              thisInstance.savePreTaxTotalValue();
1583          })
1584      },
1585  
1586      /**
1587       * Function which will register event for Reference Fields Selection
1588       */
1589      registerReferenceSelectionEvent : function(container) {
1590          var thisInstance = this;
1591  
1592          jQuery('input[name="contact_id"]', container).on(Vtiger_Edit_Js.referenceSelectionEvent, function(e, data){
1593              thisInstance.referenceSelectionEventHandler(data, container);
1594          });
1595      },
1596  
1597      /**
1598       * Reference Fields Selection Event Handler
1599       */
1600      referenceSelectionEventHandler : function(data,container){
1601          var thisInstance = this;
1602          var message = app.vtranslate('OVERWRITE_EXISTING_MSG1')+app.vtranslate('SINGLE_'+data['source_module'])+' ('+data['selectedName']+') '+app.vtranslate('OVERWRITE_EXISTING_MSG2');
1603          Vtiger_Helper_Js.showConfirmationBox({'message' : message}).then(
1604          function(e) {
1605              thisInstance.copyAddressDetails(data, container);
1606              },
1607          function(error, err){
1608          });
1609      },
1610  
1611      /**
1612       * Function which will copy the address details
1613       */
1614      copyAddressDetails : function(data,container,addressMap) {
1615          var thisInstance = this;
1616          var sourceModule = data['source_module'];
1617          var noAddress = true;
1618          var errorMsg;
1619  
1620          thisInstance.getRecordDetails(data).then(
1621              function(data){
1622                  var response = data['result'];
1623                  if(typeof addressMap != "undefined"){
1624                      var result = response['data'];
1625                      for(var key in addressMap) {
1626                          if(result[addressMap[key]] != ""){
1627                              noAddress = false;
1628                              break;
1629                          }
1630                      }
1631                      if(noAddress){
1632                          if(sourceModule == "Accounts"){
1633                              errorMsg = 'JS_SELECTED_ACCOUNT_DOES_NOT_HAVE_AN_ADDRESS';
1634                          } else if(sourceModule == "Contacts"){
1635                              errorMsg = 'JS_SELECTED_CONTACT_DOES_NOT_HAVE_AN_ADDRESS';
1636                          }
1637                          Vtiger_Helper_Js.showPnotify(app.vtranslate(errorMsg));
1638                      } else{
1639                          thisInstance.mapAddressDetails(addressMap, result, container);
1640                      }
1641                  } else{
1642                      thisInstance.mapAddressDetails(thisInstance.addressFieldsMapping[sourceModule], response['data'], container);
1643                      if(sourceModule == "Accounts"){
1644                          container.find('.accountAddress').attr('checked','checked');
1645                      }else if(sourceModule == "Contacts"){
1646                          container.find('.contactAddress').attr('checked','checked');
1647                      }
1648                  }
1649              },
1650              function(error, err){
1651  
1652              });
1653      },
1654  
1655      /**
1656       * Function which will copy the address details of the selected record
1657       */
1658      mapAddressDetails : function(addressDetails, result, container) {
1659          for(var key in addressDetails) {
1660              container.find('[name="'+key+'"]').val(result[addressDetails[key]]);
1661              container.find('[name="'+key+'"]').trigger('change');
1662          }
1663      },
1664  
1665      registerLineItemAutoComplete : function(container) {
1666          var thisInstance = this;
1667          if(typeof container == 'undefined') {
1668              container = thisInstance.getLineItemContentsContainer();
1669          }
1670          container.find('input.autoComplete').autocomplete({
1671              'minLength' : '3',
1672              'source' : function(request, response){
1673                  //element will be array of dom elements
1674                  //here this refers to auto complete instance
1675                  var inputElement = jQuery(this.element[0]);
1676                  var tdElement = inputElement.closest('td');
1677                  var searchValue = request.term;
1678                  var params = {};
1679                  var searchModule = tdElement.find('.lineItemPopup').data('moduleName');
1680                  params.search_module = searchModule
1681                  params.search_value = searchValue;
1682                  thisInstance.searchModuleNames(params).then(function(data){
1683                      var reponseDataList = new Array();
1684                      var serverDataFormat = data.result
1685                      if(serverDataFormat.length <= 0) {
1686                          serverDataFormat = new Array({
1687                              'label' : app.vtranslate('JS_NO_RESULTS_FOUND'),
1688                              'type'  : 'no results'
1689                          });
1690                      }
1691                      for(var id in serverDataFormat){
1692                          var responseData = serverDataFormat[id];
1693                          reponseDataList.push(responseData);
1694                      }
1695                      response(reponseDataList);
1696                  });
1697              },
1698              'select' : function(event, ui ){
1699                  var selectedItemData = ui.item;
1700                  //To stop selection if no results is selected
1701                  if(typeof selectedItemData.type != 'undefined' && selectedItemData.type=="no results"){
1702                      return false;
1703                  }
1704                  var element = jQuery(this);
1705                  element.attr('disabled','disabled');
1706                  var tdElement = element.closest('td');
1707                  var selectedModule = tdElement.find('.lineItemPopup').data('moduleName');
1708                  var popupElement = tdElement.find('.lineItemPopup');
1709                  var dataUrl = "index.php?module=Inventory&action=GetTaxes&record="+selectedItemData.id+"&currency_id="+jQuery('#currency_id option:selected').val();
1710                  AppConnector.request(dataUrl).then(
1711                      function(data){
1712                          for(var id in data){
1713                              if(typeof data[id] == "object"){
1714                              var recordData = data[id];
1715                              thisInstance.mapResultsToFields(selectedModule, popupElement, recordData);
1716                              }
1717                          }
1718                      },
1719                      function(error,err){
1720  
1721                      }
1722                  );
1723              },
1724              'change' : function(event, ui) {
1725                  var element = jQuery(this);
1726                  //if you dont have disabled attribute means the user didnt select the item
1727                  if(element.attr('disabled')== undefined) {
1728                      element.closest('td').find('.clearLineItem').trigger('click');
1729                  }
1730              }
1731          });
1732      },
1733  
1734      registerClearLineItemSelection : function() {
1735          var thisInstance = this;
1736          var lineItemTable = this.getLineItemContentsContainer();
1737          lineItemTable.on('click','.clearLineItem',function(e){
1738              var elem = jQuery(e.currentTarget);
1739              var parentElem = elem.closest('td');
1740              thisInstance.clearLineItemDetails(parentElem);
1741              parentElem.find('input.productName').removeAttr('disabled').val('');
1742              e.preventDefault();
1743          });
1744      },
1745  
1746      clearLineItemDetails : function(parentElem) {
1747          var thisInstance = this;
1748          var lineItemRow = parentElem.closest('tr.'+thisInstance.rowClass);
1749          jQuery('input.selectedModuleId',lineItemRow).val('');
1750          jQuery('input.listPrice',lineItemRow).val('0');
1751          jQuery('.lineItemCommentBox', lineItemRow).val('');
1752          thisInstance.quantityChangeActions(lineItemRow);
1753      },
1754  
1755      checkLineItemRow : function(){
1756          var lineItemTable = this.getLineItemContentsContainer();
1757          var noRow = lineItemTable.find('.lineItemRow').length;
1758          if(noRow >1){
1759              this.showLineItemsDeleteIcon();
1760          }else{
1761              this.hideLineItemsDeleteIcon();
1762          }
1763      },
1764  
1765      showLineItemsDeleteIcon : function(){
1766          var lineItemTable = this.getLineItemContentsContainer();
1767          lineItemTable.find('.deleteRow').show();
1768      },
1769  
1770      hideLineItemsDeleteIcon : function(){
1771          var lineItemTable = this.getLineItemContentsContainer();
1772          lineItemTable.find('.deleteRow').hide();
1773      },
1774  
1775      /**
1776       * Function to swap array
1777       * @param Array that need to be swapped
1778       */
1779      swapObject : function(objectToSwap){
1780          var swappedArray = {};
1781          var newKey,newValue;
1782          for(var key in objectToSwap){
1783              newKey = objectToSwap[key];
1784              newValue = key;
1785              swappedArray[newKey] = newValue;
1786          }
1787          return swappedArray;
1788      },
1789  
1790      /**
1791       * Function to copy address between fields
1792       * @param strings which accepts value as either odd or even
1793       */
1794      copyAddress : function(swapMode){
1795          var thisInstance = this;
1796          var formElement = this.getForm();
1797          var addressMapping = this.addressFieldsMappingInModule;
1798          if(swapMode == "false"){
1799              for(var key in addressMapping) {
1800                  var fromElement = formElement.find('[name="'+key+'"]');
1801                  var toElement = formElement.find('[name="'+addressMapping[key]+'"]');
1802                  toElement.val(fromElement.val());
1803              }
1804          } else if(swapMode){
1805              var swappedArray = thisInstance.swapObject(addressMapping);
1806              for(var key in swappedArray) {
1807                  var fromElement = formElement.find('[name="'+key+'"]');
1808                  var toElement = formElement.find('[name="'+swappedArray[key]+'"]');
1809                  toElement.val(fromElement.val());
1810              }
1811              toElement.val(fromElement.val());
1812          }
1813      },
1814  
1815      /**
1816       * Function to register event for copying addresses
1817       */
1818      registerEventForCopyAddress : function(){
1819          var thisInstance = this;
1820          var formElement = this.getForm();
1821          jQuery('[name="copyAddressFromRight"],[name="copyAddressFromLeft"]').change(function(){
1822              var element = jQuery(this);
1823              var elementClass = element.attr('class');
1824              var targetCopyAddress = element.data('copyAddress');
1825              var objectToMapAddress;
1826              if(elementClass == "accountAddress"){
1827                  var recordRelativeAccountId = jQuery('[name="account_id"]').val();
1828                  if(recordRelativeAccountId == "" || recordRelativeAccountId == "0"){
1829                      Vtiger_Helper_Js.showPnotify(app.vtranslate('JS_PLEASE_SELECT_AN_ACCOUNT_TO_COPY_ADDRESS'));
1830                  } else {
1831                      var recordRelativeAccountName = jQuery('#account_id_display').val();
1832                      var data = {
1833                          'record' : recordRelativeAccountId,
1834                          'selectedName' : recordRelativeAccountName,
1835                          'source_module': "Accounts"
1836                      }
1837                      if(targetCopyAddress == "billing"){
1838                          objectToMapAddress = thisInstance.addressFieldsMappingBetweenModules['AccountsBillMap'];
1839                      } else if(targetCopyAddress == "shipping"){
1840                          objectToMapAddress = thisInstance.addressFieldsMappingBetweenModules['AccountsShipMap'];
1841                      }
1842                      thisInstance.copyAddressDetails(data,element.closest('table'),objectToMapAddress);
1843                      element.attr('checked','checked');
1844                  }
1845              }else if(elementClass == "contactAddress"){
1846                  var recordRelativeContactId = jQuery('[name="contact_id"]').val();
1847                  if(recordRelativeContactId == "" || recordRelativeContactId == "0"){
1848                      Vtiger_Helper_Js.showPnotify(app.vtranslate('JS_PLEASE_SELECT_AN_CONTACT_TO_COPY_ADDRESS'));
1849                  } else {
1850                      var recordRelativeContactName = jQuery('#contact_id_display').val();
1851                      var data = {
1852                          'record' : recordRelativeContactId,
1853                          'selectedName' : recordRelativeContactName,
1854                          source_module: "Contacts"
1855                      }
1856                      if(targetCopyAddress == "billing"){
1857                          objectToMapAddress = thisInstance.addressFieldsMappingBetweenModules['ContactsBillMap'];
1858                      } else if(targetCopyAddress == "shipping"){
1859                          objectToMapAddress = thisInstance.addressFieldsMappingBetweenModules['ContactsShipMap'];
1860                      }
1861                      thisInstance.copyAddressDetails(data,element.closest('table'),objectToMapAddress);
1862                      element.attr('checked','checked');
1863                  }
1864              } else if(elementClass == "shippingAddress"){
1865                  var target = element.data('target');
1866                  if(target == "shipping"){
1867                      var swapMode = "true";
1868                  }
1869                  thisInstance.copyAddress(swapMode);
1870              } else if(elementClass == "billingAddress"){
1871                  var target = element.data('target');
1872                  if(target == "billing"){
1873                      var swapMode = "false";
1874                  }
1875                  thisInstance.copyAddress(swapMode);
1876              }
1877          })
1878          jQuery('[name="copyAddress"]').on('click',function(e){
1879              var element = jQuery(e.currentTarget);
1880              var swapMode;
1881              var target = element.data('target');
1882              if(target == "billing"){
1883                  swapMode = "false";
1884              }else if(target == "shipping"){
1885                  swapMode = "true";
1886              }
1887              thisInstance.copyAddress(swapMode);
1888          })
1889      },
1890  
1891      /**
1892       * Function to toggle shipping and billing address according to layout
1893       */
1894      registerForTogglingBillingandShippingAddress : function(){
1895          var billingAddressPosition = jQuery('[name="bill_street"]').closest('td').index();
1896          var copyAddress1Block = jQuery('[name="copyAddress1"]');
1897          var copyAddress2Block = jQuery('[name="copyAddress2"]');
1898          var copyHeader1 = jQuery('[name="copyHeader1"]');
1899          var copyHeader2 = jQuery('[name="copyHeader2"]');
1900          var copyAddress1toggleAddressLeftContainer = copyAddress1Block.find('[name="togglingAddressContainerLeft"]');
1901          var copyAddress1toggleAddressRightContainer = copyAddress1Block.find('[name="togglingAddressContainerRight"]');
1902          var copyAddress2toggleAddressLeftContainer = copyAddress2Block.find('[name="togglingAddressContainerLeft"]')
1903          var copyAddress2toggleAddressRightContainer = copyAddress2Block.find('[name="togglingAddressContainerRight"]');
1904          var headerText1 = copyHeader1.html();
1905          var headerText2 = copyHeader2.html();
1906  
1907          if(billingAddressPosition == 3){
1908                  if(copyAddress1toggleAddressLeftContainer.hasClass('hide')){
1909                      copyAddress1toggleAddressLeftContainer.removeClass('hide');
1910                  }
1911                  copyAddress1toggleAddressRightContainer.addClass('hide');
1912                  if(copyAddress2toggleAddressRightContainer.hasClass('hide')){
1913                      copyAddress2toggleAddressRightContainer.removeClass('hide');
1914                  }
1915                  copyAddress2toggleAddressLeftContainer.addClass('hide');
1916                  copyHeader1.html(headerText2);
1917                  copyHeader2.html(headerText1);
1918                  copyAddress1Block.find('[data-copy-address]').each(function(){
1919                      jQuery(this).data('copyAddress','shipping');
1920                  })
1921                  copyAddress2Block.find('[data-copy-address]').each(function(){
1922                      jQuery(this).data('copyAddress','billing');
1923                  })
1924              }
1925          },
1926  
1927      /**
1928       * Function to check for relation operation
1929       * if relation exist calculation should happen by default
1930       */
1931      registerForRealtionOperation : function(){
1932          var form = this.getForm();
1933          var relationExist = form.find('[name="relationOperation"]').val();
1934          if(relationExist){
1935              jQuery('.qty').trigger('focusout');
1936          }
1937      },
1938  
1939      //Related to preTaxTotal Field
1940  
1941      /**
1942       * Function to set the pre tax total
1943       */
1944      setPreTaxTotal : function(preTaxTotalValue){
1945          jQuery('#preTaxTotal').text(preTaxTotalValue);
1946          return this;
1947      },
1948  
1949      /**
1950       * Function to get the pre tax total
1951       */
1952      getPreTaxTotal : function() {
1953          return parseFloat(jQuery('#preTaxTotal').text());
1954      },
1955  
1956      /**
1957       * Function to calculate the preTaxTotal value
1958       */
1959      calculatePreTaxTotal : function() {
1960          var numberOfDecimal = parseInt(jQuery('.numberOfCurrencyDecimal').val());
1961          var netTotal = this.getNetTotal();
1962          var shippingHandlingCharge = this.getShippingAndHandling();
1963          var finalDiscountValue = this.getFinalDiscountTotal();
1964          var preTaxTotal = netTotal+shippingHandlingCharge-finalDiscountValue;
1965          var preTaxTotalValue = parseFloat(preTaxTotal).toFixed(numberOfDecimal);
1966          this.setPreTaxTotal(preTaxTotalValue);
1967      },
1968  
1969      /**
1970       * Function to save the pre tax total value
1971       */
1972      savePreTaxTotalValue : function() {
1973          jQuery('#pre_tax_total').val(this.getPreTaxTotal());
1974      },
1975  
1976      /**
1977       * Function which will register all the events
1978       */
1979      registerBasicEvents : function(container) {
1980          this._super(container);
1981          this.registerReferenceSelectionEvent(container);
1982      },
1983      
1984      registerEvents: function(){
1985          this._super();
1986          this.registerAddingNewProductsAndServices();
1987          this.lineItemActions();
1988          this.lineItemResultActions();
1989          //TODO : this might be costier operation. This we added to calculate tax for each line item
1990          this.makeLineItemsSortable();
1991          this.checkLineItemRow();
1992          this.registerForRealtionOperation();
1993      }
1994  });


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1