ad-sponsored-text

Skip to Main Content
ICBA

Search Education

Type
An error occurred while processing the template.
The following has evaluated to null or missing:
==> productDetail.urlImage  [in template "49724393377863#35335#2373423" at line 52, column 27]

----
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: defaultImageURL = productDetail.urlIm...  [in template "49724393377863#35335#2373423" at line 52, 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            <#assign isInPerson = "true" /> 
148          </#if> 
149          <#if category.vocabulary == 'delivery method' && category.name == "Livestream"> 
150						<#if infoObj["Event End Date"]?has_content> 
151								<#assign end = infoObj["Event End Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
152								<#assign today = .now?datetime> <!-- Today's date without time --> 
153								<#assign showLiveStream = end < today /> 
154								<!-- Ensure 'end' is valid before performing the comparison --> 
155								<#if !showLiveStream> 
156										<#assign isLivestream = "true" /> 
157								</#if> 
158						</#if> 
159          </#if> 
160          <#if category.vocabulary == 'event type' && category.name == "Institute"> 
161            <#assign isInstitute = "true" /> 
162          </#if> 
163          <#if category.vocabulary == 'event type' && category.name == "Seminar"> 
164            <#assign isSeminar = "true" /> 
165          </#if> 
166          <#if category.vocabulary == 'product type' && category.name == "Webinar"> 
167            <#assign isWebinar = "true" /> 
168          </#if> 
169          <#if category.vocabulary == 'product type' && category.name == "Online Course"> 
170            <#assign isOnlineCourse = "true" /> 
171          </#if> 
172          <#if category.vocabulary == 'product type' && category.name == "Event"> 
173            <#assign isEvent = "true" /> 
174          </#if> 
175          <#if category.vocabulary == 'event type'> 
176            <#assign eventTypeName = category.name /> 
177          </#if> 
178        </#list> 
179      </#if> 
180 
181      <div class="card education-card mb-4 asdasd"> 
182        <div class="card-body"> 
183          <div class="top-row"> 
184            <#if infoObj.deliverymethod??> 
185              <div class="education-card-categories"> 
186                <#list infoObj.deliverymethod as format> 
187                  <#if format.value != ""> 
188                    <#if defaultImgMap[format.value]?has_content> 
189											<#if format.value == "Livestream"> 
190												<#if isLivestream == "true"> 
191													<span class="category"> 
192														<img src="${defaultImgMap[format.value]['image']}" alt="" class="category-img bg-${defaultImgMap[format.value]['color']}" /> 
193														<span class="category-name">${format.value}</span> 
194													</span> 
195												</#if> 
196											<#else> 
197												<span class="category"> 
198													<img src="${defaultImgMap[format.value]['image']}" alt="" class="category-img bg-${defaultImgMap[format.value]['color']}" /> 
199													<span class="category-name">${format.value}</span> 
200												</span> 
201											</#if> 
202                    </#if> 
203                  </#if> 
204                </#list> 
205              </div> 
206            </#if> 
207 
208            <#if isInstitute == "true"> 
209              <div class="certification-info"> 
210                <span class="certification-info-text">Earn Professional Certification</span> 
211                <div class="certification-info-img"><i class="certification-info-img"></i></div> 
212              </div> 
213            </#if> 
214          </div> 
215 
216					<#assign viewUrl = friendlyURL /> 
217 
218					<#if friendlyURL?contains("/p/")> 
219					  <#assign viewUrl = ("https://www.icba.org/p/" + friendlyURL?keep_after("/p/")) /> 
220					</#if> 
221						 
222          <div class="card-title"> 
223            <h3 class="header-s"><a href="${viewUrl}">${productName}</a></h3> 
224          </div> 
225 
226          <div class="education-card-details"> 
227							<#if infoObj["Event Start Date"]?has_content> 
228                <#assign start = infoObj["Event Start Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
229                <#assign startDateStr = start?string("MMM d") /> 
230                <#assign year = start?string("yyyy") /> 
231                <#assign startTime = start?string("h:mm") + " " + start?string("a")?lower_case /> 
232              </#if> 
233 
234              <#if infoObj["Event End Date"]?has_content> 
235                <#assign end = infoObj["Event End Date"]?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") /> 
236                <#assign endDateStr = end?string("MMM d") /> 
237                <#assign endTime = end?string("h:mm") + " " + end?string("a")?lower_case /> 
238              </#if> 
239 
240						<#if isLivestream == "true" || isInPerson == "true"> 
241                <#if start?has_content && end?has_content> 
242                  <#if start?string("yyyyMMdd") == end?string("yyyyMMdd")> 
243                    <#assign dateDisplay = startDateStr + ", " + year /> 
244                    <#assign timeDisplay = startTime + "–" + endTime /> 
245                  <#else> 
246                    <#assign dateDisplay = startDateStr + "–" + endDateStr + ", " + year /> 
247                    <#assign timeDisplay = startTime /> 
248                  </#if> 
249                </#if> 
250									 
251									</#if>	 
252								<div class="education-card-location"> 
253              <#if isWebinar == "true" || isEvent == "true"> 
254									 
255									<span class="date">${dateDisplay}</span> 
256									<#if isWebinar == "true"> 
257										<#if isLivestream == "true" || isInPerson == "true">|</#if> <span class="category">Webinar</span> 
258									</#if> 
259									 
260									<#if isEvent == "true"> 
261										<#if isLivestream == "true" || isInPerson == "true">| </#if><span class="category">${eventTypeName}</span> 
262									</#if> 
263									<span class="time d-none">${timeDisplay}</span> 
264								</#if> 
265								 
266								<#if isInPerson == "true"> 
267									<span class="location"> 
268										<#if infoObj["Location City"]?has_content> 
269											${infoObj["Location City"]} 
270										</#if> 
271										<#if infoObj["Location State"]?has_content> 
272											, ${infoObj["Location State"]} 
273										</#if> 
274									</span> 
275								</#if> 
276							</div> 
277									 
278             
279              <div class="education-card-credits"> 
280                <span class="credits-info"><#if infoObj["CPE Credits"]?has_content>CPE Credits: ${infoObj["CPE Credits"]}</#if></span> 
281              </div> 
282	 
283<!---Start ----> 
284					  
285<!-- SKU Area  --> 
286<#assign 	productskuJson = jsonFactoryUtil.createJSONObject(productsku)/> 
287<#if productskuJson?has_content && productskuJson.has("items")> 
288	<#assign itemsArray = productskuJson.getJSONArray("items")/> 
289	<#if itemsArray?has_content> 
290<#assign priceList = [] /> 
291 
292<#if itemsArray?has_content && itemsArray.length() gt 0> 
293  <#list 0..itemsArray.length() - 1 as index> 
294    <#assign item = itemsArray.getJSONObject(index) /> 
295    <#if item?has_content && item.getJSONArray("skuOptions")?has_content> 
296      <#assign skuOptions = item.getJSONArray("skuOptions") /> 
297      <#assign registrationOption = "" /> 
298      <#assign deliveryMethod = "" /> 
299      <#assign rowdisplayName = "" /> 
300 
301      <!-- Extract values from skuOptions --> 
302      <#list 0..skuOptions.length() - 1 as i> 
303        <#assign skuOption = skuOptions.getJSONObject(i) /> 
304        <#assign key = skuOption.getString("skuOptionKey") /> 
305        <#assign valueKey = skuOption.getString("skuOptionValueKey") /> 
306        <#assign valueName = skuOption.getJSONArray("skuOptionValueNames").getString(0) /> 
307 
308        <#if key == "registration-options"> 
309          <#assign registrationOption = valueKey /> 
310          <#assign rowdisplayName = valueName /> 
311        </#if> 
312 
313        <#if key == "webinar-delivery-method"> 
314          <#assign deliveryMethod = valueKey /> 
315        </#if> 
316      </#list> 
317 
318      <!-- Filter: Only show On-demand + desired registration-options --> 
319			<#if isWebinar == "true"> 
320      <#if deliveryMethod == "ondemand" &&  
321            (registrationOption == "icba-member" ||  
322             registrationOption == "nonmember" ||  
323             registrationOption == "unlimited-webinar-pass")> 
324         
325        <!-- Format price --> 
326        <#assign price = item.price.priceFormatted /> 
327        <!-- Store display name + price in a map --> 
328        <#assign priceList = priceList + [{"name": rowdisplayName, "price": price}] /> 
329      </#if> 
330				<#else> 
331					<#if registrationOption == "icba-member" ||  
332             registrationOption == "nonmember" ||  
333             registrationOption == "unlimited-webinar-pass"> 
334         
335        <!-- Format price --> 
336        <#assign price = item.price.priceFormatted /> 
337        <!-- Store display name + price in a map --> 
338        <#assign priceList = priceList + [{"name": rowdisplayName, "price": price}] /> 
339      </#if> 
340				</#if> 
341    </#if> 
342  </#list> 
343    </#if> 
344    </#if>	 
345	</#if> 
346									 
347 
348<!-- Display the collected name + price --> 
349<div class="education-card-price"> 
350  <#if priceList?has_content> 
351 
352    <!-- First: Member --> 
353    <#list priceList as item> 
354      <#if item?has_content && item.name == "ICBA Member"> 
355        <span class="education-card-price-item member-price">Member: ${item.price}</span> 
356      </#if> 
357    </#list> 
358 
359    <!-- Second: Non-Member --> 
360   <#list priceList as item> 
361      <#if item?has_content && item.name == "Non-Member"> 
362        <span class="education-card-price-item member-price">${item.name}: ${item.price}</span> 
363      </#if> 
364    </#list>  
365		 
366	<!-- Third: ICBA Bank Director Program Subscriber --> 
367   <#list priceList as item> 
368      <#if item?has_content && item.name == "Bank Director Program Subscriber"> 
369        <span class="education-card-price-item member-price">ICBA Bank Director Program Subscriber: ${item.price}</span> 
370      </#if> 
371    </#list>  
372		 
373    <!-- Fourth: Unlimited Webinar Pass --> 
374    <#list priceList as item> 
375      <#if item?has_content && item.name == "Unlimited Webinar Pass"> 
376        <span class="education-card-price-item member-price">Unlimited Webinar Pass: ${item.price}</span> 
377      </#if> 
378    </#list> 
379 
380  </#if> 
381</div> 
382 
383 
384<!-----Ends --->									 
385            <div class="education-card-tags"> 
386             <#if categories?has_content> 
387               <#assign topicCount = 0/> 
388               <#assign displayedCategories = []/> 
389               <#assign totalTopicCount = 0/> 
390 
391               <#-- First, count total topic categories --> 
392               <#list categories as category> 
393                 <#if category.vocabulary == 'topic'> 
394                    <#assign totalTopicCount += 1/> 
395                 </#if> 
396              </#list> 
397 
398             <#-- Now display first 3 topics --> 
399             <#list categories as category> 
400               <#if category.vocabulary == 'topic' && topicCount < 3> 
401                 <#assign taxonomyCategoryId = category.id/> 
402                 <#assign response = restClient.get("/headless-admin-taxonomy/v1.0/taxonomy-categories/${taxonomyCategoryId}") /> 
403                   <#if response.taxonomyCategoryProperties?has_content> 
404                     <#assign firstProperty = response.taxonomyCategoryProperties[0] /> 
405                     <#assign categoryValue = firstProperty.value /> 
406                      <span class="tag-pill body-13">${categoryValue}</span> 
407                      <#else> 
408                     <span class="tag-pill body-13">${category.name}</span> 
409                  </#if> 
410              <#assign topicCount += 1> 
411             </#if> 
412          </#list> 
413 
414        <#-- If more topics exist, show "+X More..." --> 
415         <#if (totalTopicCount - topicCount) gt 0> 
416            <span class="tag-pill body-13">+${totalTopicCount - topicCount} More...</span> 
417          </#if> 
418 
419           </#if> 
420           </div> 
421          </div> 
422        </div> 
423      </div> 
424    </#list> 
425  </#if> 
426</div> 

ad-sponsored-text