From 0ead75560028f9df00abdfefbb840142e957dc2a Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Mon, 11 May 2026 17:19:01 -0400 Subject: [PATCH 1/3] Fix typo in VolumeSourceFieldRegularExpression setting comparison. --- Code.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code.lua b/Code.lua index ee9c07e..859d8a5 100644 --- a/Code.lua +++ b/Code.lua @@ -830,7 +830,7 @@ function HandleRequests () Log:DebugFormat("Found transaction number {0} in \"{1}\"", tn, Settings.RequestMonitorQueue) local regex - if Settings.VolumeSourceFieldRegularExpressionn and Settings.VolumeSourceFieldRegularExpression ~= "" then + if Settings.VolumeSourceFieldRegularExpression and Settings.VolumeSourceFieldRegularExpression ~= "" then regex = Types["Regex"](Settings.VolumeSourceFieldRegularExpression) Log:DebugFormat("Found Regex \"{0}\" for VolumeSourceField.", Settings.VolumeSourceFieldRegularExpression) else From 33c97b0605e24295638741c2de6766fc1f49c732 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 12 May 2026 11:21:14 -0400 Subject: [PATCH 2/3] Add Sierra item location mapping (v1.3.0) - New LocationDestinationField / LocationValueType settings populate the matched item's location into a Transaction column; missing location warns and continues rather than erroring. - Redact ClientKey, ClientSecret, and Sierra access tokens from DEBUG logs. - Harden regex-based volume parsing: skip the regex when the source field is blank, preserve the original value when the regex finds no match, and ignore zero-width matches. --- Code.lua | 53 ++++++++++++++++++++++++++++++++++++++++------------- Config.xml | 10 +++++++++- Readme.md | 18 ++++++++++++++++++ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/Code.lua b/Code.lua index 859d8a5..192922e 100644 --- a/Code.lua +++ b/Code.lua @@ -252,7 +252,7 @@ function SierraApi:UpdateAccessToken(clientKey, clientSecret) ]] local accessToken = self:GetAccessToken(clientKey, clientSecret) - SierraApi.Log:DebugFormat("Updated Access Token: {0}", accessToken) + SierraApi.Log:Debug("Updated Access Token: [REDACTED]") self.AccessToken = accessToken return accessToken end @@ -307,7 +307,7 @@ function SierraApi:GetAccessTokenResponse (clientKey, clientSecret) local authUploadSuccess, authUploadResult = pcall(function() - SierraApi.Log:DebugFormat("Encoded Client Key and Secret: {0}", encodedKeyAndSecret) + SierraApi.Log:Debug("Encoded Client Key and Secret: [REDACTED]") SierraApi.Log:DebugFormat("Posting to URL: {0}", authTokenUrl) return credentialWebClient:UploadString(authTokenUrl, uploadMethod, uploadBody) end) @@ -318,7 +318,7 @@ function SierraApi:GetAccessTokenResponse (clientKey, clientSecret) SierraApi.Log:Warn("Failure occurred while obtaining access token.") error(authUploadResult) else - SierraApi.Log:DebugFormat("Access Token Response: {0}", authUploadResult) + SierraApi.Log:Debug("Access Token Response: [REDACTED]") end @@ -737,6 +737,9 @@ Settings.VolumeSourceFieldRegularExpression = GetSetting("VolumeSourceFieldRegul Settings.ExactSearch = GetSetting("ExactSearch") Settings.ReplaceVolumeWhenNotNull = GetSetting("ReplaceVolumeWhenNotNull") +Settings.LocationDestinationField = GetSetting("LocationDestinationField") +Settings.LocationValueType = GetSetting("LocationValueType") + luanet.load_assembly("System") luanet.load_assembly("log4net") @@ -782,7 +785,11 @@ function TimerElapsed (eventArgs) Log:Debug("Addon Settings: ") for settingKey, settingValue in pairs(Settings) do - Log:DebugFormat("{0}: {1}", settingKey, settingValue) + if settingKey == "ClientKey" or settingKey == "ClientSecret" then + Log:DebugFormat("{0}: [REDACTED]", settingKey) + else + Log:DebugFormat("{0}: {1}", settingKey, settingValue) + end end local successfulAddonExecution, error = pcall(function() @@ -792,7 +799,7 @@ function TimerElapsed (eventArgs) end local accessToken = sierraApi:UpdateAccessToken(Settings.ClientKey, Settings.ClientSecret) - Log:DebugFormat("Generated Access Token: {0}", accessToken) + Log:Debug("Generated Access Token: [REDACTED]") ProcessDataContexts("TransactionStatus", Settings.RequestMonitorQueue, "HandleRequests") end) @@ -844,17 +851,16 @@ function HandleRequests () Log:DebugFormat("Getting BibID from transaction.{0}", Settings.BibIdSourceField) local transactionBibId = GetFieldValue("Transaction", Settings.BibIdSourceField) transactionBibId = transactionBibId:gsub("%D", "") - local transactionVolume - if regex ~= nil then - match = regex:Match(GetFieldValue("Transaction", Settings.VolumeSourceField)) - if match.Success then - Log:DebugFormat("Using Regex for volume source field {0} results in match \"{1}\"", - Settings.VolumeSourceField, match.Value) - transactionVolume = match.Value + local transactionVolume = GetFieldValue("Transaction", Settings.VolumeSourceField); + if regex ~= nil and NotNilOrBlank(transactionVolume) then + local match = regex:Match(transactionVolume); + if match.Success and match.Value ~= "" then + Log:DebugFormat("Using Regex for volume source field {0} results in match \"{1}\"", Settings.VolumeSourceField, match.Value); + transactionVolume = match.Value; end else Log:DebugFormat("Getting volume source field {0}", Settings.VolumeSourceField) - transactionVolume = GetFieldValue("Transaction", Settings.VolumeSourceField) + transactionVolume = transactionVolume; end return transactionBibId, transactionVolume end @@ -918,6 +924,27 @@ function HandleRequests () SaveDataSource("Transaction") end + if Settings.LocationDestinationField and Settings.LocationDestinationField ~= "" then + Log:Debug("Populating location destination field") + + local locationValue + if sierraRecord.location then + if Settings.LocationValueType == "code" then + locationValue = sierraRecord.location.code + else + locationValue = sierraRecord.location.name + end + end + + if locationValue and locationValue ~= "" then + SetFieldValue("Transaction", Settings.LocationDestinationField, locationValue) + SaveDataSource("Transaction") + else + Log:WarnFormat("Sierra item record does not contain location.{0}; leaving {1} unchanged.", + Settings.LocationValueType, Settings.LocationDestinationField) + end + end + return nil end ) diff --git a/Config.xml b/Config.xml index 41f6a66..f2a2000 100644 --- a/Config.xml +++ b/Config.xml @@ -1,7 +1,7 @@ Sierra ILS Data Import Server Addon - Test Build Atlas Systems, Inc. - 1.2.0 + 1.3.0 true Server @@ -67,6 +67,14 @@ A regular expression for parsing the volume from the field specified in the VolumeSourceField setting. The matched result will be used instead of the value from the VolumeSourceField, whenever volume information is compared. If this is set to blank, the actual value from the VolumeSourceField will be used. + + + Specifies the transaction field where the matched Sierra item's location information should be stored. The value of this setting is optional. If specified, the value of this setting must match the name of a column from the Transactions table. If left blank, no location information will be written. + + + + Determines which property of the Sierra item's location is written to the LocationDestinationField. Set to "name" to use the location's display name or "code" to use the location's code. Any value other than "code" is treated as "name". + Code.lua diff --git a/Readme.md b/Readme.md index c1eba59..5fc19d6 100644 --- a/Readme.md +++ b/Readme.md @@ -4,6 +4,12 @@ This addon imports ILS data from Sierra's Items API for transactions that are in ## Changelog +- `v1.3.0` + - Added option to import the matched Sierra item's location into a configurable Transaction field via the new `LocationDestinationField` and `LocationValueType` settings. + - Fixed a typo in the `VolumeSourceFieldRegularExpression` guard that prevented the configured regex from ever being applied. Sites with a non-empty regex (including the shipped default) will now see the regex used during volume matching. + - Hardened regex-based volume parsing: the regex is now skipped when the source field is nil or blank, the original field value is preserved when the regex finds no match, and zero-width regex matches no longer overwrite the volume with an empty string. + - Redacted `ClientKey`, `ClientSecret`, and Sierra API access tokens from the addon's log output. These values were previously written to the log at the DEBUG level on every timer tick. + - `v1.1.0` - Added ability to parse volume information via regular expressions. - Added exact matching options on volume information. @@ -96,6 +102,18 @@ A regular expression for parsing the volume from the field specified in the Volu *EXAMPLE*: `([B,b]ox\s*\d+)` will parse all box numbers only +### LocationDestinationField + +Specifies the transaction field where the matched Sierra item's location information should be stored. The value of this setting is optional. If specified, the value of this setting must match the name of a column from the Transactions table. If left blank, no location information will be written. + +*Default*: `SubLocation` + +### LocationValueType + +Determines which property of the Sierra item's location is written to the `LocationDestinationField`. Set to `name` to use the location's display name or `code` to use the location's code. Any value other than `code` is treated as `name`. If the Sierra response does not contain location data, the destination field is left unchanged and a warning is logged (the transaction is still routed to the success queue). + +*Default*: `name` + ## Workflow Summary The addon watches the transaction queue specified by the RequestMonitorQueue addon setting. When the addon detects that there are transactions present in the queue, it will grab bibId and volume information from the transaction. Using the bibId and volume information, the addon will attempt to download information regarding a single item using Sierra's API. If exactly one item is found, the item's information will be added to the transaction, which will then be routed to the specified success queue. If anything does not occur as expected during this process, a note will be added to the transaction, and it will be placed into the specified error queue. From 224785625595b16b84985f46b1eb9a813ae5b551 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 13 May 2026 12:05:41 -0400 Subject: [PATCH 3/3] Add IsNilOrBlank function, use for nil checks. --- Code.lua | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Code.lua b/Code.lua index 192922e..d6b41cd 100644 --- a/Code.lua +++ b/Code.lua @@ -403,7 +403,7 @@ function SierraApi:GetItems (bibId, volume, exact) local entryId = v_entry.id or "" local v_volume = SierraApi:GetVarFieldValue(v_entry, "v") - if v_volume and v_volume ~= "" and volume and volume ~= "" then + if not IsNilOrBlank(v_volume) and not IsNilOrBlank(volume) then if exact then if Utility.Trim(volume) == Utility.Trim(v_volume) then SierraApi.Log:DebugFormat("Sierra item record \"{0}\" matches specified bibId and volume (exact).", entryId); @@ -415,7 +415,7 @@ function SierraApi:GetItems (bibId, volume, exact) table.insert(matchingItems, v_entry) end end - elseif (not volume or volume == "") and (not v_volume or v_volume == "") then + elseif IsNilOrBlank(volume) and IsNilOrBlank(v_volume) then SierraApi.Log:DebugFormat("Sierra item record \"{0}\" matches specified bibId.", entryId); table.insert(matchingItems, v_entry); end @@ -459,7 +459,7 @@ function SierraApi:GetVarFieldValue (itemRecord, varField, subField) for i_vf, v_varField in ipairs(itemRecord.varFields or {}) do if v_varField and v_varField.fieldTag == varField then - if subField and subField ~= "" then + if not IsNilOrBlank(subField) then for i_sf, v_subField in ipairs(v_varField.subFields or {}) do @@ -621,7 +621,7 @@ function SierraApi:BuildItemsWebClient () webClient.Headers:Clear() webClient.Headers:Add("Authorization", "Bearer " .. self.AccessToken) - if self.UserAgent and self.UserAgent ~= "" then + if not IsNilOrBlank(self.UserAgent) then webClient.Headers:Add("User-Agent", self.UserAgent) end @@ -837,7 +837,7 @@ function HandleRequests () Log:DebugFormat("Found transaction number {0} in \"{1}\"", tn, Settings.RequestMonitorQueue) local regex - if Settings.VolumeSourceFieldRegularExpression and Settings.VolumeSourceFieldRegularExpression ~= "" then + if not IsNilOrBlank(Settings.VolumeSourceFieldRegularExpression) then regex = Types["Regex"](Settings.VolumeSourceFieldRegularExpression) Log:DebugFormat("Found Regex \"{0}\" for VolumeSourceField.", Settings.VolumeSourceFieldRegularExpression) else @@ -852,7 +852,7 @@ function HandleRequests () local transactionBibId = GetFieldValue("Transaction", Settings.BibIdSourceField) transactionBibId = transactionBibId:gsub("%D", "") local transactionVolume = GetFieldValue("Transaction", Settings.VolumeSourceField); - if regex ~= nil and NotNilOrBlank(transactionVolume) then + if regex ~= nil and not IsNilOrBlank(transactionVolume) then local match = regex:Match(transactionVolume); if match.Success and match.Value ~= "" then Log:DebugFormat("Using Regex for volume source field {0} results in match \"{1}\"", Settings.VolumeSourceField, match.Value); @@ -904,7 +904,7 @@ function HandleRequests () SaveDataSource("Transaction") end - if Settings.VolumeDestinationField and Settings.VolumeDestinationField ~= "" then + if not IsNilOrBlank(Settings.VolumeDestinationField) then local currentVolumeDestinationField = GetFieldValue("Transaction", Settings.VolumeDestinationField) if (Settings.ReplaceVolumeWhenNotNull or (not currentVolumeDestinationField) or currentVolumeDestinationField == "") then Log:Debug("Populating volume destination field") @@ -913,7 +913,7 @@ function HandleRequests () end end - if Settings.BarcodeDestinationField and Settings.BarcodeDestinationField ~= "" then + if not IsNilOrBlank(Settings.BarcodeDestinationField) then Log:Debug("Populating barcode destination field") if (not type(sierraRecord.barcode) == "string") or sierraRecord.barcode == "" then @@ -924,7 +924,7 @@ function HandleRequests () SaveDataSource("Transaction") end - if Settings.LocationDestinationField and Settings.LocationDestinationField ~= "" then + if not IsNilOrBlank(Settings.LocationDestinationField) then Log:Debug("Populating location destination field") local locationValue @@ -936,7 +936,7 @@ function HandleRequests () end end - if locationValue and locationValue ~= "" then + if not IsNilOrBlank(locationValue) then SetFieldValue("Transaction", Settings.LocationDestinationField, locationValue) SaveDataSource("Transaction") else @@ -962,6 +962,14 @@ function HandleRequests () end end +function IsNilOrBlank(value) + if not value or value == "" then + return true; + else + return false; + end +end + function TraverseError(err) if not err.GetType then -- Not a .NET type