Contact module as Extension

Jira Code: MISC-340

Extension created for displaying, editing and creating the contacts for a customer in SCA webstore.

manifest.json

{
    "name": "ContactsExtension",
    "fantasyName": "Contacts Extension",
    "vendor": "JJ",
    "type": "extension",
    "target": "SCA,SCS",
    "version": "1.0.0",
    "description": "List, Edit and Add Contacts to a customer",
    "assets": {
        "img": {
            "files": []
        },
        "fonts": {
            "files": []
        },
        "services": {
            "files": [
                "services/ContactModule.Service.ss"
            ]
        }
    },
    "configuration": {
        "files": []
    },
    "templates": {
        "application": {
            "myaccount": {
                "files": [
                    "Modules/ContactModule/Templates/contactdetails_details.tpl",
                    "Modules/ContactModule/Templates/contactdetails_edit.tpl",
                    "Modules/ContactModule/Templates/contactdetails_list.tpl",
                    "Modules/ContactModule/Templates/jj_mycoolextension_contactmodule.tpl"
                ]
            }
        }
    },
    "sass": {
        "entry_points": {
            "myaccount": "Modules/ContactModule/Sass/_contactmodule.scss"
        },
        "files": [
            "Modules/ContactModule/Sass/_contactdetails-details.scss",
            "Modules/ContactModule/Sass/_contactdetails-edit.scss",
            "Modules/ContactModule/Sass/_contactdetails-list.scss",
            "Modules/ContactModule/Sass/_contactmodule.scss"
        ]
    },
    "javascript": {
        "entry_points": {
            "myaccount": "Modules/ContactModule/JavaScript/ContactModule.js"
        },
        "application": {
            "myaccount": {
                "files": [
                    "Modules/ContactModule/JavaScript/ContactDetails.Collection.js",
                    "Modules/ContactModule/JavaScript/ContactDetails.Details.View.js",
                    "Modules/ContactModule/JavaScript/ContactDetails.Edit.View.js",
                    "Modules/ContactModule/JavaScript/ContactDetails.List.View.js",
                    "Modules/ContactModule/JavaScript/ContactDetails.Model.js",
                    "Modules/ContactModule/JavaScript/ContactDetails.Router.js",
                    "Modules/ContactModule/JavaScript/ContactModule.View.js",
                    "Modules/ContactModule/JavaScript/ContactModule.js"
                ]
            }
        }
    },
    "ssp-libraries": {
        "entry_point": "Modules/ContactModule/SuiteScript/ContactModule.ServiceController.js",
        "files": [
            "Modules/ContactModule/SuiteScript/ContactModule.ServiceController.js",
            "Modules/ContactModule/SuiteScript/JJ.MyCoolExtension.ContactModule.js"
        ]
    }
}

JavaScript

ContactDetails.Collection.js

define(
  'ContactDetails.Collection',
  [
  'Backbone',
  'ContactDetails.Model',
  'Utils'
  ],
  function 
  (
    Backbone,
    Model,
    Utils
  ) 
  {
    return Backbone.Collection.extend({
      model: Model,
      url:Utils.getAbsoluteUrl(getExtensionAssetsPath('services/ContactModule.Service.ss'))
    });
  }
);

ContactDetails.Details.View.js

define('ContactDetails.Details.View',
  [
  'Backbone',
  'contactdetails_details.tpl'
  ],
  function (Backbone, contactdetails_details_tpl) {
    return Backbone.View.extend({
      
      template: contactdetails_details_tpl

    , initialize: function ()
      {
        this.model.on('sync', _.bind(this.render, this));
      }
    , getContext: function () {
     console.log("this.model.get('address')",this.model.get('address'));
        return {
          'name': this.model.get('name'),
          'phone': this.model.get('phone'),
          'address': this.model.get('address'),
          'internalid': this.model.get('internalid')
        }
      },

      

    });
  }
)

ContactDetails.Edit.View.js

