1 | |
package org.paneris.jammyjoes.shopping; |
2 | |
|
3 | |
import java.io.PrintWriter; |
4 | |
import java.io.StringWriter; |
5 | |
import java.util.Enumeration; |
6 | |
import java.util.Locale; |
7 | |
|
8 | |
import org.melati.Melati; |
9 | |
import org.melati.servlet.Form; |
10 | |
import org.melati.login.HttpSessionAccessHandler; |
11 | |
import org.melati.poem.AccessPoemException; |
12 | |
import org.melati.poem.AccessToken; |
13 | |
import org.melati.poem.Field; |
14 | |
import org.melati.poem.PoemTask; |
15 | |
import org.melati.poem.PoemThread; |
16 | |
import org.melati.template.ServletTemplateContext; |
17 | |
import org.melati.util.InstantiationPropertyException; |
18 | |
import org.paneris.jammyjoes.model.Affiliate; |
19 | |
import org.paneris.jammyjoes.model.DeliveryCarrier; |
20 | |
import org.paneris.jammyjoes.model.DeliveryCharge; |
21 | |
import org.paneris.jammyjoes.model.DeliveryZone; |
22 | |
import org.paneris.jammyjoes.model.JammyjoesDatabase; |
23 | |
import org.paneris.jammyjoes.model.OrderType; |
24 | |
import org.paneris.jammyjoes.model.ShopCurrency; |
25 | |
import org.paneris.jammyjoes.model.ShopOrder; |
26 | |
import org.paneris.jammyjoes.model.ShopOrderItem; |
27 | |
import org.paneris.jammyjoes.model.User; |
28 | |
import org.paneris.jammyjoes.model.UserTable; |
29 | |
import org.paneris.jammyjoes.model.Wrapping; |
30 | |
import org.paneris.jammyjoes.model.WrappingTable; |
31 | |
import org.paneris.jammyjoes.util.JammyJoesContextUtil; |
32 | |
import org.paneris.jammyjoes.util.JammyJoesUtil; |
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
|
45 | |
|
46 | |
|
47 | 0 | public class JammyJoesShoppingTrolley extends ShoppingTrolley { |
48 | |
|
49 | |
public DeliveryZone zone; |
50 | |
public Wrapping wrapping; |
51 | 0 | private ShopOrder order = null; |
52 | |
public DeliveryCarrier carrier; |
53 | |
private Boolean spam; |
54 | |
private String comment; |
55 | |
private String deliveryName; |
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
public Locale getLocale() { |
61 | |
|
62 | 0 | if (locale == null) { |
63 | |
|
64 | 0 | User user = (User) melati.getUser(); |
65 | 0 | if (!user.isGuest() && user.getCurrency() != null) { |
66 | 0 | locale = user.getCurrency().toLocale(); |
67 | |
} |
68 | |
|
69 | 0 | if (locale == null) { |
70 | 0 | locale = JammyJoesUtil.makeLocale(melati.getRequest().getHeader("accept-language")); |
71 | |
} |
72 | |
} |
73 | 0 | return locale; |
74 | |
} |
75 | |
|
76 | |
private boolean isOrderPaidOrNew() { |
77 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
78 | 0 | if (order == null) { |
79 | 0 | return true; |
80 | |
} |
81 | 0 | if (order.getStatus() == db.getOrderStatusTable().getPaid()) { |
82 | 0 | return true; |
83 | |
} |
84 | 0 | return false; |
85 | |
} |
86 | |
|
87 | |
|
88 | |
|
89 | |
public void load(Integer id) throws InstantiationPropertyException { |
90 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
91 | 0 | order = db.getShopOrderTable().getShopOrderObject(id); |
92 | 0 | setZone(order.getZone()); |
93 | 0 | setWrapping(order.getWrapping()); |
94 | 0 | setName(order.getName()); |
95 | 0 | setEmail(order.getEmail()); |
96 | 0 | setTel(order.getTel()); |
97 | 0 | setDeliveryAddress(order.getAddress()); |
98 | 0 | setTown(order.getTown()); |
99 | 0 | setPostcode(order.getPostcode()); |
100 | 0 | setMessage(order.getMessage()); |
101 | 0 | comment = order.getCustomerComment(); |
102 | 0 | deliveryName = order.getDeliveryName(); |
103 | 0 | setCountry(order.getCountry()); |
104 | 0 | setLocale(order.getCurrency().toLocale()); |
105 | 0 | setSpam(order.getSpam()); |
106 | 0 | Enumeration e = order.getItems(); |
107 | 0 | while (e.hasMoreElements()) { |
108 | 0 | ShopOrderItem line = (ShopOrderItem) e.nextElement(); |
109 | 0 | ShoppingTrolleyItem item = newItem(line.getProduct().getTroid(), null, null); |
110 | 0 | if (line.getQuantity() != null) { |
111 | 0 | item.setQuantity(line.getQuantity()); |
112 | |
} |
113 | 0 | } |
114 | 0 | } |
115 | |
|
116 | |
|
117 | |
|
118 | |
public void save() { |
119 | 0 | if (JammyJoesUtil.telesales(melati)) { |
120 | 0 | saveCatalogueOrder(); |
121 | 0 | return; |
122 | |
} |
123 | 0 | final JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
124 | 0 | User user = (User) melati.getUser(); |
125 | 0 | if (user.isGuest()) { |
126 | 0 | user = null; |
127 | |
} |
128 | 0 | user = saveOrder(db, null, db.getOrderTypeTable().getOnlineOrder()); |
129 | 0 | melati.getSession().setAttribute(HttpSessionAccessHandler.USER, user); |
130 | 0 | } |
131 | |
|
132 | |
|
133 | |
public void saveCatalogueOrder() { |
134 | 0 | final JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
135 | 0 | User operator = (User) melati.getUser(); |
136 | 0 | if (operator == null || operator.isGuest()) { |
137 | 0 | throw new AccessPoemException(); |
138 | |
} |
139 | 0 | saveOrder(db, null, db.getOrderTypeTable().getTelephoneOrder()); |
140 | 0 | order.setOperator(operator); |
141 | 0 | } |
142 | |
|
143 | |
private User saveOrder(final JammyjoesDatabase db, User user, OrderType type) { |
144 | 0 | if (user == null) { |
145 | 0 | user = (User) ((UserTable) db.getUserTable()).getEmailColumn().firstWhereEq(email); |
146 | 0 | if (user == null) { |
147 | |
|
148 | |
final User newUser; |
149 | 0 | newUser = (User) db.getUserTable().newPersistent(); |
150 | 0 | newUser.setName(name); |
151 | 0 | newUser.setEmail(email); |
152 | 0 | newUser.setTel(tel); |
153 | 0 | newUser.setAddress(address); |
154 | 0 | newUser.setTown(town); |
155 | 0 | newUser.setZone(zone); |
156 | 0 | newUser.setCountry(country); |
157 | 0 | newUser.setPostcode(postcode); |
158 | 0 | newUser.setSpam(spam); |
159 | 0 | newUser.generateDefaults(); |
160 | 0 | PoemThread.withAccessToken(AccessToken.root, new PoemTask() { |
161 | 0 | public void run() { |
162 | 0 | db.getUserTable().create(newUser); |
163 | 0 | } |
164 | |
}); |
165 | 0 | user = newUser; |
166 | 0 | } |
167 | |
} else { |
168 | |
|
169 | 0 | user.setName(name); |
170 | 0 | user.setEmail(email); |
171 | 0 | user.setTel(tel); |
172 | 0 | user.setAddress(address); |
173 | 0 | user.setTown(town); |
174 | 0 | user.setZone(zone); |
175 | 0 | user.setPostcode(postcode); |
176 | 0 | user.setCountry(country); |
177 | 0 | user.setZone(zone); |
178 | 0 | user.setSpam(spam); |
179 | |
} |
180 | 0 | if (isOrderPaidOrNew()) { |
181 | 0 | order = (ShopOrder) db.getShopOrderTable().newPersistent(); |
182 | 0 | order.setType(type); |
183 | |
} else { |
184 | 0 | order.removeItems(); |
185 | |
} |
186 | 0 | order.setUser(user); |
187 | 0 | order.setName(name); |
188 | 0 | order.setEmail(email); |
189 | 0 | order.setTel(tel); |
190 | 0 | order.setAddress(address); |
191 | 0 | order.setTown(town); |
192 | 0 | order.setZone(zone); |
193 | 0 | order.setWrapping(wrapping); |
194 | 0 | order.setPostcode(postcode); |
195 | 0 | order.setCountry(country); |
196 | 0 | order.setMessage(message); |
197 | 0 | order.setCustomerComment(comment); |
198 | 0 | order.setDeliveryName(deliveryName); |
199 | 0 | order.setStatus(db.getOrderStatusTable().getIncomplete()); |
200 | 0 | order.setAmount(convertFromUK(getTotalValue())); |
201 | 0 | order.setDelivery(convertFromUK(getTotalDeliveryValue())); |
202 | 0 | order.setAmountUK(JammyJoesUtil.roundTo2dp(getTotalValue())); |
203 | 0 | order.setDeliveryUK(JammyJoesUtil.roundTo2dp(getTotalDeliveryValue())); |
204 | 0 | order.setCurrency(getCurrency()); |
205 | 0 | order.setAffiliatepaid(false); |
206 | 0 | order.setAlert(false); |
207 | 0 | order.setComission(0d); |
208 | 0 | order.setSpam(spam); |
209 | 0 | String affiliateId = JammyJoesUtil.getCookieValue(melati, "jammyjoes"); |
210 | 0 | if (affiliateId != null) { |
211 | 0 | Affiliate affiliate = (Affiliate)db.getAffiliateTable().getObject(new Integer(affiliateId)); |
212 | 0 | order.setAffiliate(affiliate); |
213 | 0 | order.setComission(affiliate.getPercentage()); |
214 | |
} |
215 | 0 | if (order.getTroid() == null) { |
216 | 0 | db.getShopOrderTable().create(order); |
217 | |
} |
218 | 0 | for (Enumeration en = getItems(); en.hasMoreElements();) { |
219 | 0 | JammyJoesShoppingTrolleyItem item = (JammyJoesShoppingTrolleyItem) en.nextElement(); |
220 | 0 | item.save(db, order); |
221 | 0 | } |
222 | 0 | return user; |
223 | |
} |
224 | |
|
225 | |
|
226 | |
|
227 | |
|
228 | |
public boolean hasDelivery() { |
229 | 0 | if (zone == null) |
230 | 0 | return false; |
231 | 0 | return true; |
232 | |
} |
233 | |
|
234 | |
public boolean allInStock() { |
235 | 0 | boolean inStock = true; |
236 | 0 | for (Enumeration en = getItems(); en.hasMoreElements();) { |
237 | 0 | JammyJoesShoppingTrolleyItem item = (JammyJoesShoppingTrolleyItem) en.nextElement(); |
238 | 0 | if (!item.enoughStock()) |
239 | 0 | inStock = false; |
240 | 0 | } |
241 | 0 | return inStock; |
242 | |
} |
243 | |
|
244 | |
public boolean hasWrapping() { |
245 | 0 | if (wrapping == null) |
246 | 0 | return false; |
247 | 0 | WrappingTable wrappingTable = ((JammyjoesDatabase) melati.getDatabase()).getWrappingTable(); |
248 | 0 | if (wrapping.equals(wrappingTable.getNoWrapping())) |
249 | 0 | return false; |
250 | 0 | return true; |
251 | |
} |
252 | |
|
253 | |
public DeliveryZone getDeliveryZone() { |
254 | 0 | return zone; |
255 | |
} |
256 | |
|
257 | |
public Wrapping getWrapping() { |
258 | 0 | return wrapping; |
259 | |
} |
260 | |
|
261 | |
public DeliveryCarrier getDeliveryCarrier() { |
262 | 0 | return carrier; |
263 | |
} |
264 | |
|
265 | |
public Field getZones() { |
266 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
267 | 0 | Integer current = null; |
268 | 0 | if (zone != null) |
269 | 0 | current = zone.getTroid(); |
270 | 0 | return new Field(current, db.getDeliveryChargeTable().getZoneColumn()); |
271 | |
} |
272 | |
|
273 | |
public Field getWrappings() { |
274 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
275 | 0 | Integer current = null; |
276 | 0 | if (wrapping != null) |
277 | 0 | current = wrapping.getTroid(); |
278 | 0 | return new Field(current, db.getShopOrderTable().getWrappingColumn()); |
279 | |
} |
280 | |
|
281 | |
public void setFromForm(Melati melati) { |
282 | 0 | ServletTemplateContext tc = melati.getServletTemplateContext(); |
283 | 0 | setName(Form.getFormNulled(tc, "trolley_name")); |
284 | 0 | setEmail(Form.getFormNulled(tc, "trolley_email")); |
285 | 0 | setTel(Form.getFormNulled(tc, "trolley_tel")); |
286 | 0 | setDeliveryAddress(Form.getFormNulled(tc, "trolley_deliveryaddress")); |
287 | 0 | setTown(Form.getFormNulled(tc, "trolley_town")); |
288 | 0 | setCounty(Form.getFormNulled(tc, "trolley_county")); |
289 | 0 | setCountry(Form.getFormNulled(tc, "trolley_country")); |
290 | 0 | setPostcode(Form.getFormNulled(tc, "trolley_postcode")); |
291 | 0 | setMessage(Form.getFormNulled(tc, "trolley_message")); |
292 | 0 | hasDetails = true; |
293 | |
|
294 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
295 | 0 | Integer zoneId = Form.getIntegerField(tc, "field_zone"); |
296 | 0 | DeliveryZone newCode = (DeliveryZone) db.getDeliveryZoneTable().getObject(zoneId); |
297 | 0 | setZone(newCode); |
298 | 0 | Integer wrappingId = Form.getIntegerField(tc, "field_wrapping"); |
299 | 0 | WrappingTable wrappingTable = db.getWrappingTable(); |
300 | 0 | Wrapping newWrapping = (Wrapping) wrappingTable.getObject(wrappingId); |
301 | 0 | setWrapping(newWrapping); |
302 | 0 | setSpam(Form.getBooleanField(tc, "trolley_spam")); |
303 | 0 | comment = Form.getFormNulled(tc, "trolley_comment"); |
304 | 0 | deliveryName = Form.getFormNulled(tc, "trolley_deliveryName"); |
305 | 0 | } |
306 | |
|
307 | |
|
308 | |
|
309 | |
|
310 | |
public double getDeliveryValue() { |
311 | 0 | carrier = null; |
312 | 0 | if (zone == null) |
313 | 0 | return 0; |
314 | 0 | double cost = 0; |
315 | |
|
316 | 0 | if (zone.getChargeByValue() != null && zone.getChargeByValue().booleanValue()) { |
317 | 0 | cost += getDeliveryValueByValue(); |
318 | |
} else { |
319 | 0 | cost += getDeliveryValueByWeight(); |
320 | |
} |
321 | 0 | return cost; |
322 | |
} |
323 | |
public double getWrappingValue() { |
324 | 0 | if (hasWrapping()) |
325 | 0 | return WrappingTable.WRAPPING_COST; |
326 | 0 | return 0; |
327 | |
} |
328 | |
|
329 | |
public double getDeliveryValueByValue() { |
330 | 0 | carrier = null; |
331 | 0 | if (zone == null) |
332 | 0 | return 0; |
333 | 0 | DeliveryCharge thisCharge = zone.getChargeValue(getValue()); |
334 | 0 | if (thisCharge == null) |
335 | 0 | return 0; |
336 | 0 | carrier = thisCharge.getCarrier(); |
337 | 0 | return thisCharge.getCost().doubleValue(); |
338 | |
} |
339 | |
|
340 | |
public double getDeliveryValueByWeight() { |
341 | 0 | carrier = null; |
342 | 0 | if (zone == null) |
343 | 0 | return 0; |
344 | 0 | DeliveryCharge maxCharge = zone.getMaxCharge(); |
345 | 0 | if (maxCharge == null) |
346 | 0 | return 0; |
347 | 0 | double weight = getTotalWeight(); |
348 | 0 | double cost = 0; |
349 | 0 | while (weight > maxCharge.getWeight().doubleValue()) { |
350 | 0 | cost += maxCharge.getCost().doubleValue(); |
351 | 0 | weight -= maxCharge.getWeight().doubleValue(); |
352 | |
} |
353 | 0 | DeliveryCharge thisCharge = zone.getCharge(weight); |
354 | 0 | if (thisCharge == null) |
355 | 0 | return cost; |
356 | 0 | cost += thisCharge.getCost().doubleValue(); |
357 | 0 | carrier = thisCharge.getCarrier(); |
358 | 0 | return cost; |
359 | |
} |
360 | |
|
361 | |
public double getTotalWeight() { |
362 | 0 | double weight = 0; |
363 | 0 | for (Enumeration en = getItems(); en.hasMoreElements();) { |
364 | 0 | JammyJoesShoppingTrolleyItem item = (JammyJoesShoppingTrolleyItem) en.nextElement(); |
365 | 0 | weight += item.getWeight(); |
366 | 0 | } |
367 | 0 | return weight; |
368 | |
} |
369 | |
|
370 | |
|
371 | |
|
372 | |
|
373 | |
public boolean hasDiscount() { |
374 | 0 | return false; |
375 | |
} |
376 | |
|
377 | |
|
378 | |
|
379 | |
public double getDiscountRate() { |
380 | 0 | return 0; |
381 | |
} |
382 | |
|
383 | |
|
384 | |
|
385 | |
|
386 | |
public boolean hasVAT() { |
387 | 0 | return true; |
388 | |
} |
389 | |
|
390 | |
|
391 | |
|
392 | |
|
393 | |
|
394 | |
public void setDefaultDetails(Melati melati) { |
395 | 0 | if (!JammyJoesUtil.telesales(melati)) { |
396 | 0 | User user = (User) melati.getUser(); |
397 | 0 | if (user != null && !user.isGuest()) { |
398 | 0 | if (address == null) |
399 | 0 | address = user.getAddress(); |
400 | 0 | if (town == null) |
401 | 0 | town = user.getTown(); |
402 | 0 | if (zone == null) |
403 | 0 | zone = user.getZone(); |
404 | 0 | if (name == null) |
405 | 0 | name = user.getName(); |
406 | 0 | if (tel == null) |
407 | 0 | tel = user.getTel(); |
408 | 0 | if (country == null) |
409 | 0 | country = user.getCountry(); |
410 | 0 | if (postcode == null) |
411 | 0 | postcode = user.getPostcode(); |
412 | 0 | if (email == null) |
413 | 0 | email = user.getEmail(); |
414 | 0 | if (spam == null) |
415 | 0 | setSpam(user.getSpam()); |
416 | |
} |
417 | |
} |
418 | 0 | } |
419 | |
|
420 | |
public void confirmPayment(Melati melati) { |
421 | 0 | JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase(); |
422 | 0 | ServletTemplateContext context = melati.getServletTemplateContext(); |
423 | 0 | String amountString = context.getForm("amount"); |
424 | 0 | amountString = amountString.trim(); |
425 | 0 | String uniqueString = melati.getRequest().getQueryString(); |
426 | 0 | Integer orderInteger = Form.getIntegerField(context, "orderref"); |
427 | 0 | boolean error = false; |
428 | |
try { |
429 | 0 | Integer amount = new Integer(amountString); |
430 | 0 | load(orderInteger); |
431 | 0 | context.put("trolley", this); |
432 | 0 | context.put("jjutil", new JammyJoesContextUtil()); |
433 | 0 | if (!uniqueString.equals("few90kjnr32908908kjfdsa98432kjlfds9009432lk90lk43209")) { |
434 | 0 | error = true; |
435 | 0 | context.put("error", "2"); |
436 | |
} |
437 | 0 | if (!amount.equals(new Integer(getTotalValuePence()))) { |
438 | 0 | error = true; |
439 | 0 | context.put("expect", getTotalValuePence()); |
440 | 0 | context.put("paid", amountString); |
441 | 0 | context.put("error", "1"); |
442 | |
} |
443 | 0 | if (!error) { |
444 | 0 | order.setStatus(db.getOrderStatusTable().getPaid()); |
445 | 0 | for (Enumeration en = order.getItems(); en.hasMoreElements();) { |
446 | 0 | ShopOrderItem item = (ShopOrderItem) en.nextElement(); |
447 | 0 | item.setTransaction(); |
448 | 0 | } |
449 | 0 | remove(melati); |
450 | |
} |
451 | 0 | } catch (Exception e) { |
452 | 0 | error = true; |
453 | 0 | StringWriter sw = new StringWriter(); |
454 | 0 | PrintWriter pw = new PrintWriter(sw); |
455 | 0 | e.printStackTrace(pw); |
456 | 0 | context.put("error", sw); |
457 | 0 | } |
458 | 0 | } |
459 | |
|
460 | |
|
461 | |
|
462 | |
|
463 | |
public void remove(Melati melati) { |
464 | 0 | super.remove(melati); |
465 | 0 | melati.getSession().removeAttribute(HttpSessionAccessHandler.USER); |
466 | 0 | } |
467 | |
|
468 | |
public ShopOrder getOrder() { |
469 | 0 | return order; |
470 | |
} |
471 | |
|
472 | |
|
473 | |
|
474 | |
public double getTotalValue() { |
475 | 0 | return getValue() |
476 | |
+ getTotalDeliveryValue() |
477 | |
+ getDiscountValue() |
478 | |
+ getWrappingValue() |
479 | |
+ getVATValue(); |
480 | |
} |
481 | |
|
482 | |
|
483 | |
|
484 | |
public double getTotalVat() { |
485 | 0 | return roundTo2dp(getTotalValue() / 1.175 * 0.175); |
486 | |
} |
487 | |
|
488 | |
public String getWrappingDisplay() { |
489 | 0 | return displayCurrency(getWrappingValue()); |
490 | |
} |
491 | |
|
492 | |
|
493 | |
|
494 | |
public String convertFromUKandFormat(double value) { |
495 | 0 | return getCurrency().convertFromUKandFormat(value); |
496 | |
} |
497 | |
|
498 | |
|
499 | |
public double convertFromUK(double value) { |
500 | 0 | return getCurrency().convertFromUK(value); |
501 | |
} |
502 | |
|
503 | |
|
504 | |
|
505 | |
public double convertToUK(double value) { |
506 | 0 | return getCurrency().convertToUK(value); |
507 | |
} |
508 | |
|
509 | |
public ShopCurrency getCurrency(Locale locale) { |
510 | 0 | return ((JammyjoesDatabase) melati.getDatabase()).getShopCurrencyTable().getCurrency(locale); |
511 | |
} |
512 | |
|
513 | |
public ShopCurrency getCurrency() { |
514 | 0 | return getCurrency(getLocale()); |
515 | |
} |
516 | |
|
517 | |
public String displayCurrency(double value) { |
518 | 0 | return convertFromUKandFormat(value); |
519 | |
} |
520 | |
|
521 | |
public void setWrapping(Wrapping newWrapping) { |
522 | 0 | wrapping = newWrapping; |
523 | 0 | } |
524 | |
|
525 | |
public void setZone(DeliveryZone zone) { |
526 | 0 | this.zone = zone; |
527 | 0 | } |
528 | |
|
529 | |
public void setSpam(Boolean s) { |
530 | 0 | spam = s; |
531 | 0 | } |
532 | |
|
533 | |
public String getComment() { |
534 | 0 | return comment; |
535 | |
} |
536 | |
|
537 | |
public String getDeliveryName() { |
538 | 0 | return deliveryName; |
539 | |
} |
540 | |
|
541 | |
public Boolean getSpam() { |
542 | 0 | if (spam == null) |
543 | 0 | return Boolean.TRUE; |
544 | 0 | return spam; |
545 | |
} |
546 | |
|
547 | |
private JammyJoesContextUtil jjutil; |
548 | |
public JammyJoesContextUtil getJJUtil() { |
549 | 0 | if (jjutil == null) |
550 | 0 | jjutil = new JammyJoesContextUtil(); |
551 | 0 | return jjutil; |
552 | |
} |
553 | |
|
554 | |
} |