How to customize return authorization in the MyAccount section by adding custom form fields

We can use this solution to customize return authorization in the MyAccount section by adding customized form fields.

JavaScript:

Entry Point:

define("JJ.Return.Authorization", [
	"JJ.Return.Authorization.View",
	"ReturnAuthorization.Form.View",
	"jj_return_authorization.tpl",
	"ReturnAuthorization.Form.Item.Actions.View",
	"jj_return_authorization_form.tpl",
	'Backbone.View',
	'Transaction.Line.Views.Cell.SelectableActionableNavigable.View',
	'jj_transaction_line_views_cell_selectable_actionable_navigable.tpl'
], function (
	AuthorizationViewInmodelFAQ,
	ReturnAuthorizationFormView,
	jj_return_authorization_tpl,
	ReturnAuthorizationFormItemActionsView,
	jj_return_authorization_form_tpl,
	BackboneView,
	TransactionLineViewsCellSelectableActionableNavigableView,
	jj_transaction_line_views_cell_selectable_actionable_navigable_tpl
) {
	"use strict";
	return {
		mountToApp: function mountToApp(container) {
			//ReturnAuthorization.Form.Item.Actions.View is extending for the adding new field to the return form.
			_.extend(ReturnAuthorizationFormItemActionsView.prototype, {
				template: jj_return_authorization_tpl,
				events: _.extend(
					{},
					ReturnAuthorizationFormItemActionsView.prototype.events,
					{
						'click [data-action="set-return-option"]': "setReturnOption",
						'change #return-authorization-item-damaged': "setItemDamaged",
						'change #return-authorization-item-used': "setItemUsed",
						'change #return-authorization-is-in-pakage': "setItemInPackage",
						'change [data-action="reasons"]': "setReasons",
						'change [data-action="reason-text"]': "setReasonsText",
					}
				),
				//setReasonsText function is using for updating the other reason that is entered in the text box.
				setReasonsText: function (e) {
					let reason = this.model.get('reason');
					reason.text = e.currentTarget.value
					this.model.set('reason', reason);
					this.render();
				},
				//setReasons function is using to set the reason that selected in the reason selection box.
				setReasons: function (e) {
					let isOther = e.currentTarget.value === '9' ? true : false;
					let text = e.currentTarget[e.currentTarget.value].innerText;
					this.model.set('reason', { isOther : isOther, text : text, value :  e.currentTarget.value});
					this.render();
				},
				//setItemDamaged function is using to set the item damaged value that selected in the item damaged selection box.
				setItemDamaged: function (e) {
					this.model.set('itemDamaged', e.currentTarget.value);
					this.render();
				},
				//setItemUsed function is using to set the item used value that selected in the item used selection box.
				setItemUsed: function (e) {
					this.model.set('itemUsed', e.currentTarget.value);
					this.render();
				},
				//setItemInPackage function is using to set the item is in package value that selected in the item is in package selection box.
				setItemInPackage: function (e) {
					this.model.set('itemInPackage', e.currentTarget.value);
					this.render();
				},
				//setReturnOption function is used to prevent the reloading page while entering the customized options.
				setReturnOption: function (e) {
					e.preventDefault();
				},
				//ReturnAuthorization.Form.Item.Actions.View getContext is extending for the seting up of option values after render.
				getContext: _.wrap(ReturnAuthorizationFormItemActionsView.prototype.getContext,function (fn) {
					let original = fn.apply(this, _.toArray(arguments).slice(1));
					try {
						const current_reason = this.model.get('reason') || {};
						original.isOtherReasonSelected = current_reason ? current_reason.isOther : false;
						let itemId = this.model.id;
						_.delay(() => {
							this.model.get('reason') ? $('[data-id="'+ itemId + '"] [data-action="reasons"]').val(this.model.get('reason').value) : undefined;
							this.model.get('reason') ? $('[data-id="'+ itemId + '"] [data-action="reason-text"]').val(this.model.get('reason').text) : undefined;
							this.model.get('itemDamaged') ? $('[data-id="'+ itemId + '"] #return-authorization-item-damaged').val(this.model.get('itemDamaged')) : undefined;
							this.model.get('itemUsed') ? $('[data-id="'+ itemId + '"] #return-authorization-item-used').val(this.model.get('itemUsed')) : undefined;
							this.model.get('itemInPackage') ? $('[data-id="'+ itemId + '"] #return-authorization-is-in-pakage').val(this.model.get('itemInPackage')) : undefined;
						},50)
					} catch (error) {
						console.error("Error @ ReturnAuthorization.Form.View getContext",error);
					}
					return original;
					}
				),
			});
			//ReturnAuthorization.Form.View is extending for the validation of newfields and passing value to Suitescript.
			_.extend(ReturnAuthorizationFormView.prototype, {
				template: jj_return_authorization_form_tpl,
				events: _.extend({},ReturnAuthorizationFormView.prototype.events,{
					'click [data-action="show-faq-inmodel"]': "showFAQ",
					'submit form': "saveForm",
				}),
				//applyReasonHandler function is extensding for the setting up the same values when we click apply to all function.
				applyReasonHandler: function (e){
					const currentLine = this.getLine(this.getLineId(e.target));
					e.preventDefault();
					e.stopPropagation();
					return this.setActiveLines({
						reason: currentLine.get('reason'),
						textReason: currentLine.get('textReason'),
						itemDamaged: currentLine.get('itemDamaged'),
						itemUsed: currentLine.get('itemUsed'),
						itemInPackage: currentLine.get('itemInPackage')
					}).render();
				},
				//showFAQ function is using to show the FAQ content as popup.
				showFAQ: function (e) {
					let layout = this.application.getLayout();
					let view = new AuthorizationViewInmodelFAQ({
						container: container
					});
					view.render();
					layout.showInModal(view);
				},
				//saveForm function is using to extend the functionality and validation of return form.
				saveForm: function (e) {
					if (this.preValidate()) {
						let createdFrom = this.createdFromModel,
						data = {
							id: createdFrom.get('internalid'),
							type: createdFrom.recordtype,
							lines: this.getActiveLinesData(),
							comments: this.comments || ''
							};
						if (e.preventDefault(), this.isValid(data)) return BackboneView.prototype.saveForm.call(this, e, this.model, data)
					}
					e.preventDefault();
				},
				//preValidate function is using to extend the validation of newly added fields.
				preValidate: function () {
					try {
						let lines = this.lines.models;
						let isAllFilled = true;
						_.each(lines, (item) => {
							let islineSelected = $('[data-id="'+ item.id+'"] .transaction-line-views-cell-selectable-actionable-navigable-select input')[0].checked;
							if (islineSelected) {
								if (!(item.get('itemDamaged') != null) || !(item.get('itemUsed') != null) || !(item.get('itemInPackage') != null)) {
									isAllFilled = false;
								}
								let reason = item.get('reason');
								if (reason) {
									reason.isOther === true && (reason.text === '' || reason.text === 'Other') ? isAllFilled === false &&  this.showError('Please enter value other reason.') : true;
								}
							}
						})
						isAllFilled === false ? this.showError('Please answer the required questions to proceed.') : true;
						return isAllFilled;
					} catch (error) {
						console.error('Error @ preValidate: ', error);
					}
				},
				//getActiveLinesData function is extending for updating the line data.
				getActiveLinesData: function() {
					try {
						let reason = null;
						let selected_reason;
						return _.map(this.getActiveLines(), function(line) {
							reason = line.get('reason');
							selected_reason = null;
							if (reason) {
								selected_reason = reason.isOther ? line.get('textReason') : reason.text;
							}
							return {
								id: line.get('internalid'),
								quantity: line.get('returnQty') || line.get('quantity'),
								reason: selected_reason,
								custcol_jj_returns_item_damaged : line.get('itemDamaged'),
								custcol_jj_returns_item_used : line.get('itemUsed'),
								custcol_jj_returns_item_inpackage : line.get('itemInPackage')
							};
						});
					} catch (error) {
						console.error('Error @ getActiveLinesData: ', error);
					}
				},
				//ReturnAuthorizationFormView is using for disabling the return for non returnable items.
				getContext: _.wrap(ReturnAuthorizationFormView.prototype.getContext, function (fn) {
					let context = fn.apply(this, _.toArray(arguments).slice(1));
					try {
						_.each(this.lines.models, (line) => {
							if (line.get('item').get('custitem_returnable') === false) {
								line.set('checked', false);
							}
						})
					} catch (error) {
						console.error('Error @ ReturnAuthorizationFormView getContext: ', error);
					}
					return context;
				})
			});
			//TransactionLineViewsCellSelectableActionableNavigableView is using to show the error messages for non-returnable items.
			_.extend(TransactionLineViewsCellSelectableActionableNavigableView.prototype, {
				template: jj_transaction_line_views_cell_selectable_actionable_navigable_tpl,
				getContext: _.wrap(TransactionLineViewsCellSelectableActionableNavigableView.prototype.getContext, function (fn) {
					let context = fn.apply(this, _.toArray(arguments).slice(1));
					try {
						if (context.actionType === "return-line") {
							context.isReturnable = this.model.get('item').get('custitem_returnable');
						}
					} catch (error) {
						console.error('Error @ TransactionLineViewsCellSelectableActionableNavigableView getContext: ', error);
					}
					return context;
				})
			});
		},
	};
});