define('ContactDetails.Edit.View',
  [
  'Backbone',
  'contactdetails_edit.tpl',
  'SC.Configuration',
  'GlobalViews.Message.View',
  'GlobalViews.CountriesDropdown.View',
  'GlobalViews.States.View',
  'Backbone.CompositeView',
  'Backbone.FormView',
  'underscore',
  'jQuery',
  'Utils'
  ],
  function (
    Backbone,
    contactdetails_edit_tpl,
    Configuration,
    GlobalViewsMessageView,
    CountriesDropdownView,
    GlobalViewsStatesView,
    BackboneCompositeView,
    BackboneFormView,
    _,
    jQuery
  ) 
  {
    return Backbone.View.extend({
      template: contactdetails_edit_tpl,
      events: {
        'submit form': 'save'
      },
      save: function(e)
      {
        return this.saveForm(e,this.model);
      },

      bindings: {
        '[name="name"]': 'name'
      , '[name="phone"]': 'phone'
      , '[name="company"]': 'company'
      , '[name="address1"]': 'address1'
      , '[name="address2"]': 'address2'
      , '[name="city"]': 'city'
      , '[name="state"]': 'state'
      , '[name="zipcode"]': 'zipcode'
      , '[name="country"]': 'country'
      },

     getSelectedMenu: function ()
      {
        return 'contacts';
      },

      getBreadcrumbPages: function ()
      {
        return [
          {
            text: _('Contact').translate()
          , href: '/contacts'
          }
        , {
            text: this.title
          , href: '/contacts/new'
          }
        ];
      },

      render: function ()
      {
        Backbone.View.prototype.render.apply(this, arguments);

        this.$('[rel="tooltip"]').tooltip({
          placement: 'right'
        }).on('hide', function (e)
        {
          e.preventDefault();
          jQuery(e.target).next('.tooltip').hide();
        });
      },

      initialize: function(options) {
        var addNewContactLabel = _('ADD NEW CONTACT').translate();
        var editContactLabel = _('EDIT CONTACT ADDRESS').translate();
        this.title = this.model.isNew() ? addNewContactLabel : editContactLabel;
        this.application = options.application;
        this.model = options.model;
        this.countries = Configuration.get('siteSettings.countries');
        this.selectedCountry = this.model.get('country') || Configuration.get('siteSettings.defaultshipcountry');
        if (!this.selectedCountry && _.size(this.countries) === 1)
        {
          this.selectedCountry = _.first(_.keys(this.countries));
        }

        if (!!this.selectedCountry)
        {
          this.model.set('country', this.selectedCountry);
        }
        BackboneCompositeView.add(this);
        BackboneFormView.add(this);
        
      },

      childViews: {
        'CountriesDropdown': function ()
        {
          return new CountriesDropdownView({
            countries: this.countries
          , selectedCountry: this.selected_country
          , manage: this.options.manage
          });
        }
      , 'StatesView': function ()
        {console.log("this in states view contact detailsedit",this);
          return new GlobalViewsStatesView({
            countries: this.countries
          , selectedCountry: this.model.attributes.country
          , selectedState: this.model.get('state')
          , manage: this.options.manage
          });
        }
      },

  
      getContext: function() {
        return {
          isNew: this.model.isNew(),
          name: this.model.get('name'),
          phone: this.model.get('phone'),
          address: this.model.get('address'),

        }
      }

    });
  }
)

ContactDetails.List.View.js

