Update bundles and bundled products
This is an example for how a script can be written to handle bundling of products and / or articles in Easit GO.
Scenario
We have all our product and services in the Item / Article module in Easit GO and our employees can order them through our selfservice portal in Easit GO. Now we would like to bundle some of these product and services and offer them as a "Product package" (a new item type) in the selfservice portal. As we create these packages we want Easit GO to calculate the prize for us and keep it up to date as the prize for an individual item / article change and / or if the package changes (items may be added or removed from the package).
Configuration in Easit GO
We start by creating an Export configuration by going to the Control panel, search for Export and click the first result. Click on Add, change the Module to Item, give it a give it a suitable name and tag. At the bottom we need to add the collection that holds the bundled items / articles and give it the property name bundledProducts.
We then create the views we need the script to get bundles and items from in order to calculate the prize when something change. Go to the control panel in Easit GO and click on View under Admin Center and select the Items module. If you have a folder called API, click on that, otherwise create a new folder called API. Here we create 2 new view, one for items / articles, and one for bundles.
Items / Articles view (Name: CalculatePrizeProducts)
This view should at least include the following fields:
- Id
- Field with prize
Bundles view (Name: CalculatePrizeBundles)
This view should at least include the following fields:
- Id
- Field with bundled items / articles
Now we need to add these views to the API so that the script can call them and retrieve the objects from them. Go to control panel, click on Settings and under Integration / Web service click on Views. Change the module to Item and click Add. Give the view the name CalculatePrizeProducts and a tag, select CalculatePrizeProducts in the drop down box View and click on Save and close. Click on Add again, give the view the name CalculatePrizeBundles and a tag, select CalculatePrizeBundles in the drop down box View and click on Save and close.
Then we create an item rule by opening the Control panel, click Automation rules in the Design studio section. Select the Item module and click on Item rules. Click on Add to create a new item rule, give it a suitable name and tag. The rule should be applied after an item has been saved, select the item type that you use for bundles AND the item types that can be bundled. We add the collection field that holds the bundled items / articles under Any of the following fields have changed. In the section Do this we select Export item and then configuration the function to call our instance of EPR the export configuration we created at the very beginning.
Script settings
These are the settings we used in the example and is found in globalSettings.json. Update the settings as need to fit your scenario and configuration.
{
"global":{
"goWsUrl": "https://urltoeasit/webservice",
"goWsApikey":"key"
},
"CalculateBundlePrize":{
"LogOutputLevel": "VERBOSE",
"LogRotationInterval": 30,
"goWsUrl": "__globalValue__",
"goWsApikey":"__globalValue__",
"bundleView":"CalculatePrizeBundles",
"bundledItemsCollectionName":"bundledProducts",
"bundledItemsViewCollectionName":"fieldWithBundledItemsArticles",
"itemView":"CalculatePrizeProducts",
"itemPriceAttributes":["fieldNameWithPrize"],
"updateBundleImporthandler":"UpdateBundlePrize",
"ReturnMessageFailed":"fail",
"ReturnMessageSuccess":"success"
}
}
Code
The code below should be ready to copy and paste, but it is not tested or verified and therefore may contain bugs or issues.
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$StringInput
)
begin {
Import-Module -Name 'Easit.ProcessRunner.GlobalFunctions'
Write-CustomLog -Message "Starting script"
Write-CustomLog -Message "Rotating logs" -Rotate
function Set-BundlePrize {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[PSCustomObject]$Bundle,
[Parameter(Mandatory)]
[Array]$Items,
[Parameter(Mandatory)]
[Array]$Prizes
)
begin {
Write-CustomLog -Message "$($MyInvocation.MyCommand) begin" -Level VERBOSE
}
process {
foreach ($prize in $Prizes) {
Write-CustomLog -Message "Calculating new total prize for itemPriceAttribute ($prize)" -Level VERBOSE
try {
$Bundle | Add-Member -MemberType NoteProperty -Name "${prize}_total" -Value 0 -Force -TypeName Double
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
Write-CustomLog -Message "Looping over all items in bundle" -Level VERBOSE
foreach ($item in $Items) {
$item."$prize" = $item."$prize" -replace ',','.'
$item."$prize" = $item."$prize" -replace ' ',''
if (($item."$prize") -and ($item."$prize" -gt 0)) {
try {
$Bundle."${prize}_total" = [Double]$Bundle."${prize}_total" + [Double]$item."$prize"
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
} else {
$Bundle | Add-Member -MemberType NoteProperty -Name "BundlePrizeCalculationFailed" -Value $true -Force
$item | Add-Member -MemberType NoteProperty -Name "BundlePrizeCalculationFailed" -Value $true -Force -PassThru
Write-CustomLog -Message "Item ($($item.uid)) prize = $($item."$prize"). Bundle = $($Bundle.Id)" -Level WARN
}
}
Write-CustomLog -Message "New total prize for itemPriceAttribute ($prize) = $($Bundle."${prize}_total")" -Level VERBOSE
}
return $Bundle
}
end {
Write-CustomLog -Message "$($MyInvocation.MyCommand) end" -Level VERBOSE
}
}
}
process {
try {
$decodedStringInput = Read-StringAsUTF8 -InputString $StringInput
$exportObject = $decodedStringInput | ConvertFrom-Json
$easitObject = $exportObject.itemToImport[0]
} catch {
$customExitCode = 1
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
$wsParams = @{
url = $settings.goWsUrl
apikey = $settings.goWsApikey
}
$bundles = [System.Collections.ArrayList]::new()
$bundlesToUpdate = [System.Collections.ArrayList]::new()
$bundledItems = [System.Collections.ArrayList]::new()
$bundledItemsRaw = [System.Collections.ArrayList]::new()
try {
[System.Collections.ArrayList]$bundledItemsRaw += $easitObject.property | Where-Object -Property Name -EQ -Value $settings.bundledItemsCollectionName
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
if ($bundledItemsRaw.Count -gt 0) {
Write-CustomLog -Message "Received a bundle, will attempt to calculate new prize and update bundle"
Write-CustomLog -Message "Collected $($bundledItemsRaw.Count) object(s) from exported object" -Level VERBOSE
foreach ($bundledItemRaw in $bundledItemsRaw) {
try {
[System.Collections.ArrayList]$bundledItems += Get-EasitGOItem @wsParams -view $settings.itemView -IdFilter "$($bundledItemRaw.content)" -ReturnAsSeparateObjects
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
}
Write-CustomLog -Message "Collected $($bundledItems.Count) object(s) from GO"
try {
$easitObject | Add-Member -MemberType NoteProperty -Name "databaseId" -Value $easitObject.Id -Force
$easitObject.Id = $easitObject.uid
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
try {
Write-CustomLog -Message "Calculating prize for bundle $($easitObject.uid) ($($easitObject.Id))"
[System.Collections.ArrayList]$bundlesToUpdate += Set-BundlePrize -Bundle $easitObject -Items $bundledItems -Prizes $settings.itemPriceAttributes
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
} else {
Write-CustomLog -Message "Received an item, all bundles that includes this item needs to be updated"
$cachedItems = [System.Collections.ArrayList]::new()
$allBundledItems = [System.Collections.ArrayList]::new()
try {
Write-CustomLog -Message "ColumnFilter = $($settings.bundledItemsViewCollectionName),$($easitObject.id),IN," -Level VERBOSE
$filter = New-ColumnFilter -ColumnName $settings.bundledItemsViewCollectionName -RawValue $easitObject.id -Comparator 'IN'
[System.Collections.ArrayList]$bundles += Get-EasitGOItem @wsParams -view $settings.bundleView -ColumnFilter $filter
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
Write-CustomLog -Message "Collected $($bundles.Count) bundles from GO"
foreach ($bundle in $bundles) {
foreach ($bundledItem in $bundle."$($settings.bundledItemsViewCollectionName)") {
Write-CustomLog -Message "Looking up GO object for item $($bundledItem.rawValue)" -Leve VERBOSE
if ($cachedItems -contains $bundledItem.rawValue) {
Write-CustomLog -Message "Found GO object for bundled item ($($bundledItem.rawValue)) in cache" -Leve VERBOSE
} else {
Write-CustomLog -Message "GO object for bundled item ($($bundledItem.rawValue)) not found in cache" -Leve VERBOSE
try {
Write-CustomLog -Message "Retrieving GO object for bundled item ($($bundledItem.rawValue))" -Leve VERBOSE
[System.Collections.ArrayList]$allBundledItems += Get-EasitGOItem @wsParams -view $settings.itemView -IdFilter "$($bundledItem.rawValue)"
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
try {
Write-CustomLog -Message "Adding GO object for bundled item ($($bundledItem.rawValue)) to cache" -Level VERBOSE
[void]$cachedItems.Add("$($bundledItem.rawValue)")
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
}
try {
[System.Collections.ArrayList]$bundledItems += $allBundledItems | Where-Object -Property databaseId -EQ $bundledItem.rawValue
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
}
try {
Write-CustomLog -Message "Calculating prize for bundle $($bundle.Id)"
[System.Collections.ArrayList]$bundlesToUpdate += Set-BundlePrize -Bundle $bundle -Items $bundledItems -Prizes $settings.itemPriceAttributes
Write-CustomLog -Message "Calculating for $($bundle.Id) completed"
} catch {
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
return
}
}
}
Write-CustomLog -Message "$($bundlesToUpdate.Count) object(s) to update in GO" -Level VERBOSE
try {
Send-ToEasitGO @wsParams -ImportHandlerIdentifier $settings.updateBundleImporthandler -Item $bundlesToUpdate
} catch {
Write-CustomLog -Message "Failed to update one or more bundles" -Level WARN
Write-CustomLog -Message "$($_.Exception)" -Level ERROR
continue
}
}
end {
$goWebserviceParams = @{
url = $settings.goWsUrl
apikey = $settings.goWsApikey
}
$resultPropertiesParams = @{
ID = $easitObject.uid
exitCode = $customExitCode
}
if ($customExitCode -ne 0) {
$resultPropertiesParams.Add('ReturnMessage',"$($settings.ReturnMessageFailed)")
}
if ($customExitCode -eq 0) {
$resultPropertiesParams.Add('ReturnMessage',"$($settings.ReturnMessageSuccess)")
}
try {
Send-ToEasitGO @goWebserviceParams -ImportHandlerIdentifier $settings.updateBundleImporthandler -CustomItem $resultPropertiesParams
} catch {
Write-CustomLog -InputObject $_ -Level ERROR
}
}
We have added the function Set-BundlePrize to make it easier to follow what the script does.