ad-sponsored-text

Skip to Main Content
ICBA
An error occurred while processing the template.
The following has evaluated to null or missing:
==> productCategories.items  [in template "49724393377863#35335#230212" at line 57, column 22]

----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: categories = productCategories.items  [in template "49724393377863#35335#230212" at line 57, column 9]
----
1<#assign  
2	defaultImgMap = { 
3				 "Default": { 
4	  			   "image": "/documents/d/guest/default_logo.png", 
5		  		   "color": "gray" 
6			  	 }, 
7  				 "Livestream": { 
8	  			   "image": "/documents/d/guest/icon-desktop-svg", 
9		  		   "color": "purple" 
10			  	 }, 
11				   "Recorded":{ 
12				     "image": "/documents/d/guest/icon-play", 
13				     "color": "red" 
14  				 }, 
15	  			 "In Person":{ 
16		  		   "image": "/documents/d/guest/icon-persons", 
17			  	   "color": "green" 
18				   }, 
19				   "Download": { 
20				     "image": "/documents/d/guest/icon-download-black", 
21				     "color": "border-color" 
22  				 }, 
23  				 "Self-paced": { 
24				     "image": "/documents/d/guest/icon-mouse-white", 
25				     "color": "black" 
26				   }, 
27					 "Bank subscription": { 
28				     "image": "/documents/d/guest/icon-bank", 
29				     "color": "blue" 
30
31	}			  
32/> 
33 
34<#assign commerceContext = renderRequest.getAttribute("COMMERCE_CONTEXT") /> 
35<#assign account = commerceContext.getAccountEntry() /> 
36<#assign accountId = account.getAccountEntryId() /> 
37<#assign chanelId = commerceContext.getCommerceChannelId() /> 
38 
39<div class="product-card-tiles"> 
40  <#if entries?has_content> 
41    <#list entries as curCPCatalogEntry> 
42      <#assign 
43        cpDefinitionId = curCPCatalogEntry.getCPDefinitionId() 
44        productId = curCPCatalogEntry.getCProductId() 
45        productName = curCPCatalogEntry.getName() 
46        productShortDescription = curCPCatalogEntry.getShortDescription() 
47        productDescription = curCPCatalogEntry.getDescription() 
48        friendlyURL = cpContentHelper.getFriendlyURL(curCPCatalogEntry, themeDisplay) 
49        defaultImageURL = cpContentHelper.getDefaultImageFileURL(accountId, cpDefinitionId) 
50        defaultImageFileVersion = cpContentHelper.getCPDefinitionImageFileVersion(cpDefinitionId, request) 
51        productDetail = restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${chanelId}/products/${productId}?accountId=${accountId}&nestedFields=categories,productSpecifications") 
52        defaultImageURL = productDetail.urlImage?replace('https://localhost', '') 
53        fileEntryIdAttr = 'data-fileentryid="' + defaultImageFileVersion.fileEntryId + '"' 
54        specifications = productDetail.productSpecifications 
55        customFields = productDetail.customFields 
56        productCategories = restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${chanelId}/products/${productId}/categories?pageSize=75") 
57        categories = productCategories.items 
58	      productsku= restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${chanelId}/products/${productId}/skus?pageSize=40")	 
59        erc = productDetail.externalReferenceCode 
60        infoObj = {} 
61        tags = productDetail.tags 
62        featuredSpecificationKeys = ["fit", "weight", "material"] 
63        eventTypeName = "" 
64        startDate = "" 
65        startTime = "" 
66        endDate = "" 
67        endTime = "" 
68        deliverymethodArray = [{"id": "", "value": ""}] 
69        locationAddress = "" 
70      /> 
71      <#if categories?has_content> 
72        <#list categories as category> 
73          <#if category.vocabulary?replace(' ', '') == 'deliverymethod'> 
74            <#assign deliverymethodArray += [{"id": category.id, "value": category.name}] /> 
75          <#else> 
76            <#assign infoObj = infoObj + {category.vocabulary?replace(' ', ''): {"id": category.id, "value": category.name}} /> 
77          </#if> 
78        </#list> 
79        <#assign infoObj = infoObj + {"deliverymethod": deliverymethodArray} /> 
80      </#if> 
81 
82      <#list customFields as customField> 
83        <#assign infoObj = infoObj + {(customField.name): customField.customValue.data} /> 
84      </#list> 
85 
86   <!--   <div class="d-none"> 
87        <ul> 
88          <li> 
89            <#assign sku = "" /> 
90            <#if cpContentHelper.getDefaultCPSku(curCPCatalogEntry)?has_content> 
91              <#assign sku = cpContentHelper.getDefaultCPSku(curCPCatalogEntry).getSku() /> 
92            </#if> 
93            SKU: ${sku} 
94          </li> 
95          <li> 
96            <@liferay_commerce_ui["availability-label"] CPCatalogEntry=curCPCatalogEntry /> 
97          </li> 
98 
99          <#if categories?has_content> 
100            <#list categories as category> 
101              <#if category.vocabulary == 'event type'> 
102                <#assign eventTypeName = category.name /> 
103                <#assign eventTypeId = category.id /> 
104              </#if> 
105              <li>${category.vocabulary}: ${category.name}</li> 
106            </#list> 
107          </#if> 
108        </ul> 
109      </div> --> 
110 
111      <!-- Category Flags --> 
112      <#assign 
113        isInstitute = "false" 
114        isSeminar = "false" 
115        isLivestream = "false" 
116        isOnlineCourse = "false" 
117        isInPerson = "false" 
118        isWebinar = "false" 
119        isEvent = "false" 
120        isPriceTypeFree = "false" 
121        isPriceTypeSubs = "false" 
122        isPriceTypeMB = "false" 
123        start = "" 
124        end = "" 
125        startDateStr = "" 
126        endDateStr = "" 
127        startTime = "" 
128        endTime = "" 
129        year = "" 
130        dateDisplay = "" 
131        timeDisplay = "" 
132        locationDisplay = "" 
133      /> 
134 
135      <#if categories?has_content> 
136        <#list categories as category> 
137          <#if category.vocabulary == 'price type' && category.name == "Free"> 
138            <#assign isPriceTypeFree = "true" /> 
139          </#if> 
140          <#if category.vocabulary == 'price type' && category.name == "Subscription"> 
141            <#assign isPriceTypeSubs = "true" /> 
142          </#if> 
143          <#if category.vocabulary == 'price type' && category.name == "Member Benefit"> 
144            <#assign isPriceTypeMB = "true" /> 
145          </#if> 
146          <#if category.vocabulary == 'delivery method' && category.name == "In Person"> 
147						<#if infoObj["Event End Date"]?has_content> 
148								<#assign end = infoObj["Event End Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
149								<#assign today = .now?datetime> <!-- Today's date without time --> 
150								<#assign showInPerson = end < today /> 
151								<!-- Ensure 'end' is valid before performing the comparison --> 
152								<#if !showInPerson> 
153										<#assign isInPerson = "true" /> 
154								</#if> 
155						</#if> 
156          </#if> 
157          <#if category.vocabulary == 'delivery method' && category.name == "Livestream"> 
158						<#if infoObj["Event End Date"]?has_content> 
159								<#assign end = infoObj["Event End Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
160								<#assign today = .now?datetime> <!-- Today's date without time --> 
161								<#assign showLiveStream = end < today /> 
162								<!-- Ensure 'end' is valid before performing the comparison --> 
163								<#if !showLiveStream> 
164										<#assign isLivestream = "true" /> 
165								</#if> 
166						</#if> 
167          </#if> 
168          <#if category.vocabulary == 'event type' && category.name == "Institute"> 
169            <#assign isInstitute = "true" /> 
170          </#if> 
171          <#if category.vocabulary == 'event type' && category.name == "Seminar"> 
172            <#assign isSeminar = "true" /> 
173          </#if> 
174          <#if category.vocabulary == 'product type' && category.name == "Webinar"> 
175            <#assign isWebinar = "true" /> 
176          </#if> 
177          <#if category.vocabulary == 'product type' && category.name == "Online Course"> 
178            <#assign isOnlineCourse = "true" /> 
179          </#if> 
180          <#if category.vocabulary == 'product type' && category.name == "Event"> 
181            <#assign isEvent = "true" /> 
182          </#if> 
183          <#if category.vocabulary == 'event type'> 
184            <#assign eventTypeName = category.name /> 
185          </#if> 
186        </#list> 
187      </#if> 
188 
189      <div class="card education-card mb-4 asdasd"> 
190        <div class="card-body"> 
191          <div class="top-row"> 
192            <#if infoObj.deliverymethod??> 
193              <div class="education-card-categories"> 
194                <#list infoObj.deliverymethod as format> 
195                  <#if format.value != ""> 
196                    <#if defaultImgMap[format.value]?has_content> 
197											<#if format.value == "Livestream"> 
198												<#if isLivestream == "true"> 
199													<span class="category"> 
200														<img src="${defaultImgMap[format.value]['image']}" alt="" class="category-img bg-${defaultImgMap[format.value]['color']}" /> 
201														<span class="category-name">${format.value}</span> 
202													</span> 
203												</#if> 
204											<#elseif format.value == "In Person"> 
205												<#if isInPerson == "true"> 
206													<span class="category"> 
207														<img src="${defaultImgMap[format.value]['image']}" alt="" class="category-img bg-${defaultImgMap[format.value]['color']}" /> 
208														<span class="category-name">${format.value}</span> 
209													</span> 
210												</#if> 
211											<#else> 
212												<span class="category"> 
213													<img src="${defaultImgMap[format.value]['image']}" alt="" class="category-img bg-${defaultImgMap[format.value]['color']}" /> 
214													<span class="category-name">${format.value}</span> 
215												</span> 
216											</#if> 
217                    </#if> 
218                  </#if> 
219                </#list> 
220              </div> 
221            </#if> 
222 
223            <#if isInstitute == "true"> 
224              <div class="certification-info"> 
225                <span class="certification-info-text">Earn Professional Certification</span> 
226                <div class="certification-info-img"><i class="certification-info-img"></i></div> 
227              </div> 
228            </#if> 
229          </div> 
230 
231          <div class="card-title"> 
232            <h3 class="header-s"><a href="${friendlyURL}">${productName}</a></h3> 
233          </div> 
234 
235          <div class="education-card-details"> 
236							<#if infoObj["Event Start Date"]?has_content> 
237                <#assign start = infoObj["Event Start Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
238                <#assign startDateStr = start?string("MMM d") /> 
239                <#assign year = start?string("yyyy") /> 
240                <#assign startTime = start?string("h:mm") + " " + start?string("a")?lower_case /> 
241              </#if> 
242 
243              <#if infoObj["Event End Date"]?has_content> 
244                <#assign end = infoObj["Event End Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
245                <#assign endDateStr = end?string("MMM d") /> 
246                <#assign endTime = end?string("h:mm") + " " + end?string("a")?lower_case /> 
247              </#if> 
248 
249						<#if isLivestream == "true" || isInPerson == "true"> 
250                <#if start?has_content && end?has_content> 
251                  <#if start?string("yyyyMMdd") == end?string("yyyyMMdd")> 
252                    <#assign dateDisplay = startDateStr + ", " + year /> 
253                    <#assign timeDisplay = startTime + "–" + endTime /> 
254                  <#else> 
255                    <#assign dateDisplay = startDateStr + "–" + endDateStr + ", " + year /> 
256                    <#assign timeDisplay = startTime /> 
257                  </#if> 
258                </#if> 
259									 
260									</#if>	 
261								<div class="education-card-location"> 
262              <#if isWebinar == "true" || isEvent == "true"> 
263									 
264									<span class="date">${dateDisplay}</span> 
265									<#if isWebinar == "true"> 
266										<#if isLivestream == "true" || isInPerson == "true">|</#if> <span class="category">Webinar</span> 
267									</#if> 
268									 
269									<#if isEvent == "true"> 
270										<#if isLivestream == "true" || isInPerson == "true">| </#if><span class="category">${eventTypeName}</span> 
271									</#if> 
272									<span class="time d-none">${timeDisplay}</span> 
273								</#if> 
274								 
275								<#if isInPerson == "true"> 
276									<span class="location"> 
277										<#if infoObj["Location City"]?has_content> 
278											${infoObj["Location City"]} 
279										</#if> 
280										<#if infoObj["Location State"]?has_content> 
281											, ${infoObj["Location State"]} 
282										</#if> 
283									</span> 
284								</#if> 
285							</div> 
286									 
287             
288              <div class="education-card-credits"> 
289                <span class="credits-info"><#if infoObj["CPE Credits"]?has_content>CPE Credits: ${infoObj["CPE Credits"]}</#if></span> 
290              </div> 
291	 
292<!---Start ----> 
293					  
294<!-- SKU Area  --> 
295<#assign 	productskuJson = jsonFactoryUtil.createJSONObject(productsku)/> 
296<#if productskuJson?has_content && productskuJson.has("items")> 
297	<#assign itemsArray = productskuJson.getJSONArray("items")/> 
298	<#if itemsArray?has_content> 
299<#assign priceList = [] /> 
300 
301<#if itemsArray?has_content && itemsArray.length() gt 0> 
302  <#list 0..itemsArray.length() - 1 as index> 
303    <#assign item = itemsArray.getJSONObject(index) /> 
304    <#if item?has_content && item.getJSONArray("skuOptions")?has_content> 
305      <#assign skuOptions = item.getJSONArray("skuOptions") /> 
306      <#assign registrationOption = "" /> 
307      <#assign deliveryMethod = "" /> 
308      <#assign rowdisplayName = "" /> 
309 
310      <!-- Extract values from skuOptions --> 
311      <#list 0..skuOptions.length() - 1 as i> 
312        <#assign skuOption = skuOptions.getJSONObject(i) /> 
313        <#assign key = skuOption.getString("skuOptionKey") /> 
314        <#assign valueKey = skuOption.getString("skuOptionValueKey") /> 
315        <#assign valueName = skuOption.getJSONArray("skuOptionValueNames").getString(0) /> 
316 
317        <#if key == "registration-options"> 
318          <#assign registrationOption = valueKey /> 
319          <#assign rowdisplayName = valueName /> 
320        </#if> 
321 
322        <#if key == "webinar-delivery-method"> 
323          <#assign deliveryMethod = valueKey /> 
324        </#if> 
325      </#list> 
326 
327      <!-- Filter: Only show On-demand + desired registration-options --> 
328			<#if isWebinar == "true"> 
329      <#if deliveryMethod == "ondemand" &&  
330            (registrationOption == "icba-member" ||  
331             registrationOption == "nonmember" ||  
332             registrationOption == "unlimited-webinar-pass")> 
333         
334        <!-- Format price --> 
335        <#assign price = item.price.priceFormatted /> 
336        <!-- Store display name + price in a map --> 
337        <#assign priceList = priceList + [{"name": rowdisplayName, "price": price}] /> 
338      </#if> 
339				<#else> 
340					<#if registrationOption == "icba-member" ||  
341             registrationOption == "nonmember" ||  
342             registrationOption == "unlimited-webinar-pass"> 
343         
344        <!-- Format price --> 
345        <#assign price = item.price.priceFormatted /> 
346        <!-- Store display name + price in a map --> 
347        <#assign priceList = priceList + [{"name": rowdisplayName, "price": price}] /> 
348      </#if> 
349				</#if> 
350    </#if> 
351  </#list> 
352    </#if> 
353    </#if>	 
354	</#if> 
355									 
356 
357<!-- Display the collected name + price --> 
358<div class="education-card-price"> 
359  <#if priceList?has_content> 
360 
361    <!-- First: Member --> 
362    <#list priceList as item> 
363      <#if item?has_content && item.name == "ICBA Member"> 
364        <span class="education-card-price-item member-price">Member: ${item.price}</span> 
365      </#if> 
366    </#list> 
367 
368    <!-- Second: Non-Member --> 
369   <#list priceList as item> 
370      <#if item?has_content && item.name == "Non-Member"> 
371        <span class="education-card-price-item member-price">${item.name}: ${item.price}</span> 
372      </#if> 
373    </#list>  
374		 
375	<!-- Third: ICBA Bank Director Program Subscriber --> 
376   <#list priceList as item> 
377      <#if item?has_content && item.name == "Bank Director Program Subscriber"> 
378        <span class="education-card-price-item member-price">ICBA Bank Director Program Subscriber: ${item.price}</span> 
379      </#if> 
380    </#list>  
381		 
382    <!-- Fourth: Unlimited Webinar Pass --> 
383    <#list priceList as item> 
384      <#if item?has_content && item.name == "Unlimited Webinar Pass"> 
385        <span class="education-card-price-item member-price">Unlimited Webinar Pass: ${item.price}</span> 
386      </#if> 
387    </#list> 
388 
389  </#if> 
390</div> 
391 
392 
393<!-----Ends --->									 
394            <div class="education-card-tags"> 
395             <#if categories?has_content> 
396               <#assign topicCount = 0/> 
397               <#assign displayedCategories = []/> 
398               <#assign totalTopicCount = 0/> 
399 
400               <#-- First, count total topic categories --> 
401               <#list categories as category> 
402                 <#if category.vocabulary == 'topic'> 
403                    <#assign totalTopicCount += 1/> 
404                 </#if> 
405              </#list> 
406 
407             <#-- Now display first 3 topics --> 
408             <#list categories as category> 
409               <#if category.vocabulary == 'topic' && topicCount < 3> 
410                 <#assign taxonomyCategoryId = category.id/> 
411                 <#assign response = restClient.get("/headless-admin-taxonomy/v1.0/taxonomy-categories/${taxonomyCategoryId}") /> 
412                   <#if response.taxonomyCategoryProperties?has_content> 
413                     <#assign firstProperty = response.taxonomyCategoryProperties[0] /> 
414                     <#assign categoryValue = firstProperty.value /> 
415                      <span class="tag-pill body-13">${categoryValue}</span> 
416                      <#else> 
417                     <span class="tag-pill body-13">${category.name}</span> 
418                  </#if> 
419              <#assign topicCount += 1> 
420             </#if> 
421          </#list> 
422 
423        <#-- If more topics exist, show "+X More..." --> 
424         <#if (totalTopicCount - topicCount) gt 0> 
425            <span class="tag-pill body-13">+${totalTopicCount - topicCount} More...</span> 
426          </#if> 
427 
428           </#if> 
429           </div> 
430          </div> 
431        </div> 
432      </div> 
433    </#list> 
434  </#if> 
435</div> 

ad-sponsored-text