define(
	'ContactDetails.List.View',
 	[
 		'Backbone.CompositeView'
	,	'Backbone.CollectionView'
	,	'ContactDetails.Details.View'
	,	'Backbone'
	,	'contactdetails_list.tpl'
  , 'GlobalViews.Confirmation.View'
  , 'jQuery'
  , 'Profile.Model'
  , 'Profile.Information.View'
  ]
,   function(
		BackboneCompositeView
	,	BackboneCollectionView
	,	ContactDetailsDetailsView
 	,	Backbone
 	,	contactdetails_list_tpl
  , GlobalViewsConfirmationView
  , jQuery
  , ProfileModel
  , ProfileInformationView
 	) 
{
   return Backbone.View.extend({

   	template : contactdetails_list_tpl

  , events: {
      'click button[data-action="remove"]': 'removecontact'
    }


  , removeModel: function(options) {
      var model = options.context.collection.get(options.id);
      model.destroy();
    }

  , removecontact: function(e) {
      e.preventDefault();
      var view = new GlobalViewsConfirmationView({
        title: 'Remove Contact',
        body: 'Are you sure you want to remove this contact?',
        callBack: this.removeModel,
        callBackParameters: {
          context: this,
          id: jQuery(e.target).data('id')
        },
        autohide: true
      });
      this.application.getLayout().showInModal(view);
    }


  , page_header: _('CONTACT INFO').translate()

  , title: _('Contact info').translate()

  , attributes: { 'class': 'ContactDetailsListView' }


	, initialize: function (options) {
      BackboneCompositeView.add(this);
      var self = this;
      this.application = options.application;
      this.collection = options.collection;
      this.collection.on('reset sync add remove change destroy', function ()
      {
          self.render();
      });
    }

  , getSelectedMenu: function ()
    {
      return 'contacts';
    }

  , getBreadcrumbPages: function ()
    {
      return {
        text: this.title
      , href: '/contacts'
      };
    }

  ,	childViews: {
      'ContactDetails.Collection': function() {
        return new BackboneCollectionView({
          childView: ContactDetailsDetailsView,
          collection: this.collection,
          viewsPerRow: 1
        });
      }
    /*, 'Profile.Information' : function(){
        return new ProfileInformationView({
        application: this.application
      , model: ProfileModel.getInstance()
      });
      }*/


    }
    
  , getContext: function ()
    {
      //@class Address.List.View.Context
      return {
        //@property {String} pageHeader
        pageHeader: this.page_header
      , isEmailSubscribeChecked:SC.ENVIRONMENT.siteSettings.defaultSubscriptionStatus
      };
    }

   });
});

ContactDetails.Model.js

define(
	'ContactDetails.Model',
  [
  	'Backbone',
  	'underscore',
    'Utils'
  ],
  function 
  (
  	Backbone,
  	 _,
     Utils
  ) 
  {
    return Backbone.Model.extend({
      urlRoot: Utils.getAbsoluteUrl(getExtensionAssetsPath('services/ContactModule.Service.ss'))
      

    , validation: {
        /*name: { required: true, msg: _('Name is required').translate() }
      , address1: { required: true, msg: _('Address is required').translate() }
      , city: { required: true, msg: _('City is required').translate() }
      , state: { required: true, msg: _('state is required').translate() }
      , zipcode: { required: true, msg: _('zipcode is required').translate() }
      , country: { required: true, msg: _('Country is required').translate() }*/
    }

    });
  }
);

ContactDetails.Router.js

define(
	'ContactDetails.Router'
, [
  'Backbone',
  'ContactDetails.List.View',
  'ContactDetails.Model',
  'ContactDetails.Collection',
  'ContactDetails.Edit.View',
  'jQuery'
  ]
, function Router(
  	Backbone
  ,	ContactDetailsListView
  , Model
  , Collection
  , ContactDetailsEditView
  , jQuery
  ) 
  {
  return Backbone.Router.extend({

  	initialize: function(application) {
      this.application = application;
      console.log("inrouter")
    }

,    routes: {
      'contacts': 'contactList',
      'contacts/new': 'contactDetails',
      'contacts/:id': 'contactDetails'
    }
,   contactList: function() 
	{console.log("incontactList")
      var collection = new Collection();
	    var view = new ContactDetailsListView({collection: collection,application: this.application});

      collection.fetch().done(function(){
      view.showContent();
    })
	}
/*,   newContact: function () {
      var view = new ContactDetailsEditView({model: new Model(), application: this.application});
      view.showContent();
    }*/

,   contactDetails: function (id) {
 console.log("incontactDetails")
      var model = new Model();
      var promise = jQuery.Deferred();
      
      var self = this;
      console.log('id',id);

      if (id == 'showinmodal=T') {

        promise.resolve();
        
      } else {         
        model.fetch({
          data: {
            internalid: id
          }
        }).done(function () {
          promise.resolve();
        });
      }
      promise.done(function () {
        var view = new ContactDetailsEditView({model: model, application: self.application});



        view.showContent();
        view.model.on('sync', function (model) {
            Backbone.history.navigate('contacts', {trigger: true});
            location.reload(0);
            
        });
      });
    }
  });
});

ContactModule.js


