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>