netsuite
Evénement utilisateur: événements avant et après la soumission
Recherche…
Syntaxe
- beforeSubmit (type) // Before Submit, 1.0
- beforeSubmit (scriptContext) // Avant la soumission, 2.0
- afterSubmit (type) // Après soumission, 1.0
- afterSubmit (scriptContext) // Après soumission, 2.0
Paramètres
Paramètre | Détails |
---|---|
SuiteScript 2.0 | - |
scriptContext | {Object} |
scriptContext.newRecord | {N/record.Record} Une référence à l'enregistrement en cours de lecture dans la base de données. Nous pouvons l'utiliser pour modifier les valeurs de champ sur l'enregistrement |
scriptContext.oldRecord | {N/record.Record} Une référence en lecture seule à l'état précédent de l'enregistrement. Nous pouvons l'utiliser pour comparer aux nouvelles valeurs |
scriptContext.type | {UserEventType} Une énumération du type d'action d'écriture en cours d'exécution |
SuiteScript 1.0 | - |
type | {String} Le type d'action d'écriture en cours d'exécution |
Remarques
beforeSubmit
et afterSubmit
Ces deux événements sont déclenchés par toute opération d'écriture de base de données sur un enregistrement. Chaque fois qu'un utilisateur, un script, une importation CSV ou une demande de service Web tente d'écrire un enregistrement dans la base de données, les événements Submit sont déclenchés.
Enregistrez les actions qui déclenchent les deux événements Submit:
- Créer
- modifier
- Effacer
- XEdit (modification en ligne)
- Approuver
- Rejeter
- Annuler
- Pack
- Navire
Enregistrez les actions qui déclenchent avant la beforeSubmit
uniquement:
- Mark Complete
- Réassigner (cas de support)
- Modifier les prévisions
Enregistrez les actions qui déclenchent afterSubmit
uniquement:
- Dropship
- Commande spéciale
- Items commandés
- Payer les factures
Cas d'utilisation typiques pour beforeSubmit
- Valider l'enregistrement avant qu'il ne soit engagé dans la base de données
- Vérification des autorisations et des restrictions
- Modifications de dernière minute avant la validation de la base de données
- Tirez les mises à jour des systèmes externes
Cas d'utilisation typiques pour afterSubmit
- Notification par email des modifications d'enregistrement
- Redirection du navigateur
- Créer / mettre à jour des enregistrements dépendants
- Poussez les changements sur les systèmes externes
Les événements utilisateur ne sont pas enchaînés
Le code écrit dans les événements utilisateur ne déclenche aucun événement utilisateur sur d' autres enregistrements. Par exemple, la modification de l'enregistrement client associé à l' beforeSubmit
d'un enregistrement de commande client ne déclenchera pas les événements de soumission de l'enregistrement client.
NetSuite fait cela pour éviter que des événements utilisateur se déclenchent dans une boucle infinie. Si vous avez besoin d' événements utilisateur pour tirer dans une séquence enchaînée, d' autres types de script (par exemple RESTlets, Suitelets, Scripts programmés) devront être injectés entre les événements.
Les gestionnaires d'événements renvoient un void
Le type de retour des gestionnaires d'événements Submit est void
. Toute donnée renvoyée par notre gestionnaire d'événement n'a aucun effet sur le système. Nous n'avons pas besoin de renvoyer quelque chose de notre fonction de gestionnaire car nous ne pouvons rien faire avec sa valeur renvoyée.
!! MISE EN GARDE !!
Soyez très prudent lorsque vous comparez les valeurs entre les anciens et les nouveaux enregistrements. Les champs vides de l' ancien enregistrement sont renvoyés comme null
, tandis que les champs vides du nouvel enregistrement sont renvoyés sous forme de chaîne vide. Cela signifie que vous ne pouvez pas simplement comparer l’ancien avec le nouveau ou que vous obtenez des faux positifs. Toute logique que vous écrivez doit gérer le cas où l'un est null
et l'autre est une chaîne vide appropriée.
Minimal: enregistrer un message
// 1.0, Revealing Module pattern
var myNamespace = myNamespace || {};
myNamespace.example = (function () {
/**
* User Event 1.0 example detailing usage of the Submit events
*
* @appliedtorecord employee
*/
var exports = {};
function beforeSubmit(type) {
nlapiLogExecution("DEBUG", "Before Submit", "action=" + type);
}
function afterSubmit(type) {
nlapiLogExecution("DEBUG", "After Submit", "action=" + type);
}
exports.beforeSubmit = beforeSubmit;
exports.afterSubmit = afterSubmit;
return exports;
})();
// 2.0
define(["N/log"], function (log) {
/**
* User Event 2.0 example showing usage of the Submit events
*
* @NApiVersion 2.x
* @NModuleScope SameAccount
* @NScriptType UserEventScript
* @appliedtorecord employee
*/
var exports = {};
function beforeSubmit(scriptContext) {
log.debug({
"title": "Before Submit",
"details": "action=" + scriptContext.type
});
}
function afterSubmit(scriptContext) {
log.debug({
"title": "After Submit",
"details": "action=" + scriptContext.type
});
}
exports.beforeSubmit = beforeSubmit;
exports.afterSubmit = afterSubmit;
return exports;
});
Avant de soumettre: Valider l'enregistrement avant qu'il ne soit engagé dans la base de données
Pour cet exemple, nous voulons nous assurer que tous les employés marqués comme ressource de projet ont également un coût de main-d'œuvre approprié défini.
// 1.0, Revealing Module pattern
var myNamespace = myNamespace || {};
myNamespace.example = (function () {
/**
* User Event 1.0 example detailing usage of the Submit events
*
* @appliedtorecord employee
*/
var exports = {};
function beforeSubmit(type) {
if (!isEmployeeValid(nlapiGetNewRecord())) {
throw nlapiCreateError("STOIC_ERR_INVALID_DATA", "Employee data is not valid", true);
}
}
function isEmployeeValid(employee) {
return (!isProjectResource(employee) || hasValidLaborCost(employee));
}
function isProjectResource(employee) {
return (employee.getFieldValue("isjobresource") === "T");
}
function hasValidLaborCost(employee) {
var laborCost = parseFloat(employee.getFieldValue("laborcost"));
return (Boolean(laborCost) && (laborCost > 0));
}
exports.beforeSubmit = beforeSubmit;
return exports;
})();
// 2.0
define(["N/error"], function (err) {
var exports = {};
/**
* User Event 2.0 example detailing usage of the Submit events
*
* @NApiVersion 2.x
* @NModuleScope SameAccount
* @NScriptType UserEventScript
* @appliedtorecord employee
*/
function beforeSubmit(scriptContext) {
if (!isEmployeeValid(scriptContext)) {
throw err.create({
"name": "STOIC_ERR_INVALID_DATA",
"message": "Employee data is not valid",
"notifyOff": true
});
}
}
function isEmployeeValid(scriptContext) {
return (!isProjectResource(scriptContext.newRecord) || hasValidLaborCost(scriptContext.newRecord));
}
function isProjectResource(employee) {
return (employee.getValue({"fieldId" : "isjobresource"}));
}
function hasValidLaborCost(employee) {
var laborCost = employee.getValue({"fieldId" : "laborcost"});
return (Boolean(laborCost) && (laborCost > 0));
}
exports.beforeSubmit = beforeSubmit;
return exports;
});
Notez que nous transmettons des références au nouvel enregistrement dans notre validation car nous ne nous soucions pas des valeurs utilisées auparavant. Nous nous intéressons uniquement aux valeurs sur le point d'être écrites dans la base de données. En 2.0, nous le faisons via la référence scriptContext.newRecord
, et en 1.0, nous appelons la fonction globale nlapiGetNewRecord
.
Lorsque les données soumises ne sont pas valides, nous créons et générons une erreur. Dans un événement beforeSubmit
, afin d'éviter que les modifications ne soient écrites dans la base de données, votre fonction doit throw
une exception. Souvent, les développeurs essaient de return false
fonction, en s’attendant à ce que cela soit suffisant, mais cela ne suffit pas. Les objets d'erreur sont créés en 2.0 en utilisant le module N/error
et en 1.0 en utilisant la fonction globale nlapiCreateError
; nous soulevons ensuite une exception en utilisant notre objet d'erreur créé avec le mot-clé throw
.
Après envoi: détermine si un champ a été modifié
Une fois que l'enregistrement est stocké dans la base de données, nous voulons inspecter ce qui a été modifié dans l'enregistrement. Nous effectuerons cette inspection en comparant les valeurs entre l'ancienne et la nouvelle instance d'enregistrement.
// 1.0, Revealing Module pattern
var myNamespace = myNamespace || {};
myNamespace.example = (function () {
/**
* User Event 1.0 example detailing usage of the Submit events
*
* @appliedtorecord employee
*/
var exports = {};
function afterSubmit(type) {
notifySupervisor();
}
function notifySupervisor() {
// Old and New record instances are retrieved from global functions
var employee = nlapiGetNewRecord();
var prevEmployee = nlapiGetOldRecord();
// If Employee Status didn't change, there's nothing to do
if (!didStatusChange(employee, prevEmployee)) {
return;
}
// Otherwise, continue with business logic...
}
function didStatusChange(employee, prevEmployee) {
var status = employee.getFieldValue("employeestatus");
var prevStatus = prevEmployee.getFieldValue("employeestatus");
/* !! Caution !!
* Empty fields from the Old record come back as `null`
* Empty fields from the New record come back as an empty String
* This means you cannot simply compare the old and new
*/
return ((prevStatus || status) && (status !== prevStatus));
}
exports.afterSubmit = afterSubmit;
return exports;
})();
// 2.0
define(["N/runtime"], function (runtime) {
/**
* User Event 2.0 example detailing usage of the Submit events
*
* @NApiVersion 2.x
* @NModuleScope SameAccount
* @NScriptType UserEventScript
* @appliedtorecord employee
*/
var exports = {};
function afterSubmit(scriptContext) {
notifySupervisor(scriptContext);
}
function notifySupervisor(scriptContext) {
// Old and New records are simply properties on scriptContext
var employee = scriptContext.newRecord;
var prevEmployee = scriptContext.oldRecord;
// If Employee Status didn't change, there's nothing to do
if (!didStatusChange(employee, prevEmployee)) {
return;
}
// Otherwise, continue with business logic...
}
function didStatusChange(employee, prevEmployee) {
var status = employee.getValue({"fieldId" : "employeestatus"});
var prevStatus = prevEmployee.getValue({"fieldId" : "employeestatus"});
/* !! Caution !!
* Empty fields from the Old record come back as `null`
* Empty fields from the New record come back as an empty String
* This means you cannot simply compare the old and new
*/
return ((prevStatus || status) && (status !== prevStatus));
}
exports.afterSubmit = afterSubmit;
return exports;
});
Soyez très prudent lorsque vous comparez les valeurs entre les anciens et les nouveaux enregistrements. Les champs vides de l' ancien enregistrement sont renvoyés comme null
, tandis que les champs vides du nouvel enregistrement sont renvoyés sous forme de chaîne vide. Cela signifie que vous ne pouvez pas simplement comparer l’ancien avec le nouveau ou que vous obtenez des faux positifs. Toute logique que vous écrivez doit gérer le cas où l'un est null
et l'autre est une chaîne vide appropriée.