define(
	'ContactModule'
,   [
		'ContactDetails.Router'
	
	]
,   function (
		Router
	
	)
{
	'use strict';

	return  {
		mountToApp: function mountToApp (container)
		
		{
			var myaccountmenu = container.getComponent("MyAccountMenu");
			if(myaccountmenu)
			{
				 var preordersmenugroup = {
			     id: "contacts",
			     name: "Contacts",
			     index: 2,
			     url: "contacts",
			     permissionoperator: "OR",
			     permissions: [
			         {
			             group: "transactions",
			             id: "TRAN_CUSTINVC",
			             level: "1"
			         },
			         {
			             group: "transactions",
			             id: "TRAN_CUSTCRED",
			             level: "1"
			         }
			     ]
			}

			myaccountmenu.addGroup(preordersmenugroup);
			}
            console.log("bkkjshajkdjkk")
			new Router(container);
		}
	};
});

ContactModule.View.js


define('ContactModule.View'
,	[
		'jj_mycoolextension_contactmodule.tpl'
	,	'Utils'
	,	'Backbone'
	,	'jQuery'
	,	'underscore'
	]
,	function (
		jj_mycoolextension_contactmodule_tpl
	,	Utils
	,	Backbone
	,	jQuery
	,	_
	)
{
	'use strict';

	
	return Backbone.View.extend({

		template: jj_mycoolextension_contactmodule_tpl

	,	initialize: function (options) {

			/*  Uncomment to test backend communication with an example service 
				(you'll need to deploy and activate the extension first)
			*/
			this.message = '';
			// var service_url = Utils.getAbsoluteUrl(getExtensionAssetsPath('services/ContactModule.Service.ss'));

			// jQuery.get(service_url)
			// .then((result) => {

			// 	this.message = result;
			// 	this.render();
			// });
		}

	,	events: {
		}

	,	bindings: {
		}

	, 	childViews: {
			
		}

		
	,	getContext: function getContext()
		{
			
			this.message = this.message || 'Hello World!!'
			return {
				message: this.message
			};
		}
	});
});

Sass

_contactdetails-details.scss

.contactdetails-details{
	color: #435363;
	background-color: #e5e5e5;
	margin-bottom: 15px;
}
.contactdetails-details-area{
	padding: 15px 30px;
}
.contactdetails-details-contact-name{
    margin-bottom: 10px;
    font-weight: 600;
}
.contactdetails-details-contact-address{
    margin-bottom: 10px;
    
}
.contactdetails-details-contact-phone{
	//font-weight: 600;
}
.contactdetails-details-divider{
    background-color: darkgrey;
    margin: 0px;
}
.contactdetails-details-actions{
	text-align: right;
	font-size: 16px;
    color: #435363;
    font-weight: 600;
    margin-top: 5px;
    padding-bottom: 5px;
}
.contactdetails-details-edit{
	color: #435363;
	margin-right: 40px;
}
.contactdetails-details-remove{
	color: #435363;
	background-color: #e5e5e5;
	margin: 10px 40px 10px 40px;
}
.contactdetails-contact-phone{
	font-weight: 600;
	color:#435363;
}

_contactdetails-edit.scss

.contactdetails-edit-required{
	@extend .input-required;
} 
.contactdetails-edit-fields{
	background-color: #ededed;
    border: none;
}
.contactdetails-edit-label{
	color: #435363;
	margin-bottom: 5px;
}
.edit-label{
    font-size: 14px;
}
.contactdetails-edit-fields-cell-left{
	padding-left: 0px;
}
.contactdetails-edit-fields-cell-right{
	padding-right: 0px;
}
.contactdetails-edit-fields-group{
	padding: 0px;
}
.contactdetails-edit-form-button-submit{
	 @extend .button-primary;
    @extend .button-medium;
    background-color: #435363;
    border-radius: 0px;
    border:none;
    width: 25%;
    height: 40px;
    &:hover{
       background-color: #435363; 
    };
}
.contactdetails-edit-action{
	text-align: center;
}

