Suitlet Script
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define(['N/log', 'N/record'],
/**
* @param{log} log
* @param{record} record
*/
(log, record) => {
/**
* 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) => {
if (scriptContext.request.method === 'POST') {
try {
let request = scriptContext.request;
let goldPrice = request.parameters.gold_price;
let currency = request.parameters.currency;
// Create the custom record
let newRecord = record.create({
type: 'customrecord_jj_daily_good_price',
isDynamic: true
});
newRecord.setValue({
fieldId: 'custrecord_jj_dgp_gold_price',
value: goldPrice
});
newRecord.setValue({
fieldId: 'custrecord_jj_dgp_currency',
value: currency
});
let recordId = newRecord.save();
scriptContext.response.write(`
<script>
window.history.back(); // Go back to the previous page
</script>
`);
} catch (error) {
log.error("Error Creating Custom Record", error.message);
scriptContext.response.write(`
<script>
window.history.back(); // Go back to the previous page
</script>
`);
}
}
}
return {onRequest}
});
Portlet Script
/**
* @NApiVersion 2.1
* @NScriptType Portlet
*/
define(['N/record', 'N/search', 'N/ui/serverWidget', 'N/url'],
/**
* @param{record} record
* @param{search} search
* @param{serverWidget} serverWidget
* @param{url} url
*/
function (record, search, serverWidget, url) {
/**
* Defines the Portlet script trigger point.
* @param {Object} params - The params parameter is a JavaScript object. It is automatically passed to the script entry
* point by NetSuite. The values for params are read-only.
* @param {Portlet} params.portlet - The portlet object used for rendering
* @param {string} params.column - Column index forthe portlet on the dashboard; left column (1), center column (2) or
* right column (3)
* @param {string} params.entity - (For custom portlets only) references the customer ID for the selected customer
* @since 2015.2
*/
const render = (params) => {
try {
let portlet = params.portlet;
portlet.title = ' ';
// Fetch the most recent custom record
let dailyGoldPriceSearch = search.create({
type: 'customrecord_jj_daily_good_price',
columns: [
search.createColumn({ name: "internalid", sort: search.Sort.DESC, label: "internalid" }),
search.createColumn({name: "custrecord_jj_dgp_currency", label: "Currency"}),
search.createColumn({ name: "custrecord_jj_dgp_gold_price", label: "Gold Price" }),
search.createColumn({
name: "symbol",
join: "CUSTRECORD_JJ_DGP_CURRENCY",
label: "Symbol"
})
],
filters: [
['isinactive', 'is', 'F'],
'AND',
["custrecord_jj_dgp_date", "within", "today"]
]
});
let todaysGoldPriceList = [];
// Fetch all currencies from NetSuite
let currencyOptions = '';
search.create({
type: 'currency',
filters: ["isinactive","is","F"],
columns: [
search.createColumn({ name: "internalid", sort: search.Sort.ASC, label: "Internal ID" }),
search.createColumn({ name: "name", label: "Currency Name" }),
search.createColumn({ name: "symbol", label: "Symbol" })
]
}).run().each((result) => {
let currencyId = result.getValue('internalid');
let currencyName = result.getValue('name');
let currencySymbol = result.getValue('symbol');
currencyOptions += `<option value="${currencyId}">${currencyName}</option>`;
todaysGoldPriceList.push({
currencyId: currencyId,
currencyName: currencyName,
currencySymbol: currencySymbol
});
return true; // Continue iterating
});
dailyGoldPriceSearch.run().each(result => {
let currency = result.getValue({ name: 'custrecord_jj_dgp_currency' });
let goldPrice = result.getValue({ name: 'custrecord_jj_dgp_gold_price' });
// Format gold price with commas
let formattedGoldPrice = goldPrice ? new Intl.NumberFormat('en-US', {
style: 'decimal',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(goldPrice) : 'Not Available';
// Check if the currencyId exists in todaysGoldPriceList and if gold price is not already set
let currencyEntry = todaysGoldPriceList.find(entry => entry.currencyId === currency);
if (currencyEntry && !currencyEntry.hasOwnProperty('goldPrice')) {
currencyEntry.goldPrice = formattedGoldPrice;
}
return true; // Continue iteration
});
log.debug('Updated Todays Gold Price List', JSON.stringify(todaysGoldPriceList));
let tbodyContent = todaysGoldPriceList.map(item => `
<tr>
<td>${item.currencyName} (${item.currencySymbol})</td>
<td class= "td-price">${item.goldPrice || 'Not Available'}</td>
</tr>
`).join('');
let suiteletUrl = url.resolveScript({
scriptId: 'customscript_jj_sl_update_gold_price',
deploymentId: 'customdeploy_jj_sl_update_gold_price',
returnExternalUrl: false
});
portlet.html = `
<style>
.form-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
padding: 20px;
border-radius: 8px;
background: linear-gradient(135deg, #fff5d1, #fff8e5);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 600px;
margin: 20px auto;
}
.form-group {
flex: 1 1 calc(50% - 15px); /* Take 50% of space or adjust dynamically */
display: flex;
flex-direction: column;
margin-bottom: 10px;
}
.form-group-full {
flex: 1 1 100%; /* Full row */
}
.form-group label {
margin-bottom: 5px;
font-weight: bold;
color: #856404; /* Gold shade for labels */
}
.form-group input,
.form-group select {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
background-color: #fff;
height: 40px; /* Set consistent height for all fields */
}
.submit-button {
padding: 12px 25px;
font-size: 16px;
font-weight: bold;
color: #fff;
background: linear-gradient(90deg, #f4d03f, #d4ac0d);
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s ease;
width: 100%;
}
.submit-button:hover {
background: linear-gradient(90deg, #d4ac0d, #a67c00);
}
.price-display {
text-align: center;
font-size: 24px;
font-weight: bold;
margin-bottom: 15px;
color: #d4ac0d; /* Gold shade for the price display */
}
table {
max-width: 600px;
width: 100%;
border-collapse: collapse;
margin: 20px auto;
text-align: left;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
}
th {
font-size: 16px;
font-weight: bold;
background-color: #f4f4f4;
}
td {
font-size: 14px;
font-weight: normal;
color: #000000;
}
.td-price {
text-align: right;
}
</style>
<div class="price-display">
Today's Gold Price:
<table>
<thead>
<tr>
<th>Currency</th>
<th>Price</th>
</tr>
</thead>
<tbody>
${tbodyContent}
</tbody>
</table>
</div>
<form action="${suiteletUrl}" method="POST" class="form-container">
<div class="form-group">
<label for="gold_price">Gold Price:</label>
<input type="number" id="gold_price" name="gold_price" step="0.01" min="0" required />
</div>
<div class="form-group">
<label for="currency">Currency:</label>
<select id="currency" name="currency" required>
${currencyOptions}
</select>
</div>
<div class="form-group-full" style="text-align: center;">
<input type="submit" value="Update Gold Price" class="submit-button" />
</div>
</form>
`;
} catch (error) {
log.debug("Error in Portlet Script", error.message);
}
}
return { render }
});