Here is sample suitelet that fetches the sales order Id or customer Id given and returns the sales order from the netsuite.
define(['N/search', 'N/url', 'N/file'],
(search, url, file) => {
"use strict";
const BACKGROUND_IMAGE_PATH = 'SuiteScripts/Jobin and Jismi IT ServicesLLP/CRYS-94 QR Code Scanning/layer.svg';
const LOGO_FILE_PATH = 'SuiteScripts/Jobin and Jismi IT ServicesLLP/CRYS-94 QR Code Scanning/CT-Logo-900x214.png';
const SCRIPT_ID_UPDATE_SO = 'customscript_jj_sl_so_details_crys_192';
const DEPLOY_ID_UPDATE_SO = 'customdeploy_jj_sl_so_details_crys_192';
function getSalesOrderDetails(customer, salesOrder) {
try {
let searchFilter = [
["type", "anyof", "SalesOrd"],
// "AND",
// ["status", "anyof", "SalesOrd:G"],
"AND",
["mainline", "is", "T"]
];
if (customer) {
searchFilter.push("AND", ["name", "anyof", customer]);
}
else if (salesOrder) {
searchFilter.push("AND", ["internalid", "anyof", salesOrder]);
}
let salesorderSearchObj = search.create({
type: "salesorder",
filters: searchFilter,
columns:
[search.createColumn({ name: "internalid", label: "Internal ID" }),
search.createColumn({ name: "tranid", label: "Document Number" }),
search.createColumn({ name: "entity", label: "Name" }),
search.createColumn({ name: "statusref", label: "Status" }),
]
});
let results = [];
log.debug('filterArray', searchFilter)
let searchResultCount = salesorderSearchObj.runPaged().count;
log.debug("Sales Order Search Count", searchResultCount);
salesorderSearchObj.run().each((result) => {
results.push({
salesOrderId: result.getValue({ name: "internalid" }),
salesOrderNo: result.getValue({ name: "tranid" }),
customerName: result.getText({ name: "entity" }),
status: result.getText({ name: "statusref" })
});
return true;
});
return results;
} catch (error) {
log.error('error @getSalesOrderDetails', e);
return {};
}
}
function salesOrderSelect(scriptContext, backgroundFileUrl, fullFileUrl, urlUpdateSO) {
try {
let htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sales Order Update</title>
<style>
body {
font-family: 'Montserrat', sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
flex-direction: column;
background: url('${backgroundFileUrl.replace(/"/g, '"')}') no-repeat center center/cover;
}
.container {
max-width: 600px;
width: 90%;
padding: 20px;
text-align: center;
border: 1px solid #ddd;
border-radius: 10px;
background: rgba(220, 220, 220, 0.25);
margin-bottom: 20px;
}
.results-container {
max-width: 900px;
width: 90%;
padding: 20px;
border: 1px solid #ddd;
border-radius: 10px;
background: rgba(220, 220, 220, 0.25);
text-align: center;
overflow-x: auto;
}
/* Logo Styling */
.logo {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
.logo img {
max-width: 180px; /* Ensures a max width for responsiveness */
height: auto; /* Maintains aspect ratio */
object-fit: contain;
}
h1 {
font-size: 1.8rem;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 20px;
}
.input-group {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 15px;
}
label {
font-size: 1rem;
font-weight: bold;
margin-bottom: 5px;
}
input {
padding: 10px;
font-size: 16px;
border: 1px solid #999;
border-radius: 5px;
width: 100%;
box-sizing: border-box;
}
button {
padding: 10px 20px;
font-size: 16px;
border: none;
background-color: #007bff;
color: white;
cursor: pointer;
border-radius: 5px;
width: 100%;
box-sizing: border-box;
}
button:hover {
background-color: #0056b3;
}
#salesOrderList {
margin-top: 20px;
max-height: 400px;
overflow-y: auto;
box-sizing: border-box;
}
table {
width: 100%;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin-top: 20px;
table-layout: auto;
min-width: 800px;
}
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
white-space: nowrap;
}
th {
background-color: #4CAF50;
color: white;
font-size: 1rem;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}
a {
text-decoration: none;
color: #007bff;
font-weight: bold;
}
a:hover {
color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<!-- Logo Section -->
<div class="logo">
<img src="${fullFileUrl.replace(/"/g, '"')}" alt="Company Logo">
</div>
<!-- Search Form Container -->
<h1>Sales Order Updation</h1>
<div class="form-group">
<div class="input-group">
<label for="salesOrderId">Enter Sales Order ID:</label>
<input type="text" id="salesOrderId" placeholder="Enter Sales Order ID">
</div>
<div class="input-group">
<label for="customerId">Enter Customer ID:</label>
<input type="text" id="customerId" placeholder="Enter Customer ID">
</div>
<button id="fetchSalesOrders">SEARCH</button>
</div>
</div>
<!-- Results Container -->
<div class="results-container">
<h2>Search Results</h2>
<div id="salesOrderList"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("fetchSalesOrders").addEventListener("click", fetchSalesOrders);
});
let urlUpdateSO = "${urlUpdateSO}";
function fetchSalesOrders() {
let salesOrderId = document.getElementById("salesOrderId").value.trim();
let customerId = document.getElementById("customerId").value.trim();
let resultElement = document.getElementById("salesOrderList");
if (!salesOrderId && !customerId) {
resultElement.innerHTML = "<p style='color: red;'>⚠️ Please enter at least one search field</p>";
return;
}
fetch(window.location.href, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ salesOrderId, customerId })
})
.then(response => response.json())
.then(data => {
if (data.success && data.orders.length > 0) {
let tableHtml = `
<table>
<tr>
<th>No</th>
<th>Sales Order No</th>
<th>Customer Name</th>
<th>Status</th>
<th>Update</th>
</tr>`;
data.orders.forEach((order, index) => {
tableHtml += `
<tr>
<td>${index + 1}</td>
<td>${order.salesOrderNo}</td>
<td>${order.customerName}</td>
<td>${order.status}</td>
<td><a href="${urlUpdateSO}&salesOrderId=${order.salesOrderId}" target="_blank">Update</a></td>
</tr>`;
});
tableHtml += "</table>";
resultElement.innerHTML = tableHtml;
setTimeout(() => {
window.scrollTo({ top: 0, behavior: 'smooth' });
resultElement.scrollTop = 0;
}, 100);
} else {
resultElement.innerHTML = "<p style='color: red;'>❌ No Sales Orders Found</p>";
}
})
.catch(error => {
console.error("Error:", error);
resultElement.innerHTML = "<p style='color: red;'>❌ Error fetching Sales Orders</p>";
});
}
</script>
</body>
</html>`;
scriptContext.response.write(htmlContent);
} catch (e) {
log.error('Error @ salesOrderSelect', e);
}
}
/**
*
* @param {*} request
* @returns
*/
function checkIfExternal(request) {
try {
let host = request.headers['host'];
// Ensure host is defined before proceeding
if (!host) {
throw new Error("Host header is undefined");
}
// NetSuite external URLs usually contain '.extforms.netsuite.com'
return host.includes('.extforms.netsuite.com');
} catch (error) {
log.error("Error in checkIfExternal", error);
return false; // Default to false in case of an error
}
}
/**
* Retrieves the full URL of a file given its path or ID.
*
* @param {string} filePath - The path or ID of the file to load.
* @returns {string} The full URL of the file, or an empty string if an error occurs.Domain(filePath)
*/
function getFileUrl(filePath) {
try {
// Load the file using its path or ID
let fileObj = file.load({
id: filePath
});
// Retrieve the relative URL of the file
let fileRelativeUrl = fileObj.url;
// Use the `N / url` module to get the base domain dynamically
let baseDomain = url.resolveDomain({ hostType: url.HostType.APPLICATION });
// Construct and return the full file URL
return 'https://' + baseDomain + fileRelativeUrl;
} catch (error) {
log.error("Error loading file", error);
return '';
}
}
/**
* Resolves the URL for a given script and deployment.
*
* @param {string} scriptId - The internal ID of the script.
* @param {string} deploymentId - The internal ID of the script deployment.
* @returns {string} The resolved URL for the script deployment.
*/
function resolveScriptUrl(scriptId, deploymentId, isExternal) {
try {
return url.resolveScript({
scriptId: scriptId,
deploymentId: deploymentId,
returnExternalUrl: isExternal,
});
} catch (error) {
log.error('error @resolveScriptUrl',error)
}
}
/**
* Defines the Suitelet script trigger point.
* @param {Object} scriptContext
* @param {ServerRequest} scriptContext.request - Incoming request
* @param {ServerResponse} scriptContext.response - Suitelet response
* @since 2015.2
*/
const onRequest = (scriptContext) => {
try {
let isExternal = false;
isExternal = checkIfExternal(scriptContext.request);
log.debug('isExternal', isExternal);
let urlUpdateSO = resolveScriptUrl(SCRIPT_ID_UPDATE_SO, DEPLOY_ID_UPDATE_SO, isExternal);
if (scriptContext.request.method === 'GET') {
let backgroundFileUrl = getFileUrl(BACKGROUND_IMAGE_PATH);
let fullFileUrl = getFileUrl(LOGO_FILE_PATH);
salesOrderSelect(scriptContext, backgroundFileUrl, fullFileUrl, urlUpdateSO);
}
else if (scriptContext.request.method === 'POST') {
log.debug('scriptContext', scriptContext.request.body);
let requestData = JSON.parse(scriptContext.request.body); // Parse incoming JSON data
let salesOrders = getSalesOrderDetails(requestData.customerId, requestData.salesOrderId);
scriptContext.response.write(JSON.stringify({
success: true,
orders: salesOrders,
urlUpdateSO: urlUpdateSO
}));
}
}
catch (e) {
log.error('error @onRequest', e);
scriptContext.response.write(JSON.stringify({
success: false,
message: e.message
}));
}
};
return { onRequest };
});