.contactdetails-edit-checkbox{
    input[type=checkbox] {
             position: relative;
               cursor: pointer;
        }
        input[type=checkbox]:before {
             content: "";
             display: block;
             position: absolute;
             width: 13px;
             height: 13px;
             top: 0;
             left: 0;
             border: 2px solid #435363;
             border-radius: 3px;
             background-color: white;
        }
        input[type=checkbox]:checked:after {
             content: "";
             display: block;
             width: 3px;
             height: 6px;
             border: solid black;
             border-width: 0 2px 2px 0;
             -webkit-transform: rotate(45deg);
             -ms-transform: rotate(45deg);
             transform: rotate(45deg);
             position: absolute;
             top: 3px;
             left: 6px;
        }
    
}

_contactdetails-list.scss

.contactdetails-list{
	padding: 30px;
	margin-bottom:30px;
}

.contactdetails-list-pageheader{
	font-size: 22px;
    font-weight: 600;
    color: #00a7ce;
}

.ContactDetailsListView{
	background-color: white;
}
.contactdetails-list-title{
	font-size: 18px;
	font-weight: 700;
	color:#435363;
}

.contactdetails-list-newcontact{
	border-radius: 0px;
		background:#435363;
		text-transform:uppercase;
		padding: 10px 30px 10px 30px;
		font-weight: 600;
		color: white;
	
	&::before {
		/*content: url("https://www.alibisecurity.ml/SSP Applications/NetSuite Inc. - SCA Aconcagua/Development/img/plus_button1.png");*/
		position: relative;
		top: 4px;
		left: -10px;
	}
	&:hover{
		color: white;
	};
}
.contactdetails-profileinfo-call{
	background-color: #e5e5e5;
}

.profileinformation-list-title{
	font-size: 18px;
	font-weight: 700;
	color:#435363;
	margin-top: 20px;
}

.contactdetails-list-subscription{
	margin-bottom: 20px;
	color: #435363;
	display: inline-flex;
}

.contactdetails-list-subscription-main{
	display: flex;
    input[type=checkbox] {
             position: relative;
               cursor: pointer;
        }
        input[type=checkbox]:before {
             content: "";
             display: block;
             position: absolute;
             width: 13px;
             height: 13px;
             //top: -1px;
             left: 0;
             border: 2px solid #435363;
             border-radius: 4px;
             background-color: white;
             //bottom: -8px;
        }
        input[type=checkbox]:checked:after {
             content: "";
             display: block;
             width: 3px;
             height: 6px;
             border: solid black;
             border-width: 0 2px 2px 0;
             -webkit-transform: rotate(45deg);
             -ms-transform: rotate(45deg);
             transform: rotate(45deg);
             position: absolute;
             top: 4px;
             left: 6px;
        }
    
}

.contactdetails-list-edit-help-message{
	margin-bottom: 10px;
	color: #435363;
}
.signmeuptext{
	margin-top: -5px;
}
.contactdetails-edit-fields-cell-right{
.global-views-states-group-label{
	margin-bottom: 5px;
}}
.contactdetails-edit-fields-cell-right{
.global-views-states-group-form-controls{
.global-views-states-group-select{
	border: none;
	background-color: #e5e5e5;
	min-width: 259px;
	height: 37px;
}}}

.contactdetails-edit-fields-cell-right{
.global-views-countriesDropdown-group-label{
	margin-bottom: 5px;
}}

.contactdetails-edit-fields-cell-right{
.global-views-countriesDropdown-form-controls{
.global-views-countriesDropdown-select{
	border: none;
	background-color: #e5e5e5;
	min-width: 259px;
	width: 259px;
	height: 37px;
}}}

_contactmodule.scss

/*
	Sass Application Entry Point
	Link all your sass dependencies in the right order

	Example:
	@import "other-sass-file.scss";
	@import "../../<other module>/Sass/other-sass-file.scss";
*/ 

@import "_contactdetails-details.scss";
@import "_contactdetails-edit.scss";
@import "_contactdetails-list.scss";

.contactmodule-info-card {
    @extend .info-card;
}

.contactmodule-info-card-content {
    @extend .info-card-content;
    color: $sc-color-secondary;
    font-weight: bold;
}

SuiteScript

JJ.ContactsExtension.ContactModule.ServiceController.js


