Scripting
Integration Patterns
This guide covers common patterns for integrating Licentra into different types of SuiteScripts and various use cases.
Script Type Patterns
User Event Scripts
User Event scripts are ideal for controlling feature access at the record level.
Pattern: Conditional UI Elements
Code
/** * @NApiVersion 2.1 * @NScriptType UserEventScript * @NModuleScope SameAccount */ define( ['/SuiteBundles/Bundle 571165/licentra_lib'], (licentraLib) => { const beforeLoad = (context) => { const featureId = 'ADVANCED_VALIDATION'; try { const status = licentraLib.isFeatureEnabled(featureId); if (status.enabled) { // Add advanced validation button context.form.addButton({ id: 'custpage_advanced_validate', label: 'Advanced Validation', functionName: 'performAdvancedValidation' }); } else { // Add informational message context.form.addField({ id: 'custpage_upgrade_message', type: 'inlinehtml', label: 'Upgrade Available' }).setDefaultValue( `<div style="color: blue;">Upgrade to access advanced validation features</div>` ); } } catch (error) { log.error('Feature Check Error', error.message); } }; return { beforeLoad }; } );
Pattern: Conditional Field Display
Code
const beforeLoad = (context) => { const featureId = 'CUSTOM_FIELDS'; try { const status = licentraLib.isFeatureEnabled(featureId); if (!status.enabled) { // Hide custom fields when feature is disabled const customFields = [ 'custbody_custom_field_1', 'custbody_custom_field_2', 'custbody_custom_field_3' ]; customFields.forEach(fieldId => { const field = context.form.getField(fieldId); if (field) { field.setDisplayType('hidden'); } }); } } catch (error) { log.error('Field Display Error', error.message); } };
Client Scripts
Client Scripts are perfect for controlling UI behavior and user interactions.
Pattern: Dynamic Button States
Code
/** * @NApiVersion 2.1 * @NScriptType ClientScript * @NModuleScope SameAccount */ define( ['/SuiteBundles/Bundle 571165/licentra_lib'], (licentraLib) => { const pageInit = (context) => { const featureId = 'BULK_OPERATIONS'; try { const status = licentraLib.isFeatureEnabled(featureId); if (!status.enabled) { // Disable bulk operation buttons const bulkButtons = [ 'custpage_bulk_edit_btn', 'custpage_bulk_delete_btn', 'custpage_bulk_export_btn' ]; bulkButtons.forEach(buttonId => { const button = document.getElementById(buttonId); if (button) { button.disabled = true; button.title = `Feature not available: ${status.message}`; } }); } } catch (error) { console.error('Client Script Error:', error); } }; return { pageInit }; } );
Pattern: Feature Toggle with User Feedback
Code
const pageInit = (context) => { const featureId = 'REAL_TIME_SYNC'; try { const status = licentraLib.isFeatureEnabled(featureId); if (status.enabled) { // Enable real-time sync functionality enableRealTimeSync(); } else { // Show upgrade prompt showUpgradePrompt(status.message); } } catch (error) { console.error('Sync Feature Error:', error); // Fallback to manual sync enableManualSync(); } }; function showUpgradePrompt(message) { const prompt = document.createElement('div'); prompt.innerHTML = ` <div style="background: #fff3cd; border: 1px solid #ffeaa7; padding: 10px; margin: 10px 0; border-radius: 4px;"> <strong>Upgrade Available:</strong> ${message} <button onclick="upgradeFeature()" style="margin-left: 10px; padding: 5px 10px;">Upgrade Now</button> </div> `; document.body.insertBefore(prompt, document.body.firstChild); }
Suitelets
Suitelets are server-side scripts that can control access to custom pages and functionality.
Pattern: Access Control
Code
/** * @NApiVersion 2.1 * @NScriptType SuiteletScript * @NModuleScope SameAccount */ define( ['/SuiteBundles/Bundle 571165/licentra_lib'], (licentraLib) => { const onRequest = (context) => { const featureId = 'ADMIN_DASHBOARD'; try { const status = licentraLib.isFeatureEnabled(featureId); if (!status.enabled) { // Return access denied page context.response.write(` <html> <head><title>Access Denied</title></head> <body> <h1>Access Denied</h1> <p>This feature is not available: ${status.message}</p> <p><a href="/app/center/card.nl?sc=-29&whence=">Return to Dashboard</a></p> </body> </html> `); return; } // Render the admin dashboard renderAdminDashboard(context); } catch (error) { log.error('Suitelet Access Error', error.message); context.response.write('An error occurred while checking access permissions'); } }; return { onRequest }; } );
Pattern: Feature-Based Content
Code
const onRequest = (context) => { const features = { 'BASIC_REPORTS': false, 'ADVANCED_REPORTS': false, 'EXPORT_FEATURES': false }; try { // Check multiple features Object.keys(features).forEach(featureId => { const status = licentraLib.isFeatureEnabled(featureId); features[featureId] = status.enabled; }); // Render content based on available features renderFeatureBasedContent(context, features); } catch (error) { log.error('Feature Check Error', error.message); // Render basic content as fallback renderBasicContent(context); } };
Scheduled Scripts
Scheduled Scripts can use Licentra to control batch operations and automated processes.
Pattern: Conditional Processing
Code
/** * @NApiVersion 2.1 * @NScriptType ScheduledScript * @NModuleScope SameAccount */ define( ['/SuiteBundles/Bundle 571165/licentra_lib'], (licentraLib) => { const execute = (context) => { const featureId = 'AUTOMATED_CLEANUP'; try { const status = licentraLib.isFeatureEnabled(featureId); if (status.enabled) { // Perform automated cleanup performAutomatedCleanup(); log.audit('Cleanup Completed', 'Automated cleanup process completed successfully'); } else { log.audit('Cleanup Skipped', `Automated cleanup skipped: ${status.message}`); } } catch (error) { log.error('Scheduled Script Error', error.message); } }; return { execute }; } );
Use Case Patterns
Graceful Degradation
Provide alternative functionality when features are disabled.
Code
function handleFeatureWithFallback(featureId, premiumFunction, fallbackFunction) { try { const status = licentraLib.isFeatureEnabled(featureId); if (status.enabled) { premiumFunction(); } else { log.debug('Using Fallback', `Feature ${featureId} disabled, using fallback`); fallbackFunction(); } } catch (error) { log.error('Feature Error', error.message); fallbackFunction(); } } // Usage handleFeatureWithFallback( 'ADVANCED_SEARCH', () => performAdvancedSearch(), () => performBasicSearch() );
User Experience Enhancement
Provide clear feedback and upgrade paths to users.
Code
function enhanceUserExperience(featureId, elementId) { try { const status = licentraLib.isFeatureEnabled(featureId); if (!status.enabled) { const element = document.getElementById(elementId); if (element) { element.innerHTML = ` <div style="text-align: center; padding: 20px; background: #f8f9fa; border-radius: 8px;"> <h3>Upgrade Available</h3> <p>${status.message}</p> <button onclick="showUpgradeOptions()" class="btn btn-primary"> Learn More </button> </div> `; } } } catch (error) { console.error('UX Enhancement Error:', error); } }
Error Handling Patterns
Robust Error Handling
Code
function safeFeatureCheck(featureId, defaultValue = false) { try { const status = licentraLib.isFeatureEnabled(featureId); return status.enabled; } catch (error) { log.error('Feature Check Failed', { featureId: featureId, error: error.message, stack: error.stack }); return defaultValue; } } // Usage with fallback const isFeatureEnabled = safeFeatureCheck('MY_FEATURE', false);
Retry Pattern
Code
function checkFeatureWithRetry(featureId, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const status = licentraLib.isFeatureEnabled(featureId); return status.enabled; } catch (error) { log.warning('Feature Check Attempt Failed', { attempt: attempt, featureId: featureId, error: error.message }); if (attempt === maxRetries) { log.error('Feature Check Failed After Retries', { featureId: featureId, maxRetries: maxRetries }); return false; } // Wait before retry (exponential backoff) const delay = Math.pow(2, attempt) * 1000; setTimeout(() => {}, delay); } } }
These patterns provide a solid foundation for integrating Licentra into your NetSuite solutions while ensuring robust error handling and excellent user experience.
Last modified on