Template:

jj_return_authorization_form.tpl

{{#if showBackToAccount}}
	<a href="/" class="return-authorization-form-button-back">
		<i class="return-authorization-form-button-back-icon"></i>
		{{translate 'Back to Account'}}
	</a>
{{/if}}

<section class="return-authorization-form">
	<header>
		<h2 class="return-authorization-form-title">{{pageHeader}}</h2>
	</header>
	<div data-type="alert-placeholder"></div>
  
	<form class="return-authorization-form-form">
    <fieldset class="return-authorization-form-items-fieldset">
      
      <p class="return-authorization-form-items-info">
        {{translate '<label class="return-authorization-form-items-fieldset-from-label">From: </label><a href="$(0)">Purchase #$(1)</a>' createdFromURL model.tranid}}
			</p>
			<input type="hidden" name="type" value="{{model.recordtype}}">
      
      
      <div class="view-faq-contents">View <a data-action="show-faq-inmodel" class="faq-show-model">Frequently Asked Questions</a></div>
			<h5 class="return-authorization-form-products-title">{{translate 'Select products to return'}}</h5>
			<input type="hidden" name="id" value="{{model.internalid}}">
			<div data-view="ListHeader"></div>

			<div class="return-authorization-form-list">
				<table class="return-authorization-form-returnable-products-table md2sm">
						<tbody data-view="Returnable.Lines.Collection"></tbody>
				</table>
			</div>
			<p>
				<small class="return-authorization-form-counter-legend">
					{{#if activeLinesLengthGreaterThan1}}
						{{translate '<b>$(0)</b> products selected' activeLinesLength}}
					{{else}}
						{{translate '<b>$(0)</b> product selected' activeLinesLength}}
					{{/if}}
				</small>
			</p>
			<p>
				<small class="return-authorization-form-counter-legend">
					{{#if itemsToReturnLengthGreaterThan1}}
						{{translate '<b>$(0)</b> items in total to return' itemsToReturnLength}}
					{{else}}
						{{translate '<b>$(0)</b> item in total to return' itemsToReturnLength}}
					{{/if}}
				</small>
			</p>
		</fieldset>

		{{#if showInvalidLines}}
			<div class="return-authorization-form-accordion-divider">
				<div class="return-authorization-form-accordion-head">
					<a class="return-authorization-form-accordion-head-toggle collapsed" data-toggle="collapse" data-target="#return-authorization-form-products" aria-expanded="true" aria-controls="return-authorization-form-products">
						{{translate 'Products from original order not eligible for return ($(0))' invalidLinesLength}}
					<i class="return-authorization-form-accordion-toggle-icon"></i>
					</a>
				</div>
				<div class="return-authorization-form-accordion-body collapse" id="return-authorization-form-products" role="tabpanel" data-target="#return-authorization-form-products">
					<div data-content="items-body">
							<table class="return-authorization-form-products-list">
								<thead class="return-authorization-form-table-products-header">
									<th class="return-authorization-form-table-products-header-image"></th>
									<th class="return-authorization-form-table-products-header-product">{{translate 'Product'}}</th>
									<th class="return-authorization-form-table-products-header-qty">{{translate 'Qty'}}</th>
									<th class="return-authorization-form-table-products-header-unit-price">{{translate 'Unit price'}}</th>
									<th class="return-authorization-form-table-products-header-amount">{{translate 'Amount'}}</th>
								</thead>
								<tbody data-view="Invalid.Lines.Collection"></tbody>
							</table>
					</div>
				</div>
			</div>
		{{/if}}

		<fieldset class="return-authorization-form-comment-fieldset">
			<label class="return-authorization-form-comment-label" for="comment">{{translate 'Add a comment <span class="return-authorization-form-comment-label-optional">(optional)</span>'}}</label>
			<textarea data-action="comments"  class="return-authorization-form-comment" rows="4">{{comments}}</textarea>
		</fieldset>
		<div class="form-actions">
			<button type="submit" class="return-authorization-form-submit-button" {{#unless hasAtLeastOneActiveLine}}disabled{{/unless}}>{{translate 'Submit Request'}}</button>
		</div>
	</form>
</section>


{{!----
The context variables for this template are not currently documented. Use the {{log this}} helper to view the context variables in the Console of your browser's developer tools.

----}}

jj_return_authorization.tpl

{{#if isLineActive}}
	<label class="return-authorization-form-item-actions-label" for="reason">
		{{translate 'Why are you returning the item?'}} <span class="return-authorization-form-item-actions-required">*</span>
	</label>
	{{#if showReasons}}
		<select data-action="reasons" name="reason" class="return-authorization-form-item-actions-options" data-toggle="false">
			<option value="null">{{translate 'Select a reason'}}</option>
			{{#each reasons}}
				<option value="{{id}}" {{#if isSelected}}selected{{/if}} data-toggle="false">{{text}}</option>
			{{/each}}
			{{!-- <option value="other" {{#if isOtherReasonSelected}}selected{{/if}}>{{translate 'Other'}}</option> --}}
		</select>

		{{#if isOtherReasonSelected}}
			<input type="text" data-action="reason-text" name="reason-text" value="{{textReason}}" data-toggle="false" class="return-authorization-form-item-actions-other-reason-input">
		{{/if}}
    <div class="return-authorization-form-group" data-validation="control-group">
			<label class="return-authorization-form-group-label" for="itemDamaged">
				{{translate 'Is the item damaged?'}}
				<span class="return-authorization-form-label-required">*</span>
			</label>
			<div  class="return-authorization-form-controls" data-validation="control">
				<select name="itemDamaged" id="return-authorization-item-damaged" data-toggle="false" class="return-authorization-form-item-actions-options">
          <option data-toggle="false" disabled selected value="null">Select an option</option>
          <option data-toggle="false" value="1">Yes</option>
          <option data-toggle="false" value="2">No</option>
        </select>
			</div>
		</div>
    <div class="return-authorization-form-group" data-validation="control-group">
			<label class="return-authorization-form-group-label" for="itemUsed">
				{{translate 'Has the item been used?'}}
				<span class="return-authorization-form-label-required">*</span>
			</label>
			<div  class="return-authorization-form-controls" data-validation="control">
				<select name="itemUsed" id="return-authorization-item-used" data-toggle="false" class="return-authorization-form-item-actions-options">
          <option data-toggle="false" disabled selected value="null">Select an option</option>
          <option data-toggle="false" value="1">Yes</option>
          <option data-toggle="false" value="2">No</option>
        </select>
			</div>
		</div>
    <div class="return-authorization-form-group" data-validation="control-group">
			<label class="return-authorization-form-group-label" for="isInpakage">
				{{translate 'Do you still have or is it still in the original packaging?'}}
				<span class="return-authorization-form-label-required">*</span>
			</label>
			<div  class="return-authorization-form-controls" data-validation="control">
				<select name="isInpakage" id="return-authorization-is-in-pakage" data-toggle="false" class="return-authorization-form-item-actions-options">
          <option data-toggle="false" disabled selected value="null">Select an option</option>
          <option data-toggle="false" value="1">Yes</option>
          <option data-toggle="false" value="2">No</option>
        </select>
			</div>
		</div>
		{{#if activeLinesLengthGreaterThan1}}
			<a href="#" class="return-authorization-form-item-actions-apply-reason-button" data-action="apply-reason" data-toggle="false">{{translate 'Apply to all'}}</a>
		{{/if}}

	{{else}}
		<input type="text" data-action="reason-text" name="reason-text" value="{{textReason}}" data-toggle="false" class="return-authorization-form-item-actions-other-reason-text">
	{{/if}}
{{/if}}

{{!----
The context variables for this template are not currently documented. Use the {{log this}} helper to view the context variables in the Console of your browser's developer tools.

----}}

jj_transaction_line_views_cell_selectable_actionable_navigable.tpl

<tr class="transaction-line-views-cell-selectable-actionable-navigable-row{{#if isLineChecked}} selected{{/if}}" data-action="{{actionType}}" data-id="{{lineId}}">
	<td class="transaction-line-views-cell-selectable-actionable-navigable-select">
		{{#if isReturnable}} <input type="checkbox" value="{{itemId}}" data-action="select" {{#if isLineChecked}}checked{{/if}}> {{/if}}
	</td>

	<td class="transaction-line-views-cell-selectable-actionable-navigable-thumbnail">
		<img class="transaction-line-views-cell-selectable-actionable-navigable-thumbnail-image" src="{{resizeImage thumbnail.url 'thumbnail'}}" alt="{{thumbnail.altimagetext}}">
	</td>

	<td class="transaction-line-views-cell-selectable-actionable-navigable-details">
		<div class="transaction-line-views-cell-selectable-actionable-navigable-name">
      {{#if isNavigable}}
			<a {{{linkAttributes}}} class="">
        {{itemName}}
			</a>
			{{else}}
			<span class="transaction-line-views-cell-selectable-actionable-navigable-viewonly">
        {{itemName}}
			</span>
			{{/if}}
      {{#unless isReturnable}}
      <span class="global-views-message global-views-message-error alert">Sorry, this is a non-returnable item.</span>
      {{/unless}}
		</div>

		<div class="transaction-line-views-cell-selectable-actionable-navigable-price">
			<div data-view="Item.Price"></div>
		</div>

		<div data-view="Item.Sku"></div>

		<div class="transaction-line-views-cell-selectable-actionable-navigable-options">
			<div data-view="Item.SelectedOptions"></div>
		</div>
	</td>

	<td class="transaction-line-views-cell-selectable-actionable-navigable-extras">
		<div class="" data-view="Item.Summary.View"></div>
	</td>

	<td class="transaction-line-views-cell-selectable-actionable-navigable-actions">
		<div data-view="Item.Actions.View" class=""></div>
	</td>
</tr>


{{!----
The context variables for this template are not currently documented. Use the {{log this}} helper to view the context variables in the Console of your browser's developer tools.

----}}

Suite Script:

// JJ.Return.Authorization.js
// Load all your starter dependencies in backend for your extension here
// ----------------

define('JJ.Return.Authorization'
,	[
		'ReturnAuthorization.Model',
		'Application',
		'underscore'
	]
,	function (
	ReturnAuthorizationModel, Application, _
	)
{
	'use strict';
	_.extend(ReturnAuthorizationModel, {
		// @method create
		// @param data
		// @return {Number}
		//create function is extending for storing the newfield values in Return form of NetSuite.
		create: function (data) {
			const returnAuthorization = nlapiTransformRecord(
					data.type,
					data.id,
					'returnauthorization'
			);
			const CURRENT_LINE = this.getTransactionLines(data.id);
			this.setLines(returnAuthorization, data.lines, CURRENT_LINE);
			returnAuthorization.setFieldValue('memo', data.comments);
			_.each(data.lines, function (line, key) {
				returnAuthorization.setLineItemValue('item', 'custcol_jj_returns_item_used', key + 1, line.custcol_jj_returns_item_used);
				returnAuthorization.setLineItemValue('item', 'custcol_jj_returns_item_damaged', key + 1, line.custcol_jj_returns_item_damaged);
				returnAuthorization.setLineItemValue('item', 'custcol_jj_returns_item_inpackage', key + 1, line.custcol_jj_returns_item_inpackage);
				
			});
			return nlapiSubmitRecord(returnAuthorization);
		},
	})
});

Leave a comment

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