define(
	'JJ.ContactsExtension.ContactModule.ServiceController'
,	[
		'ServiceController'
	,	'JJ.MyCoolExtension.ContactModule'
	]
,	function(
		ServiceController
	,	ContactDetailsModel
	)
	{
		'use strict';

		// @class ContactDetails.ServiceController Manage ContactDetailses requests
		// @extend ServiceController
		return ServiceController.extend({

			// @property {String} name Mandatory for all ssp-libraries model
			name:'JJ.ContactsExtension.ContactModule.ServiceController'

			// @property {Service.ValidationOptions} options. All the required validation, permissions, etc.
			// The values in this object are the validation needed for the current service.
			// Can have values for all the request methods ('common' values) and specific for each one.
		,	options: {
				common: {
					requireLogin: true
				}
			}

			// @method get The call to ContactDetails.Service.ss with http method 'get' is managed by this function
			// @return {ContactDetails.Model.Attributes | Array<ContactDetails.Model.Attributes>} one or all user ContactDetailses
		,	get: function()
			{	console.log("inservicecontroler get");
				var id = this.request.getParameter('internalid');
				return id ? ContactDetailsModel.get(id) : (ContactDetailsModel.list() || []);
			}

			// @method post The call to ContactDetails.Service.ss with http method 'post' is managed by this function
			// @return {ContactDetailsModel.Attributes}
		,	post: function()
			{console.log("inservicecontroler post");
				var id = ContactDetailsModel.create(this.data);
				
				//Do not return anything here, we need send content with status 201
				this.sendContent(ContactDetailsModel.get(id), {'status': 201});
			}

			// @method update The call to ContactDetails.Service.ss with http method 'put' is managed by this function
			// @return {ContactDetails.Model.Attributes}
		,	put: function()
			{console.log("inservicecontroler put");
				var id = this.request.getParameter('internalid');
				
				ContactDetailsModel.update(id, this.data);
				return ContactDetailsModel.get(id);
			}

			// @method delete The call to ContactDetails.Service.ss with http method 'delete' is managed by this function
			// @return {StatusObject}
		,	delete: function()
			{console.log("inservicecontroler delete");
				var id = this.request.getParameter('internalid');
				
				ContactDetailsModel.remove(id);
				// If something goes wrong in the remove, an exception will fire
				return {'status': 'ok'};
			}
		});
	}
);

JJ.MyCoolExtension.ContactModule.js


define('JJ.MyCoolExtension.ContactModule',
  [
 'SC.Model'
 ,'JJ.ContactsExtension.ContactModule.ServiceController'
 ,'SC.Models.Init'
, 'Backbone.Validation'
, 'underscore'
  ],
  function (
  	  SCModel
    ,ServiceController
   ,  ModelsInit
   ,  BackboneValidation
   ,  _ 
  	) 
  {
    return SCModel.extend({
      name: 'ContactDetails',
      get: function(id) {
console.log("in SS model get");
        var field= ModelsInit.customer.getFieldValues();

        var contactSearch = nlapiSearchRecord("contact",null,
        [
           ["internalidnumber","equalto",id]
        ], 
        [
           new nlobjSearchColumn("entityid").setSort(false), 
           new nlobjSearchColumn("phone"), 
           new nlobjSearchColumn("address"),
           new nlobjSearchColumn("internalid"),
           new nlobjSearchColumn("attention","Address",null),
           new nlobjSearchColumn("address1","Address",null),
           new nlobjSearchColumn("address2","Address",null), 
           new nlobjSearchColumn("city","Address",null), 
           new nlobjSearchColumn("state","Address",null), 
           new nlobjSearchColumn("zipcode","Address",null), 
           new nlobjSearchColumn("country","Address",null)
        ]
        );
            
        if (contactSearch && contactSearch.length === 1) {
         
          return {
            phone: contactSearch[0].getValue('phone'),
            name: contactSearch[0].getValue('entityid'),
            address: contactSearch[0].getValue('address'),
            internalid: contactSearch[0].getValue('internalid'),
            company: contactSearch[0].getValue("attention","Address",null),
            address1: contactSearch[0].getValue("address1","Address",null),
            address2: contactSearch[0].getValue("address2","Address",null),
            city: contactSearch[0].getValue("city","Address",null),
            state: contactSearch[0].getValue("state","Address",null),
            zipcode: contactSearch[0].getValue("zipcode","Address",null),
            country: contactSearch[0].getValue("country","Address",null),
          };
        } else {
          throw notFoundError;
        }

        
      },
      list: function() {
       console.log("in SS model list");
        var field= ModelsInit.customer.getFieldValues();
        
        
        var customerId = field.internalid;

        var contactSearch = nlapiSearchRecord("contact",null,
        [
           ["customer.internalidnumber","equalto",customerId]
        ], 
        [
           new nlobjSearchColumn("entityid").setSort(false), 
           new nlobjSearchColumn("phone"), 
           new nlobjSearchColumn("address"),
           new nlobjSearchColumn("internalid"),
           new nlobjSearchColumn("attention","Address",null), 
           new nlobjSearchColumn("address1","Address",null), 
           new nlobjSearchColumn("address2","Address",null), 
           new nlobjSearchColumn("city","Address",null), 
           new nlobjSearchColumn("state","Address",null), 
           new nlobjSearchColumn("zipcode","Address",null), 
           new nlobjSearchColumn("country","Address",null)

        ]
        );

        return _.map(contactSearch, function(result) {


          var data = {
            phone : result.getValue("phone") || undefined, //TEXT
            name: result.getValue("entityid") || undefined, //TEXT
            address: result.getValue("address") || undefined, //TEXT 
            internalid: result.getValue("internalid") || undefined, //TEXT  
            company: result.getValue("attention","Address",null) || undefined, //TEXT 
            address1: result.getValue("address1","Address",null) || undefined, //TEXT 
            address2: result.getValue("address2","Address",null) || undefined, //TEXT 
            city: result.getValue("city","Address",null) || undefined, //TEXT 
            state: result.getValue("state","Address",null) || undefined, //TEXT 
            zipcode: result.getValue("zipcode","Address",null) || undefined, //TEXT 
            country: result.getValue("country","Address",null) || undefined, //TEXT                 
          };

          return data;
        });

      },
      create: function(data) {
       console.log("in SS model create");
        var record = nlapiCreateRecord('contact');
                record.setFieldValue('phone', data.phone);
                record.setFieldValue('entityid', data.name);
                record.setFieldValue('company', nlapiGetUser());
                var contactid = nlapiSubmitRecord(record);

        var rec = nlapiLoadRecord('contact', contactid, {
              recordmode : 'dynamic'
            });
                
        var addrSubrecord = rec.createCurrentLineItemSubrecord(
            'addressbook', 'addressbookaddress');

                
                addrSubrecord.setFieldValue('addressee', data.name);
                addrSubrecord.setFieldValue('addr1', data.address1);
                addrSubrecord.setFieldValue('addr2', data.address2);
                addrSubrecord.setFieldValue('city', data.city);
                addrSubrecord.setFieldValue('state', data.state);
                addrSubrecord.setFieldValue('zip', data.zipcode);
                addrSubrecord.setFieldValue('attention', data.company);
               
                
                addrSubrecord.commit();
                rec.commitLineItem('addressbook');
                var recordId = nlapiSubmitRecord(rec);
                return recordId;




      },
      update: function(id, data) {console.log("in SS model update");
      /*  this.validate(data);*/
        var rec = nlapiLoadRecord('contact', id, {
              recordmode : 'dynamic'
            });
        rec.selectLineItem('addressbook', 1);
       /* rec.setCurrentLineItemValue('addressbook', 'defaultshipping', data.defaultshipaddr);*/
        var addrSubrecord= rec.editCurrentLineItemSubrecord('addressbook', 'addressbookaddress');
                addrSubrecord.setFieldValue('addressee', data.name);
                addrSubrecord.setFieldValue('addr1', data.address1);
                addrSubrecord.setFieldValue('addr2', data.address2);
                addrSubrecord.setFieldValue('city', data.city);
                addrSubrecord.setFieldValue('state', data.state);
                addrSubrecord.setFieldValue('zip', data.zipcode);
                addrSubrecord.setFieldValue('attention', data.company);
                
                
                
                addrSubrecord.commit();
                rec.commitLineItem('addressbook');
                var recordId = nlapiSubmitRecord(rec);
                return recordId;
      },
      remove: function(id) {console.log("in SS model remove");
         nlapiDeleteRecord('contact', id);
      }
    });
  }
)

Templates

contactdetails_details.tpl

<div class="contactdetails-details">
	<div class=contactdetails-details-area>
	<tr>
	    <td>
	    	<div class="contactdetails-details-contact-name">{{name}}</div>
	    	<div class="contactdetails-details-contact-address">{{address}}</div>
	    	<div class="contactdetails-details-contact-phone"><span class="contactdetails-contact-phone">Phone: </span>{{phone}}</div>
	    </td>
	</tr>
	</div>
	<hr class="contactdetails-details-divider">
	<div class="contactdetails-details-actions">
		<a class="contactdetails-details-edit" href="/contacts/{{internalid}}" data-toggle="show-in-modal">EDIT</a>
		<button class="contactdetails-details-remove" data-action="remove" data-id="{{internalid}}" style="display: none;">REMOVE</button>
	</div>
</div>

contactdetails_edit.tpl

<form>
     <div data-validation="control-group">
        <label class="contactdetails-edit-label"><span class="contactdetails-edit-required">*</span>Name</label>
        <span data-validation="control">
            <input class="contactdetails-edit-fields" id="name" name="name" type="text">
        </span>
    </div>
    {{#if isNew}}
     <label class="contactdetails-edit-label">Phone</label><input class="contactdetails-edit-fields" id="phone" name="phone" type="text">
    {{/if}}
    	<input class="contactdetails-edit-fields" id="company" name="company" type="text" placeholder="Additional company line (optional)">
     <div data-validation="control-group">
     <label class="contactdetails-edit-label"><span class="contactdetails-edit-required">*</span>Address</label>
     	<span data-validation="control">
            <input class="contactdetails-edit-fields" id="address1" name="address1" type="text">
        </span>
     </div>
     	<input class="contactdetails-edit-fields" id="address2" name="address2" type="text">
     
<div class="contactdetails-edit-fields-group col-sm-12">
     <div data-validation="control-group" class="contactdetails-edit-fields-cell-left col-sm-6">
        <label class="contactdetails-edit-label"><span class="contactdetails-edit-required">*</span>City</label>
        <span data-validation="control">
            <input class="contactdetails-edit-fields" id="city" name="city" type="text">
        </span>
    </div>
    <!--  <div data-validation="control-group">
        <label>State</label>
        <span data-validation="control">
            <input id="state" name="state" type="text">
        </span>
    </div> -->

    <div class="contactdetails-edit-fields-cell-right col-sm-6" data-input="state" data-view="StatesView" data-validation="control-group"></div>
</div>
<div class="contactdetails-edit-fields-group col-sm-12">
     <div data-validation="control-group" class="contactdetails-edit-fields-cell-left col-sm-6">
        <label class="contactdetails-edit-label"><span class="contactdetails-edit-required">*</span>Zip/Postal Code</label>
        <span data-validation="control">
            <input class="contactdetails-edit-fields" id="zipcode" name="zipcode" type="text">
        </span>
     </div>
     <!-- <div data-validation="control-group">
        <label>Country</label>
        <span data-validation="control">
            <input id="country" name="country" type="text">
        </span>
    </div> -->

    <div class="contactdetails-edit-fields-cell-right col-sm-6" data-view="CountriesDropdown" data-input="country" data-validation="control-group">
    </div>
</div>
    <div class="contactdetails-edit-checkbox">
     <input id="defaultshipaddr" name="defaultshipaddr" type="checkbox" value="T">
     <label class="contactdetails-edit-label edit-label">Set as my default shipping address</label>
    </div>
    <div class="contactdetails-edit-action">
        <button type="submit" class="contactdetails-edit-form-button-submit">{{#if isNew}}ADD{{else}}SAVE{{/if}}</button>
    </div>
</form>

contactdetails_list.tpl

<section class="contactdetails-list">



<div class="contactdetails-list-pageheader">{{pageHeader}}</div>

<div data-view="ContactDetails.Collection"></div>
<a  href="/contacts/new" class="contactdetails-list-newcontact" data-toggle="show-in-modal">ADD NEW CONTACT</a>
</section>

jj_mycoolextension_contactmodule.tpl

<section class="contactmodule-info-card">
    <span class="contactmodule-info-card-content">
      {{message}}
    </span>
</section>

Leave a comment

Your email address will not be published. Required fields are